From b0afde0ad43ed70d11344352c84970312b8d08e5 Mon Sep 17 00:00:00 2001 From: Dilan Silva Date: Thu, 26 Mar 2026 14:05:08 +0530 Subject: [PATCH 001/379] feat(nexus-datasets) : introducing dynamic schema support for nexus datasets --- .../source-nexus-datasets/components.py | 152 +++++++++++++++--- .../source-nexus-datasets/manifest.yaml | 51 +++--- 2 files changed, 146 insertions(+), 57 deletions(-) diff --git a/airbyte-integrations/connectors/source-nexus-datasets/components.py b/airbyte-integrations/connectors/source-nexus-datasets/components.py index 414f61f758e1..dbc432448159 100644 --- a/airbyte-integrations/connectors/source-nexus-datasets/components.py +++ b/airbyte-integrations/connectors/source-nexus-datasets/components.py @@ -6,16 +6,17 @@ import logging from base64 import b64encode from collections import OrderedDict -from dataclasses import InitVar, dataclass +from dataclasses import InitVar, dataclass, field from datetime import date, datetime from decimal import Decimal -from typing import Any, Iterable, Mapping +from typing import Any, Iterable, Mapping, Optional from urllib.parse import parse_qs, urlencode, urljoin, urlparse, urlunparse import requests from airbyte_cdk.sources.declarative.auth.declarative_authenticator import DeclarativeAuthenticator from airbyte_cdk.sources.declarative.decoders.decoder import Decoder +from airbyte_cdk.sources.declarative.schema import SchemaLoader from airbyte_cdk.sources.declarative.types import Config @@ -51,7 +52,7 @@ def __init__(self, config: Mapping[str, Any], **kwargs): self.access_key_id = self.config.get("access_key_id", "") self.method = self.config.get("http_method", DEFAULT_HTTP_METHOD).upper() - # optional payload support (kept as-is; only used if you later add payload signing) + # optional payload support self.content_type = None self.payload = self.config.get("payload", "") self.file_content = None @@ -62,18 +63,11 @@ def __init__(self, config: Mapping[str, Any], **kwargs): self.dapi_date = "" def parse_url(self) -> None: - """ - Build the final request URL parts used in the signing base. - Important: path + query must match what the requester sends. - """ relative_path = "/".join([self.dataset_path, self.dataset_name, self.export_prefix]) full_url = urljoin(self.input_url, relative_path) parsed_url = urlparse(full_url) - # Add required query params query_params = {"mode": self.mode} - - # Merge with existing query params, if any existing_params = parse_qs(parsed_url.query) existing_params.update(query_params) @@ -108,7 +102,6 @@ def create_signing_base(self) -> bytes: if self.querystring: path_info = f"{path_info}?{self.querystring}" - # Per your original logic: lowercase everything components = OrderedDict( { "date": self.dapi_date.lower(), @@ -138,11 +131,6 @@ def sign(self, signing_base: bytes) -> bytes: class FlexibleDecoder(Decoder): """ Decoder that parses JSONL-like responses based on Content-Type. - - NOTE: This class currently yields `raw_data` as a JSON string. - If you switch schema to `raw_data` as an object (recommended), change the yield to: - yield {"raw_data": processed_record, "raw_data_string": json.dumps(processed_record)} - and update manifest schema accordingly. """ parameters: InitVar[Mapping[str, Any]] = None @@ -151,10 +139,6 @@ def __post_init__(self, parameters: Mapping[str, Any]) -> None: self.logger = logging.getLogger("airbyte") def _convert_all_to_strings(self, obj: Any) -> Any: - """ - Recursively converts all non-None values in a dictionary or list to strings. - Handles Decimal, datetime.date, datetime.datetime, and other types. - """ if obj is None: return None if isinstance(obj, (Decimal, datetime, date)): @@ -166,7 +150,6 @@ def _convert_all_to_strings(self, obj: Any) -> Any: return str(obj) def decode(self, response: requests.Response) -> Iterable[Mapping[str, Any]]: - # For 304 and 202 or not equal to 200 during data sync, raise/log with specific message if response.status_code == 304: self.logger.error("Dataset is not ready, please contact infor member services") raise AirbyteTracedException( @@ -184,6 +167,8 @@ def decode(self, response: requests.Response) -> Iterable[Mapping[str, Any]]: content_type = response.headers.get("Content-Type", "").lower() + self.logger.info(f"[FlexibleDecoder] Response Content-Type: {content_type}") + is_jsonl = any( ct in content_type for ct in ( @@ -191,6 +176,7 @@ def decode(self, response: requests.Response) -> Iterable[Mapping[str, Any]]: "application/x-jsonlines", "application/x-jsonl+json", "application/jsonl", + "application/octet-stream", # ← ADD THIS — Infor Nexus data endpoint returns this ) ) @@ -206,9 +192,123 @@ def decode(self, response: requests.Response) -> Iterable[Mapping[str, Any]]: except json.JSONDecodeError as exc: self.logger.warning("Skipping malformed JSONL line: %s - Error: %s", line.strip(), exc) continue - processed_record = self._convert_all_to_strings(record_dict) - yield { - "raw_data": processed_record, - "raw_data_string": json.dumps(processed_record), - } + yield processed_record + +@dataclass +class DynamicSchemaLoader(SchemaLoader): + """ + Fetches the schema dynamically from the Infor Nexus model metadata API. + Called during `discover` — before any data sync. + Endpoint: GET /rest/3.1/Analytics/model//fetch + Response: [{"name": "fieldName", "dataType": "String"}, ...] + """ + + config: Mapping[str, Any] + parameters: InitVar[Mapping[str, Any]] = None + + _schema_cache: Optional[dict] = field(default=None, init=False) + + DATA_TYPE_MAP: Mapping[str, str] = field(default_factory=lambda: { + "String": "string", + "string": "string", + "Text": "string", + "Char": "string", + "Integer": "integer", + "integer": "integer", + "Int": "integer", + "Long": "integer", + "Double": "number", + "Float": "number", + "Decimal": "number", + "decimal": "number", + "Boolean": "boolean", + "boolean": "boolean", + "Bool": "boolean", + "Date": "string", + "DateTime": "string", + "Object": "object", + "Array": "array", + }) + + def __post_init__(self, parameters: Mapping[str, Any]) -> None: + self.logger = logging.getLogger("airbyte") + + def _get_auth_headers(self, url: str) -> Mapping[str, Any]: + """ + Reuse NexusCustomAuthenticator's HMAC signing logic + but override the URL path to point to the schema endpoint. + """ + auth = NexusCustomAuthenticator(config=self.config) + + # Manually set the path for the schema endpoint + # instead of calling parse_url() which builds the data endpoint path + parsed = urlparse(url) + auth.path_info = parsed.path + auth.querystring = parsed.query + + # Compute signature using the schema endpoint path + signature = auth.create_authorization_header() + + return { + "Authorization": signature, + "x-dapi-date": auth.dapi_date, + "x-nexus-api-key": auth.api_key, + "Content-Type": "application/json", + } + + def get_json_schema(self) -> Mapping[str, Any]: + if self._schema_cache: + return self._schema_cache + + dataset_name = self.config.get("dataset_name", "") + base_url = self.config.get("base_url", "").rstrip("/") + + url = f"{base_url}/rest/3.1/Analytics/model/PurchaseOrderTest/fetch" + + self.logger.info(f"Fetching schema from: {url}") + + try: + headers = self._get_auth_headers(url) + response = requests.get(url, headers=headers) + response.raise_for_status() + except requests.exceptions.RequestException as e: + self.logger.error(f"Failed to fetch schema from {url}: {e}") + raise + + response_json = response.json() + self.logger.info(f"Schema API raw response: {response_json}") + + # Navigate to the nested fields list: response -> data -> field + data = response_json.get("data", {}) + fields = data.get("field", []) + + self.logger.info(f"Found {len(fields)} fields in schema response") + + properties = {} + for f in fields: + if not isinstance(f, dict): + self.logger.warning(f"Skipping unexpected field entry: {f}") + continue + + field_name = f.get("name") + + # No dataType in the response — default all fields to string // Still the change is in the RCTQ + # If dataType appears in future, DATA_TYPE_MAP will handle it + field_type = self.DATA_TYPE_MAP.get(f.get("dataType", ""), "string") + + if field_name: + properties[field_name] = {"type": [field_type, "null"]} + self.logger.info(f"Mapped field: {field_name} -> {field_type}") + + # Add known fields not returned by the schema API, this field does not exists in the schema but this is the change indicator field that is used by the connector to identify if the record is new or updated, this field is added as part of the decoder logic. + properties["zzz_ChangeCode"] = {"type": ["string", "null"]} + self._schema_cache = { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "additionalProperties": True, + "properties": properties, + } + + self.logger.info(f"Schema loaded successfully with {len(properties)} fields.") + return self._schema_cache \ No newline at end of file diff --git a/airbyte-integrations/connectors/source-nexus-datasets/manifest.yaml b/airbyte-integrations/connectors/source-nexus-datasets/manifest.yaml index b4ae71097a46..66220a89df19 100644 --- a/airbyte-integrations/connectors/source-nexus-datasets/manifest.yaml +++ b/airbyte-integrations/connectors/source-nexus-datasets/manifest.yaml @@ -1,5 +1,4 @@ version: 6.5.0 -#6.6.0 # Ensure this matches your pyproject.toml and base image type: DeclarativeSource @@ -9,21 +8,19 @@ check: - "datasets" definitions: - # Base Requester with Authentication base_requester: type: HttpRequester url_base: "{{ config['base_url'] }}" http_method: GET authenticator: type: CustomAuthenticator - class_name: source_declarative_manifest.components.NexusCustomAuthenticator # Ensure this Python class exists and is correctly implemented + class_name: source_declarative_manifest.components.NexusCustomAuthenticator config: "{{ config }}" streams: - type: DeclarativeStream - name: datasets # Name of your data stream + name: datasets $parameters: - # Dynamic path construction using config properties path: "rest/3.1/analytics/dataset/{{ config['dataset_name'] }}/export?mode={{ config.get('mode', 'Full') }}" retriever: type: SimpleRetriever @@ -31,23 +28,22 @@ streams: type: RecordSelector extractor: type: DpathExtractor - field_path: [] # Assuming the records are at the root of the response, adjust if nested + field_path: [] requester: - $ref: "#/definitions/base_requester" # Reference the shared requester + $ref: "#/definitions/base_requester" decoder: - type: CustomDecoder # Now using CustomDecoder - class_name: source_declarative_manifest.components.FlexibleDecoder # Pointing to your new Python class - $parameters: # Parameters passed to FlexibleDecoder's __init__ - # file_type is removed from here as it's inferred from Content-Type header - config: "{{ config }}" # Explicitly pass the config object (REQUIRED for 6.36.2 CustomDecoder) + type: CustomDecoder + class_name: source_declarative_manifest.components.FlexibleDecoder + $parameters: + config: "{{ config }}" schema_loader: - type: InlineSchemaLoader - schema: - $ref: "#/schemas/datasets" # Reference the schema defined below + type: CustomSchemaLoader + class_name: "source_declarative_manifest.components.DynamicSchemaLoader" + config: "{{ config }}" spec: type: Spec - documentation_url: https://docs.airbyte.com/integrations/sources/nexus-datasets # Replace with your connector's documentation URL + documentation_url: https://docs.airbyte.com/integrations/sources/nexus-datasets connection_specification: title: Infor Nexus Datasets Spec type: object @@ -66,52 +62,45 @@ spec: type: "string" description: "The base URL of the Infor Nexus datasets API." pattern: "^https?://[\\w.-]+(:\\d+)?(/[\\w.-]+)*/?$" + default: "https://demo.infornexus.com" order: 1 user_id: title: "User ID" type: "string" description: "The user ID for the Infor Nexus API." + default: "DataApiAgent@3717989018023079" order: 5 access_key_id: title: "Access Key ID" type: "string" description: "The access key ID for the Infor Nexus API." + default: "1001jcnZegkh5lchZfn" order: 6 secret_key: title: "Secret Key" type: "string" description: "The secret key for HMAC authentication." + default: "x5io4dlewi7s4dkqn4nw5iihhybw3fyr6nljzljb5yswph6zy2wwz5wibva2wh6r4q7ytulkem6ddbzm2qzyyng6v4iiewfsh2uvvli" order: 7 api_key: title: "API Key" type: string description: "The Infor Data API Key." + default: "59821a6586259964c0337f743ecae1a89c50d054" order: 8 dataset_name: title: "Dataset Name" type: string description: "The name of the dataset to export." + default: "PurchaseOrderTestExport" order: 2 mode: type: string title: Infor Streaming Mode - description: "Infor Streaming mode (Full or Incremental). https://developer.infornexus.com/api/version-3.1-api-methods" + description: "Infor Streaming mode (Full or Incremental)." enum: - Full - Incremental default: Full order: 4 - additionalProperties: true # Set to false if you want to strictly define CSV options -schemas: - datasets: - type: object - $schema: http://json-schema.org/draft-07/schema# - additionalProperties: true # IMPORTANT: Set to false if you only want the 'raw_data' column - properties: - raw_data: - type: ["object", "null"] - additionalProperties: true - description: "Record payload as JSON object." - raw_data_string: - type: ["string", "null"] - description: "Record payload as JSON string (optional)." + additionalProperties: true \ No newline at end of file From 852c7fe40491856830da90da5f0eaac6ed74ea89 Mon Sep 17 00:00:00 2001 From: Dilan Silva Date: Mon, 6 Apr 2026 10:25:06 +0530 Subject: [PATCH 002/379] refactor(nexus-datasets) : Dynamic schema discovery implementation --- .../source-nexus-datasets/components.py | 241 ++++++++++-------- .../source-nexus-datasets/manifest.yaml | 12 +- docs/integrations/sources/nexus-datasets.md | 192 +++++++------- 3 files changed, 239 insertions(+), 206 deletions(-) diff --git a/airbyte-integrations/connectors/source-nexus-datasets/components.py b/airbyte-integrations/connectors/source-nexus-datasets/components.py index dbc432448159..a061b4cd7c84 100644 --- a/airbyte-integrations/connectors/source-nexus-datasets/components.py +++ b/airbyte-integrations/connectors/source-nexus-datasets/components.py @@ -9,25 +9,42 @@ from dataclasses import InitVar, dataclass, field from datetime import date, datetime from decimal import Decimal -from typing import Any, Iterable, Mapping, Optional +from typing import Any, ClassVar, Iterable, Mapping, Optional from urllib.parse import parse_qs, urlencode, urljoin, urlparse, urlunparse import requests +from airbyte_cdk.models import FailureType from airbyte_cdk.sources.declarative.auth.declarative_authenticator import DeclarativeAuthenticator from airbyte_cdk.sources.declarative.decoders.decoder import Decoder from airbyte_cdk.sources.declarative.schema import SchemaLoader from airbyte_cdk.sources.declarative.types import Config +from airbyte_cdk.utils.traced_exception import AirbyteTracedException DATASET_PATH = "rest/3.1/analytics/dataset" +SCHEMA_PATH = "rest/3.1/Analytics/model" EXPORT_PREFIX = "export" DEFAULT_MODE = "Full" DEFAULT_HTTP_METHOD = "GET" +# Injected by the connector — not returned by the Nexus schema API. +# Indicates whether a record is new or updated during incremental syncs. +INJECTED_FIELD_NAME = "zzz_ChangeCode" + @dataclass class NexusCustomAuthenticator(DeclarativeAuthenticator): + """ + Handles HMAC authentication for the Infor Nexus Data API. + + Every request is independently signed using a cryptographic hash of the + request path, date, method, and payload. The resulting signature is + submitted in the Authorization header. + + See: https://developer.infornexus.com/api/authentication-choices/hmac + """ + config: Config def __init__(self, config: Mapping[str, Any], **kwargs): @@ -36,40 +53,37 @@ def __init__(self, config: Mapping[str, Any], **kwargs): self.kwargs = kwargs self.logger = logging.getLogger("airbyte") - # constants (removed from client config) self.dataset_path = DATASET_PATH self.export_prefix = EXPORT_PREFIX - # user/config-driven values self.dataset_name = self.config.get("dataset_name", "") self.mode = self.config.get("mode", DEFAULT_MODE) self.input_url = self.config.get("base_url", "") - # auth and request properties (snake_case) self.user_id = self.config.get("user_id", "") self.secret_access_key = self.config.get("secret_key", "") self.api_key = self.config.get("api_key", "") self.access_key_id = self.config.get("access_key_id", "") self.method = self.config.get("http_method", DEFAULT_HTTP_METHOD).upper() - # optional payload support self.content_type = None self.payload = self.config.get("payload", "") self.file_content = None - # computed during signing self.path_info = "" self.querystring = "" self.dapi_date = "" def parse_url(self) -> None: + """Build the data endpoint URL and extract path and query components for signing.""" relative_path = "/".join([self.dataset_path, self.dataset_name, self.export_prefix]) full_url = urljoin(self.input_url, relative_path) parsed_url = urlparse(full_url) - query_params = {"mode": self.mode} + # Preserve any existing query params and append the mode param as a list + # to keep consistent list-format values with parse_qs output. existing_params = parse_qs(parsed_url.query) - existing_params.update(query_params) + existing_params["mode"] = [self.mode] new_query = urlencode(existing_params, doseq=True) final_url = urlunparse(parsed_url._replace(query=new_query)) @@ -79,9 +93,18 @@ def parse_url(self) -> None: self.querystring = parsed_final_url.query def get_auth_header(self) -> Mapping[str, Any]: + """Return signed auth headers for the data endpoint.""" self.parse_url() - signature = self.create_authorization_header() + return self._build_headers() + + def get_auth_header_for_path(self, path: str, querystring: str = "") -> Mapping[str, Any]: + self.path_info = path + self.querystring = querystring + return self._build_headers() + def _build_headers(self) -> Mapping[str, Any]: + """Compute the HMAC signature and assemble the auth header dict.""" + signature = self.create_authorization_header() return { "Authorization": signature, "x-dapi-date": self.dapi_date, @@ -123,14 +146,18 @@ def set_date(self) -> None: def sign(self, signing_base: bytes) -> bytes: secret = self.secret_access_key.encode("utf-8") - digest = hmac.new(secret, signing_base, hashlib.sha256).digest() + digest = hmac.new(key=secret, msg=signing_base, digestmod=hashlib.sha256).digest() return b64encode(digest) @dataclass class FlexibleDecoder(Decoder): """ - Decoder that parses JSONL-like responses based on Content-Type. + Decodes JSONL-like responses from the Infor Nexus data endpoint. + + Handles the API's varied Content-Type headers (including + application/octet-stream, which Infor Nexus uses for data responses) + and converts all field values to strings for downstream compatibility. """ parameters: InitVar[Mapping[str, Any]] = None @@ -151,38 +178,39 @@ def _convert_all_to_strings(self, obj: Any) -> Any: def decode(self, response: requests.Response) -> Iterable[Mapping[str, Any]]: if response.status_code == 304: - self.logger.error("Dataset is not ready, please contact infor member services") raise AirbyteTracedException( - message="Dataset is not ready, please contact infor member services", failure_type=FailureType.config_error + message="Dataset is not ready, please contact Infor member services.", + failure_type=FailureType.config_error, ) - if response.status_code == 202: - self.logger.error("Dataset is not ready - try again later") - raise AirbyteTracedException(message="Dataset is not ready, try again later", failure_type=FailureType.config_error) - if response.status_code != 200: - self.logger.error("Unexpected status code: %s", response.status_code) + elif response.status_code == 202: raise AirbyteTracedException( - message=f"Unexpected status code: {response.status_code} please contact infor member services", + message="Dataset is not ready — try again later.", + failure_type=FailureType.config_error, + ) + elif response.status_code != 200: + raise AirbyteTracedException( + message=( + f"Unexpected status code {response.status_code}. " + "Please contact Infor member services." + ), failure_type=FailureType.config_error, ) content_type = response.headers.get("Content-Type", "").lower() - - self.logger.info(f"[FlexibleDecoder] Response Content-Type: {content_type}") - - is_jsonl = any( - ct in content_type - for ct in ( - "application/json", - "application/x-jsonlines", - "application/x-jsonl+json", - "application/jsonl", - "application/octet-stream", # ← ADD THIS — Infor Nexus data endpoint returns this - ) + self.logger.info("Response Content-Type: %s", content_type) + + supported_content_types = ( + "application/json", + "application/x-jsonlines", + "application/x-jsonl+json", + "application/jsonl", + "application/octet-stream", # Infor Nexus data endpoint returns this ) - if not is_jsonl: - self.logger.error("Unsupported or unrecognized Content-Type: %s. Cannot decode response.", content_type) - raise ValueError(f"Unsupported or unrecognized Content-Type: {content_type}") + if not any(ct in content_type for ct in supported_content_types): + raise ValueError( + f"Unsupported or unrecognized Content-Type: {content_type}. Cannot decode response." + ) for line in response.content.decode("utf-8").splitlines(): if not line.strip(): @@ -190,18 +218,23 @@ def decode(self, response: requests.Response) -> Iterable[Mapping[str, Any]]: try: record_dict = json.loads(line) except json.JSONDecodeError as exc: - self.logger.warning("Skipping malformed JSONL line: %s - Error: %s", line.strip(), exc) + self.logger.warning("Skipping malformed JSONL line: %s — Error: %s", line.strip(), exc) continue - processed_record = self._convert_all_to_strings(record_dict) - yield processed_record + yield self._convert_all_to_strings(record_dict) + @dataclass class DynamicSchemaLoader(SchemaLoader): """ - Fetches the schema dynamically from the Infor Nexus model metadata API. - Called during `discover` — before any data sync. - Endpoint: GET /rest/3.1/Analytics/model//fetch - Response: [{"name": "fieldName", "dataType": "String"}, ...] + Fetches the stream schema dynamically from the Infor Nexus model metadata API. + + Called during `discover` — before any data sync begins. + Endpoint: GET /rest/3.1/Analytics/model//fetch + Response shape: {"data": {"field": [{"name": "fieldName", "dataType": "String"}, ...]}} + + An additional field (_nexus_ChangeCode) is injected into every schema to + support incremental sync — it is not returned by the schema API but is + present in data responses as a change indicator. """ config: Mapping[str, Any] @@ -209,100 +242,98 @@ class DynamicSchemaLoader(SchemaLoader): _schema_cache: Optional[dict] = field(default=None, init=False) - DATA_TYPE_MAP: Mapping[str, str] = field(default_factory=lambda: { - "String": "string", - "string": "string", - "Text": "string", - "Char": "string", - "Integer": "integer", - "integer": "integer", - "Int": "integer", - "Long": "integer", - "Double": "number", - "Float": "number", - "Decimal": "number", - "decimal": "number", - "Boolean": "boolean", - "boolean": "boolean", - "Bool": "boolean", - "Date": "string", - "DateTime": "string", - "Object": "object", - "Array": "array", - }) + DATA_TYPE_MAP: ClassVar[Mapping[str, Any]] = { + "TEXT": {"type": ["string", "null"]}, + "PICKLIST": {"type": ["string", "null"]}, + "CHAR": {"type": ["string", "null"]}, + "VARCHAR": {"type": ["string", "null"]}, + "DATE": {"type": ["string", "null"], "format": "date"}, + "DATETIME": {"type": ["string", "null"], "format": "date-time"}, + "TIMESTAMP": {"type": ["string", "null"], "format": "date-time"}, + "INTEGER": {"type": ["integer", "null"]}, + "LONG": {"type": ["integer", "null"]}, + "DECIMAL": {"type": ["number", "null"]}, + "NUMERIC": {"type": ["number", "null"]}, + "FLOAT": {"type": ["number", "null"]}, + "DOUBLE": {"type": ["number", "null"]}, + "BOOLEAN": {"type": ["boolean", "null"]}, + "OBJECT": {"type": ["object", "null"]}, + "ARRAY": {"type": ["array", "null"]}, + } def __post_init__(self, parameters: Mapping[str, Any]) -> None: self.logger = logging.getLogger("airbyte") def _get_auth_headers(self, url: str) -> Mapping[str, Any]: - """ - Reuse NexusCustomAuthenticator's HMAC signing logic - but override the URL path to point to the schema endpoint. - """ + """Sign a request to the given URL using the authenticator's public API.""" auth = NexusCustomAuthenticator(config=self.config) - - # Manually set the path for the schema endpoint - # instead of calling parse_url() which builds the data endpoint path parsed = urlparse(url) - auth.path_info = parsed.path - auth.querystring = parsed.query - - # Compute signature using the schema endpoint path - signature = auth.create_authorization_header() - - return { - "Authorization": signature, - "x-dapi-date": auth.dapi_date, - "x-nexus-api-key": auth.api_key, - "Content-Type": "application/json", - } + return auth.get_auth_header_for_path( + path=parsed.path, + querystring=parsed.query, + ) def get_json_schema(self) -> Mapping[str, Any]: - if self._schema_cache: + # Return cached schema on subsequent calls — avoids redundant API requests. + if self._schema_cache is not None: return self._schema_cache - dataset_name = self.config.get("dataset_name", "") + dataset_model_name = self.config.get("dataset_model_name", "") base_url = self.config.get("base_url", "").rstrip("/") + url = f"{base_url}/{SCHEMA_PATH}/{dataset_model_name}/fetch" - url = f"{base_url}/rest/3.1/Analytics/model/PurchaseOrderTest/fetch" - - self.logger.info(f"Fetching schema from: {url}") + self.logger.info("Fetching schema from: %s", url) try: headers = self._get_auth_headers(url) response = requests.get(url, headers=headers) + + if response.status_code == 404: + raise AirbyteTracedException( + message=( + f"Dataset Model Name '{dataset_model_name}' not found in Infor Nexus. " + "Please check the 'Dataset Model Name' in your connector configuration." + ), + failure_type=FailureType.config_error, + ) + response.raise_for_status() - except requests.exceptions.RequestException as e: - self.logger.error(f"Failed to fetch schema from {url}: {e}") + + except AirbyteTracedException: raise + except requests.exceptions.RequestException as exc: + raise AirbyteTracedException( + message=( + f"Failed to fetch schema for Dataset Model Name '{dataset_model_name}' " + f"from Infor Nexus. Error: {exc}" + ), + failure_type=FailureType.system_error, + ) from exc response_json = response.json() - self.logger.info(f"Schema API raw response: {response_json}") - - # Navigate to the nested fields list: response -> data -> field - data = response_json.get("data", {}) - fields = data.get("field", []) - - self.logger.info(f"Found {len(fields)} fields in schema response") + fields = response_json.get("data", {}).get("field", []) + self.logger.info("Found %d fields in schema response.", len(fields)) properties = {} for f in fields: if not isinstance(f, dict): - self.logger.warning(f"Skipping unexpected field entry: {f}") + self.logger.warning("Skipping unexpected field entry: %s", f) continue field_name = f.get("name") - - # No dataType in the response — default all fields to string // Still the change is in the RCTQ - # If dataType appears in future, DATA_TYPE_MAP will handle it - field_type = self.DATA_TYPE_MAP.get(f.get("dataType", ""), "string") + nexus_data_type = f.get("dataType", "") if field_name: - properties[field_name] = {"type": [field_type, "null"]} - self.logger.info(f"Mapped field: {field_name} -> {field_type}") + # Fall back to string for any unmapped Nexus data types. + properties[field_name] = self.DATA_TYPE_MAP.get( + nexus_data_type, + {"type": ["string", "null"]}, + ) + + # Inject the change indicator field. Present in data responses but absent + # from the schema API — used by the connector to detect new/updated records. + properties[INJECTED_FIELD_NAME] = {"type": ["string", "null"]} - # Add known fields not returned by the schema API, this field does not exists in the schema but this is the change indicator field that is used by the connector to identify if the record is new or updated, this field is added as part of the decoder logic. - properties["zzz_ChangeCode"] = {"type": ["string", "null"]} self._schema_cache = { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", @@ -310,5 +341,5 @@ def get_json_schema(self) -> Mapping[str, Any]: "properties": properties, } - self.logger.info(f"Schema loaded successfully with {len(properties)} fields.") + self.logger.info("Schema loaded successfully with %d fields.", len(properties)) return self._schema_cache \ No newline at end of file diff --git a/airbyte-integrations/connectors/source-nexus-datasets/manifest.yaml b/airbyte-integrations/connectors/source-nexus-datasets/manifest.yaml index 66220a89df19..693a91f81ca4 100644 --- a/airbyte-integrations/connectors/source-nexus-datasets/manifest.yaml +++ b/airbyte-integrations/connectors/source-nexus-datasets/manifest.yaml @@ -55,6 +55,7 @@ spec: - secret_key - api_key - dataset_name + - dataset_model_name additionalProperties: true properties: base_url: @@ -62,38 +63,37 @@ spec: type: "string" description: "The base URL of the Infor Nexus datasets API." pattern: "^https?://[\\w.-]+(:\\d+)?(/[\\w.-]+)*/?$" - default: "https://demo.infornexus.com" order: 1 user_id: title: "User ID" type: "string" description: "The user ID for the Infor Nexus API." - default: "DataApiAgent@3717989018023079" order: 5 access_key_id: title: "Access Key ID" type: "string" description: "The access key ID for the Infor Nexus API." - default: "1001jcnZegkh5lchZfn" order: 6 secret_key: title: "Secret Key" type: "string" description: "The secret key for HMAC authentication." - default: "x5io4dlewi7s4dkqn4nw5iihhybw3fyr6nljzljb5yswph6zy2wwz5wibva2wh6r4q7ytulkem6ddbzm2qzyyng6v4iiewfsh2uvvli" order: 7 api_key: title: "API Key" type: string description: "The Infor Data API Key." - default: "59821a6586259964c0337f743ecae1a89c50d054" order: 8 dataset_name: title: "Dataset Name" type: string description: "The name of the dataset to export." - default: "PurchaseOrderTestExport" order: 2 + dataset_model_name: + title: "Dataset Model Name" + type: string + description: "The name of the dataset model to export." + order: 3 mode: type: string title: Infor Streaming Mode diff --git a/docs/integrations/sources/nexus-datasets.md b/docs/integrations/sources/nexus-datasets.md index 5c0703860639..21f961973ec4 100644 --- a/docs/integrations/sources/nexus-datasets.md +++ b/docs/integrations/sources/nexus-datasets.md @@ -1,132 +1,134 @@ -# Nexus Datasets -Nexus datasets is a solution to sync up with the current nexus data sets API. -Data can be extracted from the nexus API after providing the required data in the config. -Data set name should be provided aliong with the other details to sync the data. -[API Documentation](https://developer.gtnexus.com/) +# Nexus Datasets Source Connector + +Syncs data from the [GT Nexus Data API](https://developer.gtnexus.com/) into Airbyte. The connector authenticates using HMAC signatures and supports both full and incremental sync modes. + +--- ## Prerequisites -- Nexus customer organization with Data Mesh rights -- Export data set created in the customer organization -- Data API Agent user configured in the customer organization +Before configuring the connector, ensure the following are in place in your Nexus environment: -## Airbyte OSS and Airbyte Cloud +- A Nexus customer organization with **Data Mesh** rights +- An **Export Data Set** created within that organization +- A **Data API Agent (DAPI) user** configured with the appropriate privileges -- Name of the data set to be synced -- Data API Agent user name / Cliend access key ID / Secret key for the Data API Agent user -- Data Key (API Key) for the customer organization +--- -## Setup guide +## Nexus Setup -### Step 1: Nexus Configuration +### 1. Create a Customer Organization -#### Step 1.1: Create Nexus Customer Organization +Create a customer organization in the Nexus platform if one does not already exist. -1. Create customer organization in the nexus platform +### 2. Configure Data Mesh -#### Step 1.2: Configure Data Mesh in the Customer Organization +1. Log into the **admin side** of the Nexus application. +2. Set up the **Data Mesh rule** for the organization. +3. Create one or more users with **Data Mesh privileges**. +4. Verify that the user can log into the Nexus platform. -1. Log into the admin side of the nexus application -2. Set up the Data Mesh rule for the organization -3. Create users with the Data Mesh previledges -4. Make sure this user can be logged in to the nexus platfrom +### 3. Create an Export Data Pipeline -#### Step 1.3: Configure export data pipeline in the Nexus +1. Log into the Nexus platform as the Data Mesh user created above. +2. Navigate to **Analytics → Data Mesh Console**. +3. Click the **Export** tab to view exportable data sets. +4. Click **Create** and build a new export pipeline using an existing model. +5. Note the **Model Name** — you will need it during connector configuration. +6. Schedule the data set to run. -1. Log into the nexus platform using created user in the step 2 -2. Go to **Analytics** » **Data Mesh Console** -3. Click on **Export** tab to go into the exportable data sets -4. Click **Create** to create new export pipeline using the existing models -5. Schedule the data set to run +### 4. Collect Configuration Values -#### Step 1.4: Summary +Before setting up the connector, gather the following from your Nexus environment: -- Base URL for the nexus platform -- Nexus customer organization with relevant user with rights -- Export data set -- Data API Agent user (DAPI user) -- DAPI user id / access key id / secret key -- Data key (API key) +| Value | Description | +|---|---| +| Base URL | The base URL of your Nexus platform instance | +| Dataset Name | The name of the data set to sync | +| Model Name | The model name associated with the export pipeline | +| DAPI User ID | The user ID for the Data API Agent user | +| Access Key ID | The access key ID for the DAPI user | +| Secret Key | The secret key for the DAPI user | +| Data Key (API Key) | The API key for the customer organization | -### Step 2: Set up the source connector in Airbyte +--- -#### For Airbyte Cloud: +## Connector Setup -1. [Log into your Airbyte Cloud](https://cloud.airbyte.com/workspaces) account. -2. In the left navigation bar, click **Sources**. In the top-right corner, click **+ new source**. -3. On the source setup page, select **Nexus Datasets** from the Source type dropdown and enter a name for this connector. -4. Add **Base URL** -5. Add **Dataset Name** -6. Add **Infor Streaming Mode (default Full)** -7. Add **User ID** -8. Add **Access Key ID** -9. Add **Secret Key** -10. Add **API Key** -11. Click `Set up source` +### Airbyte Cloud -#### For Airbyte OSS: +1. Log into [Airbyte Cloud](https://cloud.airbyte.com/workspaces). +2. In the left navigation, click **Sources**, then **+ New source** in the top-right. +3. Select **Nexus Datasets** from the Source type dropdown and give the connector a name. +4. Fill in all configuration fields (see [Configuration](#configuration) below). +5. Click **Set up source**. -1. [Log into your Airbyte Cloud](https://cloud.airbyte.com/workspaces) account. -2. In the left navigation bar, click **Sources**. In the top-right corner, click **+ new source**. -3. On the source setup page, select **Nexus Datasets** from the Source type dropdown and enter a name for this connector. -4. Add **Base URL** -5. Add **Dataset Name** -6. Add **Infor Streaming Mode (default Full)** -7. Add **User ID** -8. Add **Access Key ID** -9. Add **Secret Key** -10. Add **API Key** -11. Click `Set up source`. +### Airbyte OSS -### Configuration +1. Open your local Airbyte instance. +2. In the left navigation, click **Sources**, then **+ New source** in the top-right. +3. Select **Nexus Datasets** from the Source type dropdown and give the connector a name. +4. Fill in all configuration fields (see [Configuration](#configuration) below). +5. Click **Set up source**. -| Input | Type | Description | Default Value | -|-------|------|-------------|---------------| -| `base_url` | `string` | Base URL. Enter base url for your data set | | -| `dataset_name` | `string` | Name of the dataset. Enter dataset name to be synced | | -| `infor_streaming_mode` | `string` | Name of the dataset. Enter dataset name to be synced | | -| `user_id` | `string` | Data API agent user ID. Enter DAPI agent user id configured in the nexus | | -| `access_key_id` | `string` | Access key ID. Enter access key ID for the DAPI agent user | | -| `secret_key` | `string` | Secret key. Enter secret key for the DAPI agent user | | -| `api_key` | `string` | Data API key. Enter data API key for the organization | | +--- +## Configuration +| Field | Type | Description | Default | +|---|---|---|---| +| `base_url` | string | Base URL of the Nexus platform instance | — | +| `dataset_name` | string | Name of the data set to sync | — | +| `dataset_model_name` | string | Model name for the export data pipeline | — | +| `infor_streaming_mode` | string | Sync mode: `full` or `incremental` | `full` | +| `user_id` | string | DAPI Agent user ID | — | +| `access_key_id` | string | Access key ID for the DAPI Agent user | — | +| `secret_key` | string | Secret key for the DAPI Agent user | — | +| `api_key` | string | Data API key for the organization | — | -### Supported sync modes +--- -The Nexus Datasets source connector supports the following [sync modes](https://docs.airbyte.com/cloud/core-concepts#connection-sync-modes): +## Supported Sync Modes -- Full Refresh -- Incremental +| Mode | Supported | +|---|---| +| Full Refresh | ✅ | +| Incremental | ✅ | -### Streams -| Stream Name | Primary Key | Pagination | Supports Full Sync | Supports Incremental | -|-------------|-------------|------------|---------------------|----------------------| -| datasets | ❌ | DefaultPaginator | ✅ | ✅ | +--- -### Custom Components -NexusCustomAuthenticator is a primary component which handles the HMAC authentication for nexus API. +## Streams -HMAC stands for Hash-based Message Authentication Code. In HMAC authentication, every request is independently established using a cryptographic hash function. For each API request, the client computes a hashed "signature" using a secret key and submits it in the Authorization header. +| Stream | Primary Key | Pagination | Full Refresh | Incremental | +|---|---|---|---|---| +| `datasets` | — | DefaultPaginator | ✅ | ✅ | -Please refer https://developer.infornexus.com/api/authentication-choices/hmac for more details to get the data to calculate the HMAC signature. +--- -### Error Codes -200 : Data set is ready to stream -202 : Data set is not ready but try again later. -304 : Data set is not ready, check the source again. +## Authentication +The connector uses **HMAC (Hash-based Message Authentication Code)** authentication, implemented in the `NexusCustomAuthenticator` component. For each API request, a cryptographic signature is computed using the secret key and submitted in the `Authorization` header — no session tokens or cookies are involved. -## Changelog +For full details on computing the HMAC signature, refer to the [Infor Nexus HMAC authentication documentation](https://developer.infornexus.com/api/authentication-choices/hmac). + +--- -
- Expand to review +## API Response Codes -| Version | Date | Pull Request | Subject | -|------------------|-------------------|--------------|----------------| -| 0.1.3 | 2026-02-17 | [73548](https://github.com/airbytehq/airbyte/pull/73548) | Update dependencies | -| 0.1.2 | 2026-02-10 | [73030](https://github.com/airbytehq/airbyte/pull/73030) | Update dependencies | -| 0.1.1 | 2026-02-03 | [72789](https://github.com/airbytehq/airbyte/pull/72789) | Add missing registryOverrides to metadata.yaml | -| 0.1.0 | 2025-09-30 | [69349](https://github.com/airbytehq/airbyte/pull/69349) | Nexus datasets connector first version | +| Code | Meaning | +|---|---| +| `200` | Data set is ready to stream | +| `202` | Data set is not yet ready — retry later | +| `304` | Data set is not ready — check the data source | +| `404` | Not found — verify your configuration values | + +--- + +## Changelog -
+| Version | Date | Pull Request | Notes | +|---|---|---|---| +| 0.1.4 | 2026-04-06 | | Dynamic schema discovery | +| 0.1.3 | 2026-02-17 | [#73548](https://github.com/airbytehq/airbyte/pull/73548) | Update dependencies | +| 0.1.2 | 2026-02-10 | [#73030](https://github.com/airbytehq/airbyte/pull/73030) | Update dependencies | +| 0.1.1 | 2026-02-03 | [#72789](https://github.com/airbytehq/airbyte/pull/72789) | Add missing `registryOverrides` to `metadata.yaml` | +| 0.1.0 | 2025-09-30 | [#69349](https://github.com/airbytehq/airbyte/pull/69349) | Initial release | From 89cb02235e28015c0e0d65338cf84b2d40ae07c0 Mon Sep 17 00:00:00 2001 From: "octavia-bot[bot]" <108746235+octavia-bot[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 08:23:11 +0000 Subject: [PATCH 003/379] docs: sync agent connector docs from airbyte-agent-connectors repo (#75488) Co-authored-by: ian-at-airbyte <187576150+ian-at-airbyte@users.noreply.github.com> --- docs/ai-agents/connectors/linear/README.md | 6 +++--- docs/ai-agents/connectors/linear/REFERENCE.md | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/ai-agents/connectors/linear/README.md b/docs/ai-agents/connectors/linear/README.md index 1bb8d798219e..821349235dde 100644 --- a/docs/ai-agents/connectors/linear/README.md +++ b/docs/ai-agents/connectors/linear/README.md @@ -121,7 +121,7 @@ See the official [Linear API reference](https://linear.app/developers/graphql). ## Version information -- **Package version:** 0.19.117 -- **Connector version:** 0.1.11 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Package version:** 0.19.118 +- **Connector version:** 0.1.12 +- **Generated with Connector SDK commit SHA:** 128ac5a7ba99d76a190accd255caf509ff09afde - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/linear/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/linear/REFERENCE.md b/docs/ai-agents/connectors/linear/REFERENCE.md index 4ffa7bac0e3a..16e629307755 100644 --- a/docs/ai-agents/connectors/linear/REFERENCE.md +++ b/docs/ai-agents/connectors/linear/REFERENCE.md @@ -60,6 +60,8 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | `state` | `object \| any` | | | `priority` | `number \| any` | | | `assignee` | `object \| any` | | +| `team` | `object \| any` | | +| `project` | `object \| any` | | | `createdAt` | `string` | | | `updatedAt` | `string` | | From 7419dc25cd5905c8eb0261b8188bf87064cadc3d Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 14:54:01 +0200 Subject: [PATCH 004/379] feat(source-marketo): add sfdcId and sfdcName to programs stream schema (#75461) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: gl_anatolii.yatsuk --- .../connectors/source-marketo/metadata.yaml | 2 +- .../connectors/source-marketo/pyproject.toml | 2 +- .../source-marketo/source_marketo/schemas/programs.json | 8 ++++++++ docs/integrations/sources/marketo.md | 1 + 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-marketo/metadata.yaml b/airbyte-integrations/connectors/source-marketo/metadata.yaml index 22da530d69c1..70d20474608d 100644 --- a/airbyte-integrations/connectors/source-marketo/metadata.yaml +++ b/airbyte-integrations/connectors/source-marketo/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: api connectorType: source definitionId: 9e0556f4-69df-4522-a3fb-03264d36b348 - dockerImageTag: 1.6.1 + dockerImageTag: 1.6.2 dockerRepository: airbyte/source-marketo documentationUrl: https://docs.airbyte.com/integrations/sources/marketo githubIssueLabel: source-marketo diff --git a/airbyte-integrations/connectors/source-marketo/pyproject.toml b/airbyte-integrations/connectors/source-marketo/pyproject.toml index 37aa2008d49e..0a2c9c90f874 100644 --- a/airbyte-integrations/connectors/source-marketo/pyproject.toml +++ b/airbyte-integrations/connectors/source-marketo/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "1.6.1" +version = "1.6.2" name = "source-marketo" description = "Source implementation for Marketo." authors = [ "Airbyte ",] diff --git a/airbyte-integrations/connectors/source-marketo/source_marketo/schemas/programs.json b/airbyte-integrations/connectors/source-marketo/source_marketo/schemas/programs.json index 85851ddae975..1e0601e1dce8 100644 --- a/airbyte-integrations/connectors/source-marketo/source_marketo/schemas/programs.json +++ b/airbyte-integrations/connectors/source-marketo/source_marketo/schemas/programs.json @@ -88,6 +88,14 @@ } } }, + "sfdcId": { + "description": "The ID of the corresponding object in Salesforce.", + "type": ["null", "string"] + }, + "sfdcName": { + "description": "The name of the corresponding object in Salesforce.", + "type": ["null", "string"] + }, "costs": { "description": "Period costs associated with the program.", "type": ["array", "null"], diff --git a/docs/integrations/sources/marketo.md b/docs/integrations/sources/marketo.md index 85d30ebeb60d..0a7ca78b8236 100644 --- a/docs/integrations/sources/marketo.md +++ b/docs/integrations/sources/marketo.md @@ -134,6 +134,7 @@ If these limits are too restrictive, contact your Marketo account manager for a | Version | Date | Pull Request | Subject | |:---------|:-----------|:---------------------------------------------------------|:-------------------------------------------------------------------------------------------------| +| 1.6.2 | 2026-03-26 | [75461](https://github.com/airbytehq/airbyte/pull/75461) | Add sfdcId and sfdcName fields to programs stream schema | | 1.6.1 | 2026-03-25 | [74088](https://github.com/airbytehq/airbyte/pull/74088) | Fix CSV column misalignment when syncing leads containing CJK characters | | 1.6.0 | 2026-03-19 | [74826](https://github.com/airbytehq/airbyte/pull/74826) | Add Emails and Program Tokens streams | | 1.5.0 | 2026-03-18 | [74136](https://github.com/airbytehq/airbyte/pull/74136) | Add dynamic schema discovery for custom fields on Leads stream; add tags and costs to Programs schema; add workspace to Segmentations schema | From bf75206ac7d6db6f61643498314b7afaf1b699c1 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 16:01:46 +0200 Subject: [PATCH 005/379] fix(source-hubspot): fail immediately on 401 for Private App Token auth instead of retrying (#75452) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- .../connectors/source-hubspot/components.py | 31 +- .../connectors/source-hubspot/manifest.yaml | 12 +- .../connectors/source-hubspot/metadata.yaml | 2 +- .../source-hubspot/unit_tests/poetry.lock | 403 ++---------------- .../unit_tests/test_components.py | 133 +++++- .../test_handle_retry_token_expired.py | 4 +- .../source-hubspot/unit_tests/test_streams.py | 1 - docs/integrations/sources/hubspot.md | 1 + 8 files changed, 208 insertions(+), 379 deletions(-) diff --git a/airbyte-integrations/connectors/source-hubspot/components.py b/airbyte-integrations/connectors/source-hubspot/components.py index 684d20c7576d..a90461fea74c 100644 --- a/airbyte-integrations/connectors/source-hubspot/components.py +++ b/airbyte-integrations/connectors/source-hubspot/components.py @@ -16,6 +16,7 @@ RecordSelector, SimpleRetriever, ) +from airbyte_cdk.models import FailureType from airbyte_cdk.sources.declarative.auth.oauth import DeclarativeOauth2Authenticator from airbyte_cdk.sources.declarative.auth.selective_authenticator import SelectiveAuthenticator from airbyte_cdk.sources.declarative.auth.token_provider import InterpolatedStringTokenProvider @@ -38,6 +39,7 @@ from airbyte_cdk.sources.declarative.requesters.requester import Requester from airbyte_cdk.sources.declarative.schema.schema_loader import SchemaLoader from airbyte_cdk.sources.declarative.transformations import RecordTransformation +from airbyte_cdk.sources.streams.http.error_handlers.response_models import ErrorResolution, ResponseAction from airbyte_cdk.sources.types import Config, Record, StreamSlice, StreamState from airbyte_cdk.sources.utils.transform import TransformConfig, TypeTransformer from airbyte_cdk.utils.datetime_helpers import AirbyteDateTime, ab_datetime_format, ab_datetime_now, ab_datetime_parse @@ -45,6 +47,31 @@ logger = logging.getLogger("airbyte") +_PRIVATE_APP_CREDENTIALS = "Private App Credentials" + + +class HubspotErrorHandler(DefaultErrorHandler): + """ + Custom error handler that differentiates 401 handling based on authentication type. + + For OAuth: 401 is retried because the OAuthAuthenticator can transparently refresh expired tokens. + For Private App Token (PAT): 401 is a permanent failure because static tokens cannot be refreshed. + """ + + def interpret_response(self, response_or_exception: Optional[Union[requests.Response, Exception]]) -> ErrorResolution: + if ( + isinstance(response_or_exception, requests.Response) + and response_or_exception.status_code == 401 + and self.config.get("credentials", {}).get("credentials_title") == _PRIVATE_APP_CREDENTIALS + ): + return ErrorResolution( + response_action=ResponseAction.FAIL, + failure_type=FailureType.config_error, + error_message="Please, update you Private App access token. Current token is invalid or expired.", + ) + + return super().interpret_response(response_or_exception) + @dataclass class NewtoLegacyFieldTransformation(RecordTransformation): @@ -675,7 +702,7 @@ def build_associations_retriever( config=config, parameters=parameters, ), - error_handler=DefaultErrorHandler( + error_handler=HubspotErrorHandler( backoff_strategies=[ WaitTimeFromHeaderBackoffStrategy(header="Retry-After", config=config, parameters=parameters), ExponentialBackoffStrategy(config=config, parameters=parameters), @@ -696,7 +723,7 @@ def build_associations_retriever( parameters=parameters, ), HttpResponseFilter( - action="RETRY", + action="REFRESH_TOKEN_THEN_RETRY", http_codes={401}, error_message="Authentication to HubSpot has expired. Authentication will be retried, but if this issue persists, re-authenticate to restore access to HubSpot.", config=config, diff --git a/airbyte-integrations/connectors/source-hubspot/manifest.yaml b/airbyte-integrations/connectors/source-hubspot/manifest.yaml index 6111b7ea41af..a1c99cdd5bca 100644 --- a/airbyte-integrations/connectors/source-hubspot/manifest.yaml +++ b/airbyte-integrations/connectors/source-hubspot/manifest.yaml @@ -1,4 +1,4 @@ -version: 6.51.0 +version: 6.52.0 type: DeclarativeSource @@ -40,7 +40,8 @@ definitions: $ref: "#/definitions/base_error_handler" base_error_handler: - type: DefaultErrorHandler + type: CustomErrorHandler + class_name: source_declarative_manifest.components.HubspotErrorHandler backoff_strategies: - type: WaitTimeFromHeader header: Retry-After @@ -61,7 +62,7 @@ definitions: error_message: >- HubSpot server error (5xx). Retrying with exponential backoff... - type: HttpResponseFilter - action: RETRY + action: REFRESH_TOKEN_THEN_RETRY http_codes: - 401 error_message: >- @@ -91,7 +92,8 @@ definitions: error_handler_ignore_403: # Same as the base error handler, but ignores 403 errors # to avoid failing the sync when fetching dynamic streams. - type: DefaultErrorHandler + type: CustomErrorHandler + class_name: source_declarative_manifest.components.HubspotErrorHandler backoff_strategies: - type: WaitTimeFromHeader header: Retry-After @@ -112,7 +114,7 @@ definitions: error_message: >- HubSpot server error (5xx). Retrying with exponential backoff... - type: HttpResponseFilter - action: RETRY + action: REFRESH_TOKEN_THEN_RETRY http_codes: - 401 error_message: >- diff --git a/airbyte-integrations/connectors/source-hubspot/metadata.yaml b/airbyte-integrations/connectors/source-hubspot/metadata.yaml index f716e525aee2..c98774bd8a90 100644 --- a/airbyte-integrations/connectors/source-hubspot/metadata.yaml +++ b/airbyte-integrations/connectors/source-hubspot/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: api connectorType: source definitionId: 36c891d9-4bd9-43ac-bad2-10e12756272c - dockerImageTag: 6.3.2 + dockerImageTag: 6.3.3 dockerRepository: airbyte/source-hubspot documentationUrl: https://docs.airbyte.com/integrations/sources/hubspot resourceRequirements: diff --git a/airbyte-integrations/connectors/source-hubspot/unit_tests/poetry.lock b/airbyte-integrations/connectors/source-hubspot/unit_tests/poetry.lock index 8d6d55f72644..65ff317ab7b0 100644 --- a/airbyte-integrations/connectors/source-hubspot/unit_tests/poetry.lock +++ b/airbyte-integrations/connectors/source-hubspot/unit_tests/poetry.lock @@ -1,15 +1,14 @@ -# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "airbyte-cdk" -version = "7.3.7" +version = "7.13.0" description = "A framework for writing Airbyte Connectors." optional = false python-versions = "<3.14,>=3.10" -groups = ["main"] files = [ - {file = "airbyte_cdk-7.3.7-py3-none-any.whl", hash = "sha256:11711913b6ea832fae12149eb377468bc5f64e2996cd8a47b093b99ec0b27a78"}, - {file = "airbyte_cdk-7.3.7.tar.gz", hash = "sha256:d5a1d76d54563667eea9ea30cb5d06e13d4207f64c32dbe9660002133f25a8e8"}, + {file = "airbyte_cdk-7.13.0-py3-none-any.whl", hash = "sha256:ede4018f0ce912102a7698daa6e1a793e0c8cd3f8c3456429d038951cca3a339"}, + {file = "airbyte_cdk-7.13.0.tar.gz", hash = "sha256:2b6cea3862509ab095beb19524dae78e2b24f3b356891e0a1e24f8854d8c124e"}, ] [package.dependencies] @@ -27,15 +26,12 @@ genson = "1.3.0" google-cloud-secret-manager = ">=2.17.0,<3.0.0" isodate = ">=0.6.1,<0.7.0" Jinja2 = ">=3.1.2,<3.2.0" -jsonref = ">=0.2,<0.3" +jsonref = ">=1,<2" jsonschema = ">=4.17.3,<5.0" -langchain_core = "0.1.42" nltk = "3.9.1" -numpy = "<2" orjson = ">=3.10.7,<4.0.0" packaging = "*" pandas = "2.2.3" -psutil = "6.1.0" pydantic = ">=2.7,<3.0" pyjwt = ">=2.8.0,<3.0.0" pyrate-limiter = ">=3.1.0,<3.2.0" @@ -59,10 +55,10 @@ xmltodict = ">=0.13,<0.15" [package.extras] dev = ["pytest (>=7,<8)"] -file-based = ["avro (>=1.11.2,<1.13.0)", "fastavro (>=1.11.0,<2.0.0)", "markdown", "pdf2image (==1.16.3)", "pdfminer.six (==20221105)", "pyarrow (>=19.0.0,<20.0.0)", "pytesseract (==0.3.10)", "python-calamine (==0.2.3)", "python-snappy (==0.7.3)", "unstructured.pytesseract (>=0.3.12)", "unstructured[docx,pptx] (==0.10.27)"] -manifest-server = ["ddtrace (>=3.12.3,<4.0.0)", "fastapi (>=0.116.1)", "uvicorn (>=0.35.0)"] +file-based = ["avro (>=1.11.2,<1.13.0)", "fastavro (>=1.11.0,<2.0.0)", "markdown", "openpyxl (>=3.1.0,<4.0.0)", "pdf2image (==1.16.3)", "pdfminer.six (==20221105)", "pyarrow (>=19.0.0,<20.0.0)", "pytesseract (==0.3.10)", "python-calamine (==0.2.3)", "python-snappy (==0.7.3)", "unstructured.pytesseract (>=0.3.12)", "unstructured[docx,pptx] (==0.10.27)"] +manifest-server = ["ddtrace (>=3,<4)", "fastapi (>=0.116.1)", "uvicorn (>=0.35.0)"] sql = ["sqlalchemy (>=2.0,!=2.0.36,<3.0)"] -vector-db-based = ["cohere (>=4.21,<6.0.0)", "langchain (==0.1.16)", "openai[embeddings] (==0.27.9)", "tiktoken (==0.8.0)"] +vector-db-based = ["cohere (>=4.21,<6.0.0)", "langchain_community (>=0.4,<0.5)", "langchain_core (>=1.2.5,<2.0.0)", "langchain_text_splitters (>=1.0.0,<2.0.0)", "openai[embeddings] (==0.27.9)", "tiktoken (==0.8.0)"] [[package]] name = "airbyte-protocol-models-dataclasses" @@ -70,7 +66,6 @@ version = "0.17.1" description = "Declares the Airbyte Protocol using Python Dataclasses. Dataclasses in Python have less performance overhead compared to Pydantic models, making them a more efficient choice for scenarios where speed and memory usage are critical" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "airbyte_protocol_models_dataclasses-0.17.1-py3-none-any.whl", hash = "sha256:ef83ac56de6208afe0a21ce05bcfbcfc98b98300a76fb3cdf4db2e7f720f1df0"}, {file = "airbyte_protocol_models_dataclasses-0.17.1.tar.gz", hash = "sha256:cbccfdf84fabd0b6e325cc57fa0682ae9d386fce8fcb5943faa5df2b7e599919"}, @@ -82,7 +77,6 @@ version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -94,42 +88,17 @@ version = "0.3.2" description = "Unicode to ASCII transliteration" optional = false python-versions = ">=3.3" -groups = ["main"] files = [ {file = "anyascii-0.3.2-py3-none-any.whl", hash = "sha256:3b3beef6fc43d9036d3b0529050b0c48bfad8bc960e9e562d7223cfb94fe45d4"}, {file = "anyascii-0.3.2.tar.gz", hash = "sha256:9d5d32ef844fe225b8bc7cba7f950534fae4da27a9bf3a6bea2cb0ea46ce4730"}, ] -[[package]] -name = "anyio" -version = "4.9.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c"}, - {file = "anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028"}, -] - -[package.dependencies] -exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} -idna = ">=2.8" -sniffio = ">=1.1" -typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} - -[package.extras] -doc = ["Sphinx (>=8.2,<9.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] -test = ["anyio[trio]", "blockbuster (>=1.5.23)", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""] -trio = ["trio (>=0.26.1)"] - [[package]] name = "attributes-doc" version = "0.4.0" description = "PEP 224 implementation" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "attributes-doc-0.4.0.tar.gz", hash = "sha256:b1576c94a714e9fc2c65c47cf10d0c8e1a5f7c4f5ae7f69006be108d95cbfbfb"}, {file = "attributes_doc-0.4.0-py2.py3-none-any.whl", hash = "sha256:4c3007d9e58f3a6cb4b9c614c4d4ce2d92161581f28e594ddd8241cc3a113bdd"}, @@ -141,19 +110,18 @@ version = "25.3.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, ] [package.extras] -benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] +tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] [[package]] name = "backoff" @@ -161,7 +129,6 @@ version = "2.2.1" description = "Function decoration for backoff and retry" optional = false python-versions = ">=3.7,<4.0" -groups = ["main"] files = [ {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, @@ -173,7 +140,6 @@ version = "25.0.0" description = "When they're not builtins, they're boltons." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "boltons-25.0.0-py3-none-any.whl", hash = "sha256:dc9fb38bf28985715497d1b54d00b62ea866eca3938938ea9043e254a3a6ca62"}, {file = "boltons-25.0.0.tar.gz", hash = "sha256:e110fbdc30b7b9868cb604e3f71d4722dd8f4dcb4a5ddd06028ba8f1ab0b5ace"}, @@ -185,7 +151,6 @@ version = "2.5.post1" description = "Bash style brace expander." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "bracex-2.5.post1-py3-none-any.whl", hash = "sha256:13e5732fec27828d6af308628285ad358047cec36801598368cb28bc631dbaf6"}, {file = "bracex-2.5.post1.tar.gz", hash = "sha256:12c50952415bfa773d2d9ccb8e79651b8cdb1f31a42f6091b804f6ba2b4a66b6"}, @@ -197,7 +162,6 @@ version = "5.5.2" description = "Extensible memoizing collections and decorators" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "cachetools-5.5.2-py3-none-any.whl", hash = "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a"}, {file = "cachetools-5.5.2.tar.gz", hash = "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4"}, @@ -209,7 +173,6 @@ version = "24.1.3" description = "Composable complex class support for attrs and dataclasses." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "cattrs-24.1.3-py3-none-any.whl", hash = "sha256:adf957dddd26840f27ffbd060a6c4dd3b2192c5b7c2c0525ef1bd8131d8a83f5"}, {file = "cattrs-24.1.3.tar.gz", hash = "sha256:981a6ef05875b5bb0c7fb68885546186d306f10f0f6718fe9b96c226e68821ff"}, @@ -224,8 +187,8 @@ typing-extensions = {version = ">=4.1.0,<4.6.3 || >4.6.3", markers = "python_ver bson = ["pymongo (>=4.4.0)"] cbor2 = ["cbor2 (>=5.4.6)"] msgpack = ["msgpack (>=1.0.5)"] -msgspec = ["msgspec (>=0.18.5) ; implementation_name == \"cpython\""] -orjson = ["orjson (>=3.9.2) ; implementation_name == \"cpython\""] +msgspec = ["msgspec (>=0.18.5)"] +orjson = ["orjson (>=3.9.2)"] pyyaml = ["pyyaml (>=6.0)"] tomlkit = ["tomlkit (>=0.11.8)"] ujson = ["ujson (>=5.7.0)"] @@ -236,7 +199,6 @@ version = "2025.4.26" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3"}, {file = "certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6"}, @@ -248,8 +210,6 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -329,7 +289,6 @@ version = "3.4.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"}, {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"}, @@ -431,7 +390,6 @@ version = "8.2.1" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.10" -groups = ["main"] files = [ {file = "click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b"}, {file = "click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202"}, @@ -446,8 +404,6 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main"] -markers = "platform_system == \"Windows\" or sys_platform == \"win32\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -459,7 +415,6 @@ version = "44.0.3" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = "!=3.9.0,!=3.9.1,>=3.7" -groups = ["main"] files = [ {file = "cryptography-44.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:962bc30480a08d133e631e8dfd4783ab71cc9e33d5d7c1e192f0b7c06397bb88"}, {file = "cryptography-44.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffc61e8f3bf5b60346d89cd3d37231019c17a081208dfbbd6e1605ba03fa137"}, @@ -504,10 +459,10 @@ files = [ cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} [package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0) ; python_version >= \"3.8\""] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >= \"3.8\""] -pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] +pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] sdist = ["build (>=1.0.0)"] ssh = ["bcrypt (>=3.1.5)"] test = ["certifi (>=2024)", "cryptography-vectors (==44.0.3)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] @@ -519,7 +474,6 @@ version = "1.2.2" description = "Date parsing library designed to parse dates from HTML pages" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "dateparser-1.2.2-py3-none-any.whl", hash = "sha256:5a5d7211a09013499867547023a2a0c91d5a27d15dd4dbcea676ea9fe66f2482"}, {file = "dateparser-1.2.2.tar.gz", hash = "sha256:986316f17cb8cdc23ea8ce563027c5ef12fc725b6fb1d137c14ca08777c5ecf7"}, @@ -542,7 +496,6 @@ version = "2.2.0" description = "Filesystem-like pathing and searching for dictionaries" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "dpath-2.2.0-py3-none-any.whl", hash = "sha256:b330a375ded0a0d2ed404440f6c6a715deae5313af40bbb01c8a41d891900576"}, {file = "dpath-2.2.0.tar.gz", hash = "sha256:34f7e630dc55ea3f219e555726f5da4b4b25f2200319c8e6902c394258dd6a3e"}, @@ -554,7 +507,6 @@ version = "1.24.1" description = "Dynamic version generation" optional = false python-versions = ">=3.5" -groups = ["main"] files = [ {file = "dunamai-1.24.1-py3-none-any.whl", hash = "sha256:4370e406d8ce195fc4b066b5c326bfa9adb269c4b8719b4e4fd90b63a2144bf7"}, {file = "dunamai-1.24.1.tar.gz", hash = "sha256:3aa3348f77242da8628b23f11e89569343440f0f912bcef32a1fa891cf8e7215"}, @@ -569,8 +521,6 @@ version = "1.3.0" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.10\"" files = [ {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, @@ -588,7 +538,6 @@ version = "1.5.1" description = "Let your Python tests travel through time" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "freezegun-1.5.1-py3-none-any.whl", hash = "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1"}, {file = "freezegun-1.5.1.tar.gz", hash = "sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9"}, @@ -603,7 +552,6 @@ version = "1.3.0" description = "GenSON is a powerful, user-friendly JSON Schema generator." optional = false python-versions = "*" -groups = ["main"] files = [ {file = "genson-1.3.0-py3-none-any.whl", hash = "sha256:468feccd00274cc7e4c09e84b08704270ba8d95232aa280f65b986139cec67f7"}, {file = "genson-1.3.0.tar.gz", hash = "sha256:e02db9ac2e3fd29e65b5286f7135762e2cd8a986537c075b06fc5f1517308e37"}, @@ -615,7 +563,6 @@ version = "2.24.2" description = "Google API client core library" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "google_api_core-2.24.2-py3-none-any.whl", hash = "sha256:810a63ac95f3c441b7c0e43d344e372887f62ce9071ba972eacf32672e072de9"}, {file = "google_api_core-2.24.2.tar.gz", hash = "sha256:81718493daf06d96d6bc76a91c23874dbf2fac0adbbf542831b805ee6e974696"}, @@ -625,12 +572,12 @@ files = [ google-auth = ">=2.14.1,<3.0.0" googleapis-common-protos = ">=1.56.2,<2.0.0" grpcio = [ - {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, {version = ">=1.33.2,<2.0dev", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, + {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, ] grpcio-status = [ + {version = ">=1.33.2,<2.0.dev0", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, - {version = ">=1.33.2,<2.0.dev0", optional = true, markers = "extra == \"grpc\""}, ] proto-plus = ">=1.22.3,<2.0.0" protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0" @@ -638,7 +585,7 @@ requests = ">=2.18.0,<3.0.0" [package.extras] async-rest = ["google-auth[aiohttp] (>=2.35.0,<3.0.dev0)"] -grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev) ; python_version >= \"3.11\"", "grpcio-status (>=1.33.2,<2.0.dev0)", "grpcio-status (>=1.49.1,<2.0.dev0) ; python_version >= \"3.11\""] +grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status (>=1.33.2,<2.0.dev0)", "grpcio-status (>=1.49.1,<2.0.dev0)"] grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] @@ -648,7 +595,6 @@ version = "2.40.2" description = "Google Authentication Library" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "google_auth-2.40.2-py2.py3-none-any.whl", hash = "sha256:f7e568d42eedfded58734f6a60c58321896a621f7c116c411550a4b4a13da90b"}, {file = "google_auth-2.40.2.tar.gz", hash = "sha256:a33cde547a2134273226fa4b853883559947ebe9207521f7afc707efbf690f58"}, @@ -662,11 +608,11 @@ rsa = ">=3.1.4,<5" [package.extras] aiohttp = ["aiohttp (>=3.6.2,<4.0.0)", "requests (>=2.20.0,<3.0.0)"] enterprise-cert = ["cryptography", "pyopenssl"] -pyjwt = ["cryptography (<39.0.0) ; python_version < \"3.8\"", "cryptography (>=38.0.3)", "pyjwt (>=2.0)"] -pyopenssl = ["cryptography (<39.0.0) ; python_version < \"3.8\"", "cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] +pyjwt = ["cryptography (<39.0.0)", "cryptography (>=38.0.3)", "pyjwt (>=2.0)"] +pyopenssl = ["cryptography (<39.0.0)", "cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] reauth = ["pyu2f (>=0.1.5)"] requests = ["requests (>=2.20.0,<3.0.0)"] -testing = ["aiohttp (<3.10.0)", "aiohttp (>=3.6.2,<4.0.0)", "aioresponses", "cryptography (<39.0.0) ; python_version < \"3.8\"", "cryptography (>=38.0.3)", "flask", "freezegun", "grpcio", "mock", "oauth2client", "packaging", "pyjwt (>=2.0)", "pyopenssl (<24.3.0)", "pyopenssl (>=20.0.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-localserver", "pyu2f (>=0.1.5)", "requests (>=2.20.0,<3.0.0)", "responses", "urllib3"] +testing = ["aiohttp (<3.10.0)", "aiohttp (>=3.6.2,<4.0.0)", "aioresponses", "cryptography (<39.0.0)", "cryptography (>=38.0.3)", "flask", "freezegun", "grpcio", "mock", "oauth2client", "packaging", "pyjwt (>=2.0)", "pyopenssl (<24.3.0)", "pyopenssl (>=20.0.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-localserver", "pyu2f (>=0.1.5)", "requests (>=2.20.0,<3.0.0)", "responses", "urllib3"] urllib3 = ["packaging", "urllib3"] [[package]] @@ -675,7 +621,6 @@ version = "2.23.3" description = "Google Cloud Secret Manager API client library" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "google_cloud_secret_manager-2.23.3-py3-none-any.whl", hash = "sha256:fe06ebb2f71eb739ecc6c14ea9e8dafcb9bbc6123b78b2f8986ece6733d23a1a"}, {file = "google_cloud_secret_manager-2.23.3.tar.gz", hash = "sha256:598c4c0a9d10d49d500eb4aea3255dff250aa2f92c028f5c97e3b367f768c808"}, @@ -694,7 +639,6 @@ version = "1.70.0" description = "Common protobufs used in Google APIs" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "googleapis_common_protos-1.70.0-py3-none-any.whl", hash = "sha256:b8bfcca8c25a2bb253e0e0b0adaf8c00773e5e6af6fd92397576680b807e0fd8"}, {file = "googleapis_common_protos-1.70.0.tar.gz", hash = "sha256:0e1b44e0ea153e6594f9f394fef15193a68aaaea2d843f83e2742717ca753257"}, @@ -713,7 +657,6 @@ version = "0.14.2" description = "IAM API client library" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "grpc_google_iam_v1-0.14.2-py3-none-any.whl", hash = "sha256:a3171468459770907926d56a440b2bb643eec1d7ba215f48f3ecece42b4d8351"}, {file = "grpc_google_iam_v1-0.14.2.tar.gz", hash = "sha256:b3e1fc387a1a329e41672197d0ace9de22c78dd7d215048c4c78712073f7bd20"}, @@ -730,7 +673,6 @@ version = "1.71.0" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "grpcio-1.71.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:c200cb6f2393468142eb50ab19613229dcc7829b5ccee8b658a36005f6669fdd"}, {file = "grpcio-1.71.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:b2266862c5ad664a380fbbcdbdb8289d71464c42a8c29053820ee78ba0119e5d"}, @@ -794,7 +736,6 @@ version = "1.62.3" description = "Status proto mapping for gRPC" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "grpcio-status-1.62.3.tar.gz", hash = "sha256:289bdd7b2459794a12cf95dc0cb727bd4a1742c37bd823f760236c937e53a485"}, {file = "grpcio_status-1.62.3-py3-none-any.whl", hash = "sha256:f9049b762ba8de6b1086789d8315846e094edac2c50beaf462338b301a8fd4b8"}, @@ -805,72 +746,12 @@ googleapis-common-protos = ">=1.5.5" grpcio = ">=1.62.3" protobuf = ">=4.21.6" -[[package]] -name = "h11" -version = "0.16.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, - {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, -] - -[[package]] -name = "httpcore" -version = "1.0.9" -description = "A minimal low-level HTTP client." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, - {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, -] - -[package.dependencies] -certifi = "*" -h11 = ">=0.16" - -[package.extras] -asyncio = ["anyio (>=4.0,<5.0)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<1.0)"] - -[[package]] -name = "httpx" -version = "0.28.1" -description = "The next generation HTTP client." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, - {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, -] - -[package.dependencies] -anyio = "*" -certifi = "*" -httpcore = "==1.*" -idna = "*" - -[package.extras] -brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -zstd = ["zstandard (>=0.18.0)"] - [[package]] name = "idna" version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -885,7 +766,6 @@ version = "2.1.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, @@ -897,7 +777,6 @@ version = "0.6.1" description = "An ISO 8601 date/time/duration parser and formatter" optional = false python-versions = "*" -groups = ["main"] files = [ {file = "isodate-0.6.1-py2.py3-none-any.whl", hash = "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96"}, {file = "isodate-0.6.1.tar.gz", hash = "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9"}, @@ -912,7 +791,6 @@ version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -930,49 +808,20 @@ version = "1.5.1" description = "Lightweight pipelining with Python functions" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "joblib-1.5.1-py3-none-any.whl", hash = "sha256:4719a31f054c7d766948dcd83e9613686b27114f190f717cec7eaa2084f8a74a"}, {file = "joblib-1.5.1.tar.gz", hash = "sha256:f4f86e351f39fe3d0d32a9f2c3d8af1ee4cec285aafcb27003dda5205576b444"}, ] -[[package]] -name = "jsonpatch" -version = "1.33" -description = "Apply JSON-Patches (RFC 6902)" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" -groups = ["main"] -files = [ - {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, - {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, -] - -[package.dependencies] -jsonpointer = ">=1.9" - -[[package]] -name = "jsonpointer" -version = "3.0.0" -description = "Identify specific nodes in a JSON document (RFC 6901)" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"}, - {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"}, -] - [[package]] name = "jsonref" -version = "0.2" -description = "An implementation of JSON Reference for Python" +version = "1.1.0" +description = "jsonref is a library for automatic dereferencing of JSON Reference objects for Python." optional = false -python-versions = "*" -groups = ["main"] +python-versions = ">=3.7" files = [ - {file = "jsonref-0.2-py3-none-any.whl", hash = "sha256:b1e82fa0b62e2c2796a13e5401fe51790b248f6d9bf9d7212a3e31a3501b291f"}, - {file = "jsonref-0.2.tar.gz", hash = "sha256:f3c45b121cf6257eafabdc3a8008763aed1cd7da06dbabc59a9e4d2a5e4e6697"}, + {file = "jsonref-1.1.0-py3-none-any.whl", hash = "sha256:590dc7773df6c21cbf948b5dac07a72a251db28b0238ceecce0a2abfa8ec30a9"}, + {file = "jsonref-1.1.0.tar.gz", hash = "sha256:32fe8e1d85af0fdefbebce950af85590b22b60f9e95443176adbde4e1ecea552"}, ] [[package]] @@ -981,7 +830,6 @@ version = "4.17.3" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, @@ -995,61 +843,12 @@ pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] -[[package]] -name = "langchain-core" -version = "0.1.42" -description = "Building applications with LLMs through composability" -optional = false -python-versions = "<4.0,>=3.8.1" -groups = ["main"] -files = [ - {file = "langchain_core-0.1.42-py3-none-any.whl", hash = "sha256:c5653ffa08a44f740295c157a24c0def4a753333f6a2c41f76bf431cd00be8b5"}, - {file = "langchain_core-0.1.42.tar.gz", hash = "sha256:40751bf60ea5d8e2b2efe65290db434717ee3834870c002e40e2811f09d814e6"}, -] - -[package.dependencies] -jsonpatch = ">=1.33,<2.0" -langsmith = ">=0.1.0,<0.2.0" -packaging = ">=23.2,<24.0" -pydantic = ">=1,<3" -PyYAML = ">=5.3" -tenacity = ">=8.1.0,<9.0.0" - -[package.extras] -extended-testing = ["jinja2 (>=3,<4)"] - -[[package]] -name = "langsmith" -version = "0.1.147" -description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." -optional = false -python-versions = "<4.0,>=3.8.1" -groups = ["main"] -files = [ - {file = "langsmith-0.1.147-py3-none-any.whl", hash = "sha256:7166fc23b965ccf839d64945a78e9f1157757add228b086141eb03a60d699a15"}, - {file = "langsmith-0.1.147.tar.gz", hash = "sha256:2e933220318a4e73034657103b3b1a3a6109cc5db3566a7e8e03be8d6d7def7a"}, -] - -[package.dependencies] -httpx = ">=0.23.0,<1" -orjson = {version = ">=3.9.14,<4.0.0", markers = "platform_python_implementation != \"PyPy\""} -pydantic = [ - {version = ">=1,<3", markers = "python_full_version < \"3.12.4\""}, - {version = ">=2.7.4,<3.0.0", markers = "python_full_version >= \"3.12.4\""}, -] -requests = ">=2,<3" -requests-toolbelt = ">=1.0.0,<2.0.0" - -[package.extras] -langsmith-pyo3 = ["langsmith-pyo3 (>=0.1.0rc2,<0.2.0)"] - [[package]] name = "markdown-it-py" version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, @@ -1074,7 +873,6 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -1145,7 +943,6 @@ version = "0.1.2" description = "Markdown URL utilities" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, @@ -1157,7 +954,6 @@ version = "5.2.0" description = "Rolling backport of unittest.mock for all Pythons" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "mock-5.2.0-py3-none-any.whl", hash = "sha256:7ba87f72ca0e915175596069dbbcc7c75af7b5e9b9bc107ad6349ede0819982f"}, {file = "mock-5.2.0.tar.gz", hash = "sha256:4e460e818629b4b173f32d08bf30d3af8123afbb8e04bb5707a1fd4799e503f0"}, @@ -1174,7 +970,6 @@ version = "3.9.1" description = "Natural Language Toolkit" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "nltk-3.9.1-py3-none-any.whl", hash = "sha256:4fa26829c5b00715afe3061398a8989dc643b92ce7dd93fb4585a70930d168a1"}, {file = "nltk-3.9.1.tar.gz", hash = "sha256:87d127bd3de4bd89a4f81265e5fa59cb1b199b27440175370f7417d2bc7ae868"}, @@ -1200,7 +995,6 @@ version = "1.26.4" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, @@ -1246,7 +1040,6 @@ version = "3.10.18" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "orjson-3.10.18-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a45e5d68066b408e4bc383b6e4ef05e717c65219a9e1390abc6155a520cac402"}, {file = "orjson-3.10.18-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be3b9b143e8b9db05368b13b04c84d37544ec85bb97237b3a923f076265ec89c"}, @@ -1328,7 +1121,6 @@ version = "23.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, @@ -1340,7 +1132,6 @@ version = "2.2.3" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5"}, {file = "pandas-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348"}, @@ -1388,9 +1179,9 @@ files = [ [package.dependencies] numpy = [ + {version = ">=1.22.4", markers = "python_version < \"3.11\""}, {version = ">=1.23.2", markers = "python_version == \"3.11\""}, {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, - {version = ">=1.22.4", markers = "python_version < \"3.11\""}, ] python-dateutil = ">=2.8.2" pytz = ">=2020.1" @@ -1427,7 +1218,6 @@ version = "4.3.8" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, @@ -1444,7 +1234,6 @@ version = "1.6.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, @@ -1460,7 +1249,6 @@ version = "1.26.1" description = "Beautiful, Pythonic protocol buffers" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "proto_plus-1.26.1-py3-none-any.whl", hash = "sha256:13285478c2dcf2abb829db158e1047e2f1e8d63a077d94263c2b88b043c75a66"}, {file = "proto_plus-1.26.1.tar.gz", hash = "sha256:21a515a4c4c0088a773899e23c7bbade3d18f9c66c73edd4c7ee3816bc96a012"}, @@ -1478,7 +1266,6 @@ version = "6.31.0" description = "" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "protobuf-6.31.0-cp310-abi3-win32.whl", hash = "sha256:10bd62802dfa0588649740a59354090eaf54b8322f772fbdcca19bc78d27f0d6"}, {file = "protobuf-6.31.0-cp310-abi3-win_amd64.whl", hash = "sha256:3e987c99fd634be8347246a02123250f394ba20573c953de133dc8b2c107dd71"}, @@ -1491,44 +1278,12 @@ files = [ {file = "protobuf-6.31.0.tar.gz", hash = "sha256:314fab1a6a316469dc2dd46f993cbbe95c861ea6807da910becfe7475bc26ffe"}, ] -[[package]] -name = "psutil" -version = "6.1.0" -description = "Cross-platform lib for process and system monitoring in Python." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -groups = ["main"] -files = [ - {file = "psutil-6.1.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ff34df86226c0227c52f38b919213157588a678d049688eded74c76c8ba4a5d0"}, - {file = "psutil-6.1.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:c0e0c00aa18ca2d3b2b991643b799a15fc8f0563d2ebb6040f64ce8dc027b942"}, - {file = "psutil-6.1.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:000d1d1ebd634b4efb383f4034437384e44a6d455260aaee2eca1e9c1b55f047"}, - {file = "psutil-6.1.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:5cd2bcdc75b452ba2e10f0e8ecc0b57b827dd5d7aaffbc6821b2a9a242823a76"}, - {file = "psutil-6.1.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:045f00a43c737f960d273a83973b2511430d61f283a44c96bf13a6e829ba8fdc"}, - {file = "psutil-6.1.0-cp27-none-win32.whl", hash = "sha256:9118f27452b70bb1d9ab3198c1f626c2499384935aaf55388211ad982611407e"}, - {file = "psutil-6.1.0-cp27-none-win_amd64.whl", hash = "sha256:a8506f6119cff7015678e2bce904a4da21025cc70ad283a53b099e7620061d85"}, - {file = "psutil-6.1.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6e2dcd475ce8b80522e51d923d10c7871e45f20918e027ab682f94f1c6351688"}, - {file = "psutil-6.1.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0895b8414afafc526712c498bd9de2b063deaac4021a3b3c34566283464aff8e"}, - {file = "psutil-6.1.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dcbfce5d89f1d1f2546a2090f4fcf87c7f669d1d90aacb7d7582addece9fb38"}, - {file = "psutil-6.1.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:498c6979f9c6637ebc3a73b3f87f9eb1ec24e1ce53a7c5173b8508981614a90b"}, - {file = "psutil-6.1.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d905186d647b16755a800e7263d43df08b790d709d575105d419f8b6ef65423a"}, - {file = "psutil-6.1.0-cp36-cp36m-win32.whl", hash = "sha256:6d3fbbc8d23fcdcb500d2c9f94e07b1342df8ed71b948a2649b5cb060a7c94ca"}, - {file = "psutil-6.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1209036fbd0421afde505a4879dee3b2fd7b1e14fee81c0069807adcbbcca747"}, - {file = "psutil-6.1.0-cp37-abi3-win32.whl", hash = "sha256:1ad45a1f5d0b608253b11508f80940985d1d0c8f6111b5cb637533a0e6ddc13e"}, - {file = "psutil-6.1.0-cp37-abi3-win_amd64.whl", hash = "sha256:a8fb3752b491d246034fa4d279ff076501588ce8cbcdbb62c32fd7a377d996be"}, - {file = "psutil-6.1.0.tar.gz", hash = "sha256:353815f59a7f64cdaca1c0307ee13558a0512f6db064e92fe833784f08539c7a"}, -] - -[package.extras] -dev = ["black", "check-manifest", "coverage", "packaging", "pylint", "pyperf", "pypinfo", "pytest-cov", "requests", "rstcheck", "ruff", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "virtualenv", "wheel"] -test = ["pytest", "pytest-xdist", "setuptools"] - [[package]] name = "pyasn1" version = "0.6.1" description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"}, {file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"}, @@ -1540,7 +1295,6 @@ version = "0.4.2" description = "A collection of ASN.1-based protocols modules" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a"}, {file = "pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6"}, @@ -1555,8 +1309,6 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -1568,7 +1320,6 @@ version = "2.11.5" description = "Data validation using Python type hints" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "pydantic-2.11.5-py3-none-any.whl", hash = "sha256:f9c26ba06f9747749ca1e5c94d6a85cb84254577553c8785576fd38fa64dc0f7"}, {file = "pydantic-2.11.5.tar.gz", hash = "sha256:7f853db3d0ce78ce8bbb148c401c2cdd6431b3473c0cdff2755c7690952a7b7a"}, @@ -1582,7 +1333,7 @@ typing-inspection = ">=0.4.0" [package.extras] email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] +timezone = ["tzdata"] [[package]] name = "pydantic-core" @@ -1590,7 +1341,6 @@ version = "2.33.2" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}, {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}, @@ -1702,7 +1452,6 @@ version = "2.19.1" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, @@ -1717,7 +1466,6 @@ version = "2.10.1" description = "JSON Web Token implementation in Python" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"}, {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"}, @@ -1735,7 +1483,6 @@ version = "3.1.1" description = "Python Rate-Limiter using Leaky-Bucket Algorithm" optional = false python-versions = ">=3.8,<4.0" -groups = ["main"] files = [ {file = "pyrate_limiter-3.1.1-py3-none-any.whl", hash = "sha256:c51906f1d51d56dc992ff6c26e8300e32151bc6cfa3e6559792e31971dfd4e2b"}, {file = "pyrate_limiter-3.1.1.tar.gz", hash = "sha256:2f57eda712687e6eccddf6afe8f8a15b409b97ed675fe64a626058f12863b7b7"}, @@ -1751,7 +1498,6 @@ version = "0.20.0" description = "Persistent/Functional/Immutable data structures" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "pyrsistent-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c3aba3e01235221e5b229a6c05f585f344734bd1ad42a8ac51493d74722bbce"}, {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1beb78af5423b879edaf23c5591ff292cf7c33979734c99aa66d5914ead880f"}, @@ -1793,7 +1539,6 @@ version = "8.3.5" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, @@ -1816,7 +1561,6 @@ version = "3.14.0" description = "Thin-wrapper around the mock package for easier use with pytest" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, @@ -1834,7 +1578,6 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -1849,7 +1592,6 @@ version = "3.0.0" description = "Universally unique lexicographically sortable identifier" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "python_ulid-3.0.0-py3-none-any.whl", hash = "sha256:e4c4942ff50dbd79167ad01ac725ec58f924b4018025ce22c858bfcff99a5e31"}, {file = "python_ulid-3.0.0.tar.gz", hash = "sha256:e50296a47dc8209d28629a22fc81ca26c00982c78934bd7766377ba37ea49a9f"}, @@ -1864,7 +1606,6 @@ version = "2024.2" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" -groups = ["main"] files = [ {file = "pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725"}, {file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"}, @@ -1876,7 +1617,6 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -1939,7 +1679,6 @@ version = "3.13.0" description = "rapid fuzzy string matching" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "rapidfuzz-3.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:aafc42a1dc5e1beeba52cd83baa41372228d6d8266f6d803c16dbabbcc156255"}, {file = "rapidfuzz-3.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:85c9a131a44a95f9cac2eb6e65531db014e09d89c4f18c7b1fa54979cb9ff1f3"}, @@ -2046,7 +1785,6 @@ version = "0.37.0" description = "JSON Referencing + Python" optional = false python-versions = ">=3.10" -groups = ["main"] files = [ {file = "referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231"}, {file = "referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8"}, @@ -2063,7 +1801,6 @@ version = "2024.11.6" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"}, {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"}, @@ -2167,7 +1904,6 @@ version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, @@ -2189,7 +1925,6 @@ version = "1.2.1" description = "A persistent cache for python requests" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "requests_cache-1.2.1-py3-none-any.whl", hash = "sha256:1285151cddf5331067baa82598afe2d47c7495a1334bfe7a7d329b43e9fd3603"}, {file = "requests_cache-1.2.1.tar.gz", hash = "sha256:68abc986fdc5b8d0911318fbb5f7c80eebcd4d01bfacc6685ecf8876052511d1"}, @@ -2220,7 +1955,6 @@ version = "1.12.1" description = "Mock out responses from the requests package" optional = false python-versions = ">=3.5" -groups = ["main"] files = [ {file = "requests-mock-1.12.1.tar.gz", hash = "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401"}, {file = "requests_mock-1.12.1-py2.py3-none-any.whl", hash = "sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563"}, @@ -2232,28 +1966,12 @@ requests = ">=2.22,<3" [package.extras] fixture = ["fixtures"] -[[package]] -name = "requests-toolbelt" -version = "1.0.0" -description = "A utility belt for advanced users of python-requests" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] -files = [ - {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, - {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, -] - -[package.dependencies] -requests = ">=2.0.1,<3.0.0" - [[package]] name = "rich" version = "14.0.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.8.0" -groups = ["main"] files = [ {file = "rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0"}, {file = "rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725"}, @@ -2273,7 +1991,6 @@ version = "1.8.9" description = "Format click help output nicely with rich" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "rich_click-1.8.9-py3-none-any.whl", hash = "sha256:c3fa81ed8a671a10de65a9e20abf642cfdac6fdb882db1ef465ee33919fbcfe2"}, {file = "rich_click-1.8.9.tar.gz", hash = "sha256:fd98c0ab9ddc1cf9c0b7463f68daf28b4d0033a74214ceb02f761b3ff2af3136"}, @@ -2294,7 +2011,6 @@ version = "0.27.1" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "rpds_py-0.27.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:68afeec26d42ab3b47e541b272166a0b4400313946871cba3ed3a4fc0cab1cef"}, {file = "rpds_py-0.27.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74e5b2f7bb6fa38b1b10546d27acbacf2a022a8b5543efb06cfebc72a59c85be"}, @@ -2459,7 +2175,6 @@ version = "4.9.1" description = "Pure-Python RSA implementation" optional = false python-versions = "<4,>=3.6" -groups = ["main"] files = [ {file = "rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762"}, {file = "rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75"}, @@ -2474,7 +2189,6 @@ version = "1.13.0" description = "" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "serpyco_rs-1.13.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e722b3053e627d8a304e462bce20cae1670a2c4b0ef875b84d0de0081bec4029"}, {file = "serpyco_rs-1.13.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f10e89c752ff78d720a42e026b0a9ada70717ad6306a9356f794280167d62bf"}, @@ -2529,20 +2243,19 @@ version = "80.9.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922"}, {file = "setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c"}, ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""] -core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.8.0)"] +core = ["importlib_metadata (>=6)", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.14.*)", "pytest-mypy"] [[package]] name = "six" @@ -2550,48 +2263,17 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - -[[package]] -name = "tenacity" -version = "8.5.0" -description = "Retry code until it succeeds" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "tenacity-8.5.0-py3-none-any.whl", hash = "sha256:b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687"}, - {file = "tenacity-8.5.0.tar.gz", hash = "sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78"}, -] - -[package.extras] -doc = ["reno", "sphinx"] -test = ["pytest", "tornado (>=4.5)", "typeguard"] - [[package]] name = "tomli" version = "2.2.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.10\"" files = [ {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, @@ -2633,7 +2315,6 @@ version = "4.67.1" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2"}, {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"}, @@ -2655,7 +2336,6 @@ version = "4.13.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, @@ -2667,7 +2347,6 @@ version = "0.4.1" description = "Runtime typing introspection tools" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51"}, {file = "typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28"}, @@ -2682,7 +2361,6 @@ version = "2025.2" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" -groups = ["main"] files = [ {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"}, {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"}, @@ -2694,7 +2372,6 @@ version = "5.3.1" description = "tzinfo object for the local timezone" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "tzlocal-5.3.1-py3-none-any.whl", hash = "sha256:eb1a66c3ef5847adf7a834f1be0800581b683b5608e74f86ecbcef8ab91bb85d"}, {file = "tzlocal-5.3.1.tar.gz", hash = "sha256:cceffc7edecefea1f595541dbd6e990cb1ea3d19bf01b2809f362a03dd7921fd"}, @@ -2712,7 +2389,6 @@ version = "1.4.0" description = "ASCII transliterations of Unicode text" optional = false python-versions = ">=3.7" -groups = ["main"] files = [ {file = "Unidecode-1.4.0-py3-none-any.whl", hash = "sha256:c3c7606c27503ad8d501270406e345ddb480a7b5f38827eafe4fa82a137f0021"}, {file = "Unidecode-1.4.0.tar.gz", hash = "sha256:ce35985008338b676573023acc382d62c264f307c8f7963733405add37ea2b23"}, @@ -2724,7 +2400,6 @@ version = "2.2.1" description = "URL normalization for Python" optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "url_normalize-2.2.1-py3-none-any.whl", hash = "sha256:3deb687587dc91f7b25c9ae5162ffc0f057ae85d22b1e15cf5698311247f567b"}, {file = "url_normalize-2.2.1.tar.gz", hash = "sha256:74a540a3b6eba1d95bdc610c24f2c0141639f3ba903501e61a52a8730247ff37"}, @@ -2742,14 +2417,13 @@ version = "2.4.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813"}, {file = "urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466"}, ] [package.extras] -brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] @@ -2760,7 +2434,6 @@ version = "10.0" description = "Wildcard/glob file name matcher." optional = false python-versions = ">=3.8" -groups = ["main"] files = [ {file = "wcmatch-10.0-py3-none-any.whl", hash = "sha256:0dd927072d03c0a6527a20d2e6ad5ba8d0380e60870c383bc533b71744df7b7a"}, {file = "wcmatch-10.0.tar.gz", hash = "sha256:e72f0de09bba6a04e0de70937b0cf06e55f36f37b3deb422dfaf854b867b840a"}, @@ -2775,7 +2448,6 @@ version = "0.8.10" description = "Modern datetime library for Python" optional = false python-versions = ">=3.9" -groups = ["main"] files = [ {file = "whenever-0.8.10-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:d9ecb6b649cb7e5c85742f626ddd56d5cf5d276c632a47ec5d72714350300564"}, {file = "whenever-0.8.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0698cbd2209413f7a0cb84507405587e7b3995ce22504e50477a1a65ec3b65b9"}, @@ -2874,13 +2546,12 @@ version = "0.14.2" description = "Makes working with XML feel like you are working with JSON" optional = false python-versions = ">=3.6" -groups = ["main"] files = [ {file = "xmltodict-0.14.2-py2.py3-none-any.whl", hash = "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac"}, {file = "xmltodict-0.14.2.tar.gz", hash = "sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553"}, ] [metadata] -lock-version = "2.1" +lock-version = "2.0" python-versions = "^3.10,<3.13" content-hash = "cbe90dc44c1d21e787b49e0c4f731c0dec26432421d7fd19219d2a9b202be971" diff --git a/airbyte-integrations/connectors/source-hubspot/unit_tests/test_components.py b/airbyte-integrations/connectors/source-hubspot/unit_tests/test_components.py index dd20f044ea6f..cf829625ed8d 100644 --- a/airbyte-integrations/connectors/source-hubspot/unit_tests/test_components.py +++ b/airbyte-integrations/connectors/source-hubspot/unit_tests/test_components.py @@ -8,8 +8,12 @@ import requests from requests import Response +from airbyte_cdk.models import FailureType from airbyte_cdk.sources.declarative.decoders import JsonDecoder +from airbyte_cdk.sources.declarative.requesters.error_handlers.http_response_filter import HttpResponseFilter from airbyte_cdk.sources.declarative.retrievers import SimpleRetriever +from airbyte_cdk.sources.streams.http.error_handlers.response_models import ResponseAction +from airbyte_cdk.utils.traced_exception import AirbyteTracedException @pytest.mark.parametrize( @@ -457,7 +461,8 @@ def test_associations_extractor(config, components_module): assert records[1]["contacts"] == expected_records[1]["contacts"] -def test_associations_extractor_with_permissions_error(requests_mock, config, components_module): +def test_associations_extractor_with_permissions_error(requests_mock, oauth_config, components_module): + """With OAuth credentials, a 401 on associations should be retried and succeed on the second attempt.""" response = requests.Response() response._content = ( b'{"results": [{"id": "123", "updatedAt": "2022-02-25T16:43:11Z"}, {"id": "456", "updatedAt": "2022-02-25T16:43:11Z"}]}' @@ -485,6 +490,12 @@ def test_associations_extractor_with_permissions_error(requests_mock, config, co contacts_associations_responses = [{"json": {"results": []}, "status_code": 200}] + # Mock the OAuth token refresh endpoint so REFRESH_TOKEN_THEN_RETRY can refresh the token + requests_mock.register_uri( + "POST", + "https://api.hubapi.com/oauth/v1/token", + [{"json": {"access_token": "refreshed_token", "expires_in": 3600}, "status_code": 200}], + ) requests_mock.register_uri( "POST", "https://api.hubapi.com/crm/v4/associations/deals/companies/batch/read", companies_associations_responses ) @@ -497,7 +508,7 @@ def test_associations_extractor_with_permissions_error(requests_mock, config, co entity="deals", associations_list=["companies", "contacts"], decoder=JsonDecoder(parameters={}), - config=config, + config=oauth_config, parameters={}, ) @@ -510,6 +521,38 @@ def test_associations_extractor_with_permissions_error(requests_mock, config, co assert records[1]["companies"] == ["888"] +def test_associations_extractor_with_permissions_error_pat(requests_mock, config, components_module): + """With PAT credentials, a 401 on associations should fail immediately (no retry).""" + response = requests.Response() + response._content = ( + b'{"results": [{"id": "123", "updatedAt": "2022-02-25T16:43:11Z"}, {"id": "456", "updatedAt": "2022-02-25T16:43:11Z"}]}' + ) + response.status_code = 200 + + companies_associations_responses = [ + {"json": {"error": "The OAuth token used to make this call expired 0 second(s) ago."}, "status_code": 401}, + ] + + requests_mock.register_uri( + "POST", "https://api.hubapi.com/crm/v4/associations/deals/companies/batch/read", companies_associations_responses + ) + requests_mock.register_uri( + "POST", "https://api.hubapi.com/crm/v4/associations/deals/contacts/batch/read", [{"json": {"results": []}, "status_code": 200}] + ) + + extractor = components_module.HubspotAssociationsExtractor( + field_path=["results"], + entity="deals", + associations_list=["companies", "contacts"], + decoder=JsonDecoder(parameters={}), + config=config, + parameters={}, + ) + + with pytest.raises(AirbyteTracedException, match="Please, update you Private App access token"): + list(extractor.extract_records(response=response)) + + def test_extractor_supports_entity_interpolation(config, components_module): parameters = {"entity": "engagements_emails"} @@ -650,3 +693,89 @@ def test_crm_search_pagination_strategy( ) assert actual_next_page_token == expected_next_page_token + + +@pytest.mark.parametrize( + "credentials_title, status_code, expected_action, expected_failure_type, expected_error_message", + [ + pytest.param( + "Private App Credentials", + 401, + ResponseAction.FAIL, + FailureType.config_error, + "Please, update you Private App access token. Current token is invalid or expired.", + id="pat_401_fails_immediately", + ), + pytest.param( + "OAuth Credentials", + 401, + ResponseAction.REFRESH_TOKEN_THEN_RETRY, + None, + None, + id="oauth_401_refreshes_token_then_retries", + ), + pytest.param( + "Private App Credentials", + 429, + ResponseAction.RETRY, + None, + None, + id="pat_429_retries_normally", + ), + pytest.param( + "Private App Credentials", + 200, + ResponseAction.SUCCESS, + None, + None, + id="pat_200_succeeds", + ), + ], +) +def test_hubspot_error_handler_401_by_auth_type( + credentials_title, status_code, expected_action, expected_failure_type, expected_error_message +): + """Verify that 401 with PAT credentials fails immediately while 401 with OAuth retries.""" + components_module = __import__("components") + + config = { + "start_date": "2021-01-10T00:00:00Z", + "credentials": {"credentials_title": credentials_title, "access_token": "test_access_token"}, + } + parameters = {} + + error_handler = components_module.HubspotErrorHandler( + backoff_strategies=[], + response_filters=[ + HttpResponseFilter( + action="RETRY", + http_codes={429}, + error_message="Rate limited.", + config=config, + parameters=parameters, + ), + HttpResponseFilter( + action="REFRESH_TOKEN_THEN_RETRY", + http_codes={401}, + error_message="Authentication to HubSpot has expired.", + config=config, + parameters=parameters, + ), + ], + config=config, + parameters=parameters, + ) + + response = Mock(spec=requests.Response) + response.status_code = status_code + response.ok = status_code == 200 + response.headers = {} + response.json.return_value = {} + + resolution = error_handler.interpret_response(response) + + assert resolution.response_action == expected_action + if expected_failure_type is not None: + assert resolution.failure_type == expected_failure_type + if expected_error_message is not None: + assert resolution.error_message == expected_error_message diff --git a/airbyte-integrations/connectors/source-hubspot/unit_tests/test_handle_retry_token_expired.py b/airbyte-integrations/connectors/source-hubspot/unit_tests/test_handle_retry_token_expired.py index 8a2135c6f7d4..3dd43a6bd153 100644 --- a/airbyte-integrations/connectors/source-hubspot/unit_tests/test_handle_retry_token_expired.py +++ b/airbyte-integrations/connectors/source-hubspot/unit_tests/test_handle_retry_token_expired.py @@ -4,7 +4,7 @@ import pytest -from airbyte_cdk.sources.streams.http.http_client import MessageRepresentationAirbyteTracedErrors +from airbyte_cdk.utils.traced_exception import AirbyteTracedException from .conftest import find_stream @@ -42,7 +42,7 @@ def test_handle_request_with_retry_token_expired(config, requests_mock): partitions = list(stream_instance._stream_partition_generator.generate()) assert len(partitions) == 1 - with pytest.raises(MessageRepresentationAirbyteTracedErrors): + with pytest.raises(AirbyteTracedException): list(partitions[0].read()) # 5 default retries + first call assert rate_limited_mock.call_count == 6 diff --git a/airbyte-integrations/connectors/source-hubspot/unit_tests/test_streams.py b/airbyte-integrations/connectors/source-hubspot/unit_tests/test_streams.py index c75832d6d54e..a1e5aff537bd 100644 --- a/airbyte-integrations/connectors/source-hubspot/unit_tests/test_streams.py +++ b/airbyte-integrations/connectors/source-hubspot/unit_tests/test_streams.py @@ -434,7 +434,6 @@ def match_request_body(request): @pytest.mark.parametrize( "error_response", [ - {"json": {}, "status_code": 401}, {"json": {}, "status_code": 429}, {"json": {}, "status_code": 502}, {"json": {}, "status_code": 504}, diff --git a/docs/integrations/sources/hubspot.md b/docs/integrations/sources/hubspot.md index 6b4e0730194a..7ed65cd2e634 100644 --- a/docs/integrations/sources/hubspot.md +++ b/docs/integrations/sources/hubspot.md @@ -336,6 +336,7 @@ If you use [custom properties](https://knowledge.hubspot.com/properties/create-a | Version | Date | Pull Request | Subject | |:------------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 6.3.3 | 2026-03-25 | [75452](https://github.com/airbytehq/airbyte/pull/75452) | Fixed HTTP 401 errors retrying indefinitely for Private App Token authentication | | 6.3.2 | 2026-03-17 | [74526](https://github.com/airbytehq/airbyte/pull/74526) | Update dependencies | | 6.3.1 | 2026-03-09 | [74410](https://github.com/airbytehq/airbyte/pull/74410) | Promoting release candidate 6.3.1-rc.1 to a main version. | | 6.3.1-rc.1 | 2026-03-03 | [74032](https://github.com/airbytehq/airbyte/pull/74032) | fix(source-hubspot): use v3 properties API for CRM search streams | From caa7e82be9ad49cbf85f396ac557033c6fb54da5 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 14:37:33 +0000 Subject: [PATCH 006/379] docs(source-hubspot): add 401 troubleshooting guidance and fix changelog date (#75503) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- docs/integrations/sources/hubspot.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/integrations/sources/hubspot.md b/docs/integrations/sources/hubspot.md index 7ed65cd2e634..dc73843f0b89 100644 --- a/docs/integrations/sources/hubspot.md +++ b/docs/integrations/sources/hubspot.md @@ -308,6 +308,12 @@ If you use [custom properties](https://knowledge.hubspot.com/properties/create-a } ``` +- **401 Unauthorized Error (Private App Token)** + + If you authenticate using a Private App access token and receive a 401 Unauthorized error, the connector fails immediately with a configuration error asking you to update your token. Private App tokens are static and cannot be refreshed, so retrying won't help. To resolve this, generate a new access token in your [HubSpot Private App settings](https://developers.hubspot.com/docs/api/private-apps) and update the connector configuration. + + If you authenticate using OAuth, the connector automatically refreshes expired tokens and retries the request. No action is needed unless the error persists, in which case you should re-authenticate the connector. + - **403 Forbidden Error** - Hubspot has **scopes** for each API call. @@ -336,7 +342,7 @@ If you use [custom properties](https://knowledge.hubspot.com/properties/create-a | Version | Date | Pull Request | Subject | |:------------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 6.3.3 | 2026-03-25 | [75452](https://github.com/airbytehq/airbyte/pull/75452) | Fixed HTTP 401 errors retrying indefinitely for Private App Token authentication | +| 6.3.3 | 2026-03-26 | [75452](https://github.com/airbytehq/airbyte/pull/75452) | Fixed HTTP 401 errors retrying indefinitely for Private App Token authentication | | 6.3.2 | 2026-03-17 | [74526](https://github.com/airbytehq/airbyte/pull/74526) | Update dependencies | | 6.3.1 | 2026-03-09 | [74410](https://github.com/airbytehq/airbyte/pull/74410) | Promoting release candidate 6.3.1-rc.1 to a main version. | | 6.3.1-rc.1 | 2026-03-03 | [74032](https://github.com/airbytehq/airbyte/pull/74032) | fix(source-hubspot): use v3 properties API for CRM search streams | From 2019a0a9b16debe27697b40402825c94bf8095b1 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 14:37:39 +0000 Subject: [PATCH 007/379] docs(source-marketo): update Programs stream description with Salesforce fields (#75499) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- docs/integrations/sources/marketo.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/sources/marketo.md b/docs/integrations/sources/marketo.md index 0a7ca78b8236..278c8efd22ae 100644 --- a/docs/integrations/sources/marketo.md +++ b/docs/integrations/sources/marketo.md @@ -89,7 +89,7 @@ This connector syncs the following streams from Marketo: | **[Emails](https://experienceleague.adobe.com/en/docs/marketo-developer/marketo/rest/assets/emails)** | Incremental | Marketo email assets, including subject, sender info, status, and template. Uses `updatedAt` as the cursor field. | | **[Leads](https://developers.marketo.com/rest-api/endpoint-reference/lead-database-endpoint-reference/#!/Leads/getLeadByIdUsingGET)** | Incremental | Marketo leads. Uses `updatedAt` as the cursor field. The schema is dynamically generated from the `leads/describe.json` API, so custom fields are automatically discovered and included. | | **[Lists](https://developers.marketo.com/rest-api/endpoint-reference/lead-database-endpoint-reference/#!/Static_Lists/getListByIdUsingGET)** | Incremental | Marketo static lists. Uses `createdAt` as the cursor field. | -| **[Programs](https://developers.marketo.com/rest-api/endpoint-reference/asset-endpoint-reference/#!/Programs/browseProgramsUsingGET)** | Incremental | Marketo programs, including user-defined tags and period costs. Uses `updatedAt` as the cursor field. | +| **[Programs](https://developers.marketo.com/rest-api/endpoint-reference/asset-endpoint-reference/#!/Programs/browseProgramsUsingGET)** | Incremental | Marketo programs, including user-defined tags, period costs, and Salesforce cross-reference fields (`sfdcId` and `sfdcName`) for programs synced with Salesforce. Uses `updatedAt` as the cursor field. | | **[Program Tokens](https://experienceleague.adobe.com/en/docs/marketo-developer/marketo/rest/assets/tokens)** | Full Refresh | Token definitions (My Tokens) for each program. This is a child stream of Programs, fetching tokens for every program. | | **[Segmentations](https://developers.marketo.com/rest-api/endpoint-reference/asset-endpoint-reference/#!/Segments/getSegmentationUsingGET)** | Full Refresh | Marketo segmentations. | From 6c7ed8fcd48b43f9665248e58e20f1570477eb5a Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 21:19:37 +0530 Subject: [PATCH 008/379] fix(destination-redshift): fix null sqlState causing misleading SSH error on connection check (#75286) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Aaron ("AJ") Steers Co-authored-by: Subodh Kant Chaturvedi --- .../destination-redshift/metadata.yaml | 2 +- .../redshift/RedshiftDestination.kt | 3 +-- docs/integrations/destinations/redshift.md | 23 ++++++++++--------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/airbyte-integrations/connectors/destination-redshift/metadata.yaml b/airbyte-integrations/connectors/destination-redshift/metadata.yaml index 8b7025819f2e..7ec3daafa4c1 100644 --- a/airbyte-integrations/connectors/destination-redshift/metadata.yaml +++ b/airbyte-integrations/connectors/destination-redshift/metadata.yaml @@ -41,7 +41,7 @@ data: type: GSM connectorType: destination definitionId: f7a7d195-377f-cf5b-70a5-be6b819019dc - dockerImageTag: 3.5.3 + dockerImageTag: 3.5.4 dockerRepository: airbyte/destination-redshift documentationUrl: https://docs.airbyte.com/integrations/destinations/redshift githubIssueLabel: destination-redshift diff --git a/airbyte-integrations/connectors/destination-redshift/src/main/kotlin/io/airbyte/integrations/destination/redshift/RedshiftDestination.kt b/airbyte-integrations/connectors/destination-redshift/src/main/kotlin/io/airbyte/integrations/destination/redshift/RedshiftDestination.kt index 3b9a98f93871..5673001fdd86 100644 --- a/airbyte-integrations/connectors/destination-redshift/src/main/kotlin/io/airbyte/integrations/destination/redshift/RedshiftDestination.kt +++ b/airbyte-integrations/connectors/destination-redshift/src/main/kotlin/io/airbyte/integrations/destination/redshift/RedshiftDestination.kt @@ -241,8 +241,7 @@ class RedshiftDestination : BaseConnector(), Destination { return AirbyteConnectionStatus().withStatus(AirbyteConnectionStatus.Status.SUCCEEDED) } catch (e: SQLException) { - // copied from AbstractJdbcDestination's attemptTableOperations - val stateCode: String = e.sqlState + val stateCode: String? = e.sqlState val errorCode: Int val exceptionMessage: String? if (Objects.isNull(e.cause) || e.cause !is SQLException) { diff --git a/docs/integrations/destinations/redshift.md b/docs/integrations/destinations/redshift.md index ecac7ce72ae9..efb58aa28efb 100644 --- a/docs/integrations/destinations/redshift.md +++ b/docs/integrations/destinations/redshift.md @@ -233,6 +233,7 @@ This destination supports [namespaces](https://docs.airbyte.com/platform/using-a | Version | Date | Pull Request | Subject | | :------ | :--------- | :--------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 3.5.4 | 2026-03-23 | [75286](https://github.com/airbytehq/airbyte/pull/75286) | Fix misleading SSH error when SQLException has null sqlState during connection check | | 3.5.3 | 2025-03-24 | [56355](https://github.com/airbytehq/airbyte/pull/56355) | Upgrade to airbyte/java-connector-base:2.0.1 to be M4 compatible. | | 3.5.2 | 2025-01-14 | [51500](https://github.com/airbytehq/airbyte/pull/51500) | Use a non root base image | | 3.5.1 | 2025-01-06 | [49903](https://github.com/airbytehq/airbyte/pull/49903) | Use a base image: airbyte/java-connector-base:1.0.0 | @@ -240,17 +241,17 @@ This destination supports [namespaces](https://docs.airbyte.com/platform/using-a | 3.4.4 | 2024-08-20 | [44476](https://github.com/airbytehq/airbyte/pull/44476) | Increase message parsing limit to 100mb | | 3.4.3 | 2024-08-22 | [44526](https://github.com/airbytehq/airbyte/pull/44526) | Revert protocol compliance fix | | 3.4.2 | 2024-08-15 | [42506](https://github.com/airbytehq/airbyte/pull/42506) | Fix bug in refreshes logic (already mitigated in platform, just fixing protocol compliance) | -| 3.4.1 | 2024-08-14 | [44020](https://github.com/airbytehq/airbyte/pull/44020) | Simplify Redshift Options | -| 3.4.0 | 2024-07-23 | [42445](https://github.com/airbytehq/airbyte/pull/42445) | Respect the `drop cascade` option on raw tables | -| 3.3.1 | 2024-07-15 | [41968](https://github.com/airbytehq/airbyte/pull/41968) | Don't hang forever on empty stream list; shorten error message on INCOMPLETE stream status | -| 3.3.0 | 2024-07-02 | [40567](https://github.com/airbytehq/airbyte/pull/40567) | Support for [refreshes](../../platform/operator-guides/refreshes) and resumable full refresh. WARNING: You must upgrade to platform 0.63.7 before upgrading to this connector version. | -| 3.2.0 | 2024-07-02 | [40201](https://github.com/airbytehq/airbyte/pull/40201) | Add `_airbyte_generation_id` column, and add `sync_id` to `_airbyte_meta` column | -| 3.1.1 | 2024-06-26 | [39008](https://github.com/airbytehq/airbyte/pull/39008) | Internal code changes | -| 3.1.0 | 2024-06-26 | [39141](https://github.com/airbytehq/airbyte/pull/39141) | Remove nonfunctional "encrypted staging" option | -| 3.0.0 | 2024-06-04 | [38886](https://github.com/airbytehq/airbyte/pull/38886) | Remove standard inserts mode | -| 2.6.4 | 2024-05-31 | [38825](https://github.com/airbytehq/airbyte/pull/38825) | Adopt CDK 0.35.15 | -| 2.6.3 | 2024-05-31 | [38803](https://github.com/airbytehq/airbyte/pull/38803) | Source auto-conversion to Kotlin | -| 2.6.2 | 2024-05-14 | [38189](https://github.com/airbytehq/airbyte/pull/38189) | adding an option to DROP CASCADE on resets | +| 3.4.1 | 2024-08-14 | [44020](https://github.com/airbytehq/airbyte/pull/44020) | Simplify Redshift Options | +| 3.4.0 | 2024-07-23 | [42445](https://github.com/airbytehq/airbyte/pull/42445) | Respect the `drop cascade` option on raw tables | +| 3.3.1 | 2024-07-15 | [41968](https://github.com/airbytehq/airbyte/pull/41968) | Don't hang forever on empty stream list; shorten error message on INCOMPLETE stream status | +| 3.3.0 | 2024-07-02 | [40567](https://github.com/airbytehq/airbyte/pull/40567) | Support for [refreshes](../../platform/operator-guides/refreshes) and resumable full refresh. WARNING: You must upgrade to platform 0.63.7 before upgrading to this connector version. | +| 3.2.0 | 2024-07-02 | [40201](https://github.com/airbytehq/airbyte/pull/40201) | Add `_airbyte_generation_id` column, and add `sync_id` to `_airbyte_meta` column | +| 3.1.1 | 2024-06-26 | [39008](https://github.com/airbytehq/airbyte/pull/39008) | Internal code changes | +| 3.1.0 | 2024-06-26 | [39141](https://github.com/airbytehq/airbyte/pull/39141) | Remove nonfunctional "encrypted staging" option | +| 3.0.0 | 2024-06-04 | [38886](https://github.com/airbytehq/airbyte/pull/38886) | Remove standard inserts mode | +| 2.6.4 | 2024-05-31 | [38825](https://github.com/airbytehq/airbyte/pull/38825) | Adopt CDK 0.35.15 | +| 2.6.3 | 2024-05-31 | [38803](https://github.com/airbytehq/airbyte/pull/38803) | Source auto-conversion to Kotlin | +| 2.6.2 | 2024-05-14 | [38189](https://github.com/airbytehq/airbyte/pull/38189) | adding an option to DROP CASCADE on resets | | 2.6.1 | 2024-05-13 | [\#38126](https://github.com/airbytehq/airbyte/pull/38126) | Adapt to signature changes in `StreamConfig` | | 2.6.0 | 2024-05-08 | [\#37713](https://github.com/airbytehq/airbyte/pull/37713) | Remove option for incremental typing and deduping | | 2.5.0 | 2024-05-06 | [\#34613](https://github.com/airbytehq/airbyte/pull/34613) | Upgrade Redshift driver to work with Cluster patch 181; Adapt to CDK 0.33.0; Minor signature changes | From 0d73b296323ccfb302d1c1908136c14807322863 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 11:02:02 -0500 Subject: [PATCH 009/379] chore(source-typeform): bump SDM base image to 7.13.0 (#75506) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk Co-authored-by: Alfredo Garcia --- .../connectors/source-typeform/metadata.yaml | 6 ++++-- docs/integrations/sources/typeform.md | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-typeform/metadata.yaml b/airbyte-integrations/connectors/source-typeform/metadata.yaml index 3afb333a3d2c..808a7b46682e 100644 --- a/airbyte-integrations/connectors/source-typeform/metadata.yaml +++ b/airbyte-integrations/connectors/source-typeform/metadata.yaml @@ -6,11 +6,11 @@ data: hosts: - api.typeform.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.10.1@sha256:bd69f6b52bdd92ce06c30786d67546427b828ffb553363c8950b2816c552d6e0 + baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0.post30.dev23303933335@sha256:266dda691d2928e00adc6401ac43823be107b5ae39364047ce03d4031c95e1cd connectorSubtype: api connectorType: source definitionId: e7eff203-90bf-43e5-a240-19ea3056c474 - dockerImageTag: 1.4.6 + dockerImageTag: 1.4.7-rc.1 dockerRepository: airbyte/source-typeform documentationUrl: https://docs.airbyte.com/integrations/sources/typeform externalDocumentationUrls: @@ -34,6 +34,8 @@ data: releaseDate: 2021-07-10 releaseStage: generally_available releases: + rolloutConfiguration: + enableProgressiveRollout: true breakingChanges: 1.1.0: message: diff --git a/docs/integrations/sources/typeform.md b/docs/integrations/sources/typeform.md index 3ca4e313f8e3..cf854fb4258e 100644 --- a/docs/integrations/sources/typeform.md +++ b/docs/integrations/sources/typeform.md @@ -101,6 +101,7 @@ API rate limits \(2 requests per second\): [https://developer.typeform.com/get-s | Version | Date | Pull Request | Subject | |:--------|:-----------|:---------------------------------------------------------|:------------------------------------------------------------------------------------------------| +| 1.4.7-rc.1 | 2026-03-26 | [75506](https://github.com/airbytehq/airbyte/pull/75506) | Upgrade CDK version to 7.13.0 | | 1.4.6 | 2026-03-03 | [61473](https://github.com/airbytehq/airbyte/pull/61473) | Update dependencies | | 1.4.5 | 2026-01-22 | [72261](https://github.com/airbytehq/airbyte/pull/72261) | Update CDK version from 7.0.1 to 7.6.5 | | 1.4.4 | 2025-10-22 | [68591](https://github.com/airbytehq/airbyte/pull/68591) | Add `suggestedStreams` | From 40ae1ef357d07402e140e1b7d53a40bc5f5a4ce3 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 16:31:56 +0000 Subject: [PATCH 010/379] docs(source-typeform): improve setup guide, prerequisites, and performance documentation (#75510) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- docs/integrations/sources/typeform.md | 62 +++++++++++++-------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/docs/integrations/sources/typeform.md b/docs/integrations/sources/typeform.md index cf854fb4258e..9440fabdf7e2 100644 --- a/docs/integrations/sources/typeform.md +++ b/docs/integrations/sources/typeform.md @@ -1,23 +1,15 @@ # Typeform -This page guides you through the process of setting up the Typeform source connector. +This page contains the setup guide and reference information for the [Typeform](https://www.typeform.com/) source connector. ## Prerequisites -- [Typeform Account](https://www.typeform.com/) -- Form IDs (Optional) - If you want to sync data for specific forms, you'll need to have the IDs of those forms. If you want to sync data for all forms in your account you don't need any IDs. Form IDs can be found in the URLs to the forms in Typeform Admin Panel (for example, for URL `https://admin.typeform.com/form/12345/` a `12345` part would your Form ID) - - - **For Airbyte Cloud:** - -- OAuth +- A [Typeform](https://www.typeform.com/) account + +- For Airbyte Cloud: OAuth authentication - - -**For Airbyte Open Source:** - -- Personal Access Token (see [personal access token](https://www.typeform.com/developers/get-started/personal-access-token/)) +- For Airbyte Open Source: A Typeform [personal access token](https://www.typeform.com/developers/get-started/personal-access-token/) with the following read scopes: `forms:read`, `responses:read`, `webhooks:read`, `workspaces:read`, `images:read`, and `themes:read` ## Setup guide @@ -27,21 +19,24 @@ This page guides you through the process of setting up the Typeform source conne **For Airbyte Open Source:** -To get the API token for your application, follow these [steps](https://developer.typeform.com/get-started/personal-access-token/): -1. Log in to your account at Typeform. -2. In the upper-right corner, in the drop-down menu next to your profile photo, click **My Account**. +To generate a personal access token for your Typeform account: + +1. Log in to your [Typeform](https://www.typeform.com/) account. +2. In the upper-left corner, in the drop-down menu next to your username, click **Account**. 3. In the left menu, click **Personal tokens**. 4. Click **Generate a new token**. 5. In the **Token name** field, type a name for the token to help you identify it. -6. Choose the scopes you need (API actions this token can perform). See [OAuth 2.0 scopes](https://www.typeform.com/developers/get-started/scopes/) for more details. +6. Select the following scopes: `forms:read`, `responses:read`, `webhooks:read`, `workspaces:read`, `images:read`, and `themes:read`. See [OAuth scopes](https://www.typeform.com/developers/get-started/scopes/) for details. 7. Click **Generate token**. + **For Airbyte Cloud:** -This step is not needed in Airbyte Cloud. Skip to the next step. + +Skip this step. Airbyte Cloud uses OAuth to authenticate with Typeform. @@ -54,11 +49,11 @@ This step is not needed in Airbyte Cloud. Skip to the next step. 1. [Log into your Airbyte Cloud](https://cloud.airbyte.com/workspaces) account. 2. In the left navigation bar, click **Sources**. In the top-right corner, click **+ New Source**. 3. On the source setup page, select **Typeform** from the Source type dropdown and enter a name for this connector. -4. Click `Authenticate your Typeform account` by selecting Oauth or Personal Access Token for Authentication. -5. Log in and Authorize to the Typeform account. -6. **Start date (Optional)** - The date from which to start fetching Responses stream data, in the format `YYYY-MM-DDT00:00:00Z`. If not set, the Responses stream fetches data from one year ago. -7. **Form IDs (Optional)** - List of Form IDs to sync. If not specified, all forms in your account are synced. -8. Click **Set up source**. +4. Click **Authenticate your Typeform account** and complete the OAuth flow. +5. **Start date** (Optional) - The date from which you want to replicate data for the Responses stream, in the format `YYYY-MM-DDT00:00:00Z`. If not set, the connector fetches response data from one year before the current date. +6. **Form IDs** (Optional) - IDs of specific forms to sync. If not specified, the connector syncs all forms in your account. You can find form IDs in your form URLs on the **Share** panel. For example, in the URL `https://mysite.typeform.com/to/u6nXL7`, the form ID is `u6nXL7`. +7. Click **Set up source**. + @@ -67,15 +62,18 @@ This step is not needed in Airbyte Cloud. Skip to the next step. 1. Go to your local Airbyte instance. 2. In the left navigation bar, click **Sources**. In the top-right corner, click **+ New Source**. -3. On the Set up the source page, enter a name for the connector and select **Typeform** from the Source type dropdown. -4. Enter your **API Token** and optionally set a **Start Date**. -5. Click **Set up source**. +3. On the source setup page, enter a name for the connector and select **Typeform** from the Source type dropdown. +4. Enter your personal access token in the **API Token** field. +5. **Start date** (Optional) - The date from which you want to replicate data for the Responses stream, in the format `YYYY-MM-DDT00:00:00Z`. If not set, the connector fetches response data from one year before the current date. +6. **Form IDs** (Optional) - IDs of specific forms to sync. If not specified, the connector syncs all forms in your account. You can find form IDs in your form URLs on the **Share** panel. For example, in the URL `https://mysite.typeform.com/to/u6nXL7`, the form ID is `u6nXL7`. +7. Click **Set up source**. + ## Supported streams and sync modes | Stream | Key | Incremental | API Link | -| :--------- | ----------- | :---------- | --------------------------------------------------------------------------- | +| :--------- | :---------- | :---------- | :-------------------------------------------------------------------------- | | Forms | id | No | https://developer.typeform.com/create/reference/retrieve-form/ | | Responses | response_id | Yes | https://developer.typeform.com/responses/reference/retrieve-responses | | Webhooks | id | No | https://developer.typeform.com/webhooks/reference/retrieve-webhooks/ | @@ -85,14 +83,14 @@ This step is not needed in Airbyte Cloud. Skip to the next step. ## Performance considerations -Typeform API page size limit per source: +The Typeform API enforces a rate limit of 2 requests per second per account. The connector respects this limit automatically. For more information, see the [Typeform API rate limits documentation](https://developer.typeform.com/get-started/#rate-limits). -- Forms - 200 -- Responses - 1000 +Page size limits per stream: -The connector performs an additional API call to fetch all form IDs in your account using the [retrieve forms endpoint](https://developer.typeform.com/create/reference/retrieve-forms/). +- Forms: 200 +- Responses: 1000 -API rate limits \(2 requests per second\): [https://developer.typeform.com/get-started/\#rate-limits](https://developer.typeform.com/get-started/#rate-limits) +The connector makes an additional API call per sync to fetch the list of form IDs in your account using the [retrieve forms endpoint](https://developer.typeform.com/create/reference/retrieve-forms/). ## Changelog From 510f53ad5ecf400b1e020fb04e35bf37a576f408 Mon Sep 17 00:00:00 2001 From: "Ryan Br..." Date: Thu, 26 Mar 2026 10:23:17 -0700 Subject: [PATCH 011/379] =?UTF-8?q?fix:=20upgrade=20dest=20postgres=20CDK?= =?UTF-8?q?=20to=201.0.6.=20Fix=20duplicate=20records=20in=20dedup+tr?= =?UTF-8?q?=E2=80=A6=20(#75481)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../connectors/destination-postgres/gradle.properties | 2 +- .../connectors/destination-postgres/metadata.yaml | 2 +- docs/integrations/destinations/postgres.md | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/destination-postgres/gradle.properties b/airbyte-integrations/connectors/destination-postgres/gradle.properties index 2c1bedf37f4f..69b1a029e4c6 100644 --- a/airbyte-integrations/connectors/destination-postgres/gradle.properties +++ b/airbyte-integrations/connectors/destination-postgres/gradle.properties @@ -1,4 +1,4 @@ -cdkVersion=1.0.2 +cdkVersion=1.0.6 # our testcontainer has issues with too much concurrency. # 4 threads seems to be the sweet spot. testExecutionConcurrency=4 diff --git a/airbyte-integrations/connectors/destination-postgres/metadata.yaml b/airbyte-integrations/connectors/destination-postgres/metadata.yaml index cfa7045bf94c..9b883e30fe51 100644 --- a/airbyte-integrations/connectors/destination-postgres/metadata.yaml +++ b/airbyte-integrations/connectors/destination-postgres/metadata.yaml @@ -6,7 +6,7 @@ data: connectorSubtype: database connectorType: destination definitionId: 25c5221d-dce2-4163-ade9-739ef790f503 - dockerImageTag: 3.0.11 + dockerImageTag: 3.0.12 dockerRepository: airbyte/destination-postgres documentationUrl: https://docs.airbyte.com/integrations/destinations/postgres githubIssueLabel: destination-postgres diff --git a/docs/integrations/destinations/postgres.md b/docs/integrations/destinations/postgres.md index fd879c0fa3ad..a8fdc93551c0 100644 --- a/docs/integrations/destinations/postgres.md +++ b/docs/integrations/destinations/postgres.md @@ -298,6 +298,7 @@ This destination supports [namespaces](https://docs.airbyte.com/platform/using-a | Version | Date | Pull Request | Subject | |:--------|:-----------|:-----------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 3.0.12 | 2026-03-25 | | Upgrade CDK to 1.0.6; fix duplicate records in dedup+truncate mode by dropping temp tables after successful upsert | | 3.0.11 | 2026-02-25 | | Upgrade CDK to 1.0.2 and base image to 2.0.4 for CVE patches | | 3.0.10 | 2026-02-04 | [72858](https://github.com/airbytehq/airbyte/pull/72858) | Upgrade CDK to 0.2.8 | | 3.0.9 | 2026-01-28 | [72292](https://github.com/airbytehq/airbyte/pull/72292) | Upgrade CDK to 0.2.0 | From 03f92b5eb5b3e5da235c6fce626f5d78ad4529d6 Mon Sep 17 00:00:00 2001 From: "octavia-bot[bot]" <108746235+octavia-bot[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 20:15:26 +0000 Subject: [PATCH 012/379] docs: sync agent connector docs from airbyte-agent-connectors repo (#75519) Co-authored-by: ian-at-airbyte <187576150+ian-at-airbyte@users.noreply.github.com> --- docs/ai-agents/connectors/airtable/README.md | 4 ++-- docs/ai-agents/connectors/amazon-ads/README.md | 4 ++-- docs/ai-agents/connectors/amazon-seller-partner/README.md | 4 ++-- docs/ai-agents/connectors/amplitude/README.md | 4 ++-- docs/ai-agents/connectors/asana/README.md | 4 ++-- docs/ai-agents/connectors/ashby/README.md | 4 ++-- docs/ai-agents/connectors/chargebee/README.md | 4 ++-- docs/ai-agents/connectors/clickup-api/README.md | 4 ++-- docs/ai-agents/connectors/confluence/README.md | 4 ++-- docs/ai-agents/connectors/facebook-marketing/README.md | 4 ++-- docs/ai-agents/connectors/freshdesk/README.md | 4 ++-- docs/ai-agents/connectors/github/README.md | 4 ++-- docs/ai-agents/connectors/gitlab/README.md | 4 ++-- docs/ai-agents/connectors/gmail/README.md | 4 ++-- docs/ai-agents/connectors/gong/README.md | 4 ++-- docs/ai-agents/connectors/google-ads/README.md | 4 ++-- docs/ai-agents/connectors/google-analytics-data-api/README.md | 4 ++-- docs/ai-agents/connectors/google-drive/README.md | 4 ++-- docs/ai-agents/connectors/google-search-console/README.md | 4 ++-- docs/ai-agents/connectors/granola/README.md | 4 ++-- docs/ai-agents/connectors/greenhouse/README.md | 4 ++-- docs/ai-agents/connectors/harvest/README.md | 4 ++-- docs/ai-agents/connectors/hubspot/README.md | 4 ++-- docs/ai-agents/connectors/incident-io/README.md | 4 ++-- docs/ai-agents/connectors/intercom/README.md | 4 ++-- docs/ai-agents/connectors/jira/README.md | 4 ++-- docs/ai-agents/connectors/klaviyo/README.md | 4 ++-- docs/ai-agents/connectors/linear/README.md | 4 ++-- docs/ai-agents/connectors/linkedin-ads/README.md | 4 ++-- docs/ai-agents/connectors/mailchimp/README.md | 4 ++-- docs/ai-agents/connectors/monday/README.md | 4 ++-- docs/ai-agents/connectors/notion/README.md | 4 ++-- docs/ai-agents/connectors/orb/README.md | 4 ++-- docs/ai-agents/connectors/paypal-transaction/README.md | 4 ++-- docs/ai-agents/connectors/pinterest/README.md | 4 ++-- docs/ai-agents/connectors/pylon/README.md | 4 ++-- docs/ai-agents/connectors/salesforce/README.md | 4 ++-- docs/ai-agents/connectors/sendgrid/README.md | 4 ++-- docs/ai-agents/connectors/sentry/README.md | 4 ++-- docs/ai-agents/connectors/shopify/README.md | 4 ++-- docs/ai-agents/connectors/slack/README.md | 4 ++-- docs/ai-agents/connectors/snapchat-marketing/README.md | 4 ++-- docs/ai-agents/connectors/stripe/README.md | 4 ++-- docs/ai-agents/connectors/tiktok-marketing/README.md | 4 ++-- docs/ai-agents/connectors/twilio/README.md | 4 ++-- docs/ai-agents/connectors/typeform/README.md | 4 ++-- docs/ai-agents/connectors/woocommerce/README.md | 4 ++-- docs/ai-agents/connectors/zendesk-chat/README.md | 4 ++-- docs/ai-agents/connectors/zendesk-support/README.md | 4 ++-- docs/ai-agents/connectors/zendesk-talk/README.md | 4 ++-- docs/ai-agents/connectors/zoho-crm/README.md | 4 ++-- 51 files changed, 102 insertions(+), 102 deletions(-) diff --git a/docs/ai-agents/connectors/airtable/README.md b/docs/ai-agents/connectors/airtable/README.md index 779320f5e09a..8a8317545e52 100644 --- a/docs/ai-agents/connectors/airtable/README.md +++ b/docs/ai-agents/connectors/airtable/README.md @@ -109,7 +109,7 @@ See the official [Airtable API reference](https://airtable.com/developers/web/ap ## Version information -- **Package version:** 0.1.49 +- **Package version:** 0.1.50 - **Connector version:** 1.0.6 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/airtable/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/amazon-ads/README.md b/docs/ai-agents/connectors/amazon-ads/README.md index 238e5fe584ba..e64b0b4f15cc 100644 --- a/docs/ai-agents/connectors/amazon-ads/README.md +++ b/docs/ai-agents/connectors/amazon-ads/README.md @@ -108,7 +108,7 @@ See the official [Amazon-Ads API reference](https://advertising.amazon.com/API/d ## Version information -- **Package version:** 0.1.68 +- **Package version:** 0.1.69 - **Connector version:** 1.0.9 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/amazon-ads/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/amazon-seller-partner/README.md b/docs/ai-agents/connectors/amazon-seller-partner/README.md index 3413b8fe66bc..7975acd0813d 100644 --- a/docs/ai-agents/connectors/amazon-seller-partner/README.md +++ b/docs/ai-agents/connectors/amazon-seller-partner/README.md @@ -113,7 +113,7 @@ See the official [Amazon-Seller-Partner API reference](https://developer-docs.am ## Version information -- **Package version:** 0.1.7 +- **Package version:** 0.1.8 - **Connector version:** 1.0.3 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/amazon-seller-partner/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/amplitude/README.md b/docs/ai-agents/connectors/amplitude/README.md index 18fe96a027dc..4a3a0e3c38d9 100644 --- a/docs/ai-agents/connectors/amplitude/README.md +++ b/docs/ai-agents/connectors/amplitude/README.md @@ -107,7 +107,7 @@ See the official [Amplitude API reference](https://www.docs.developers.amplitude ## Version information -- **Package version:** 0.1.9 +- **Package version:** 0.1.10 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/amplitude/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/asana/README.md b/docs/ai-agents/connectors/asana/README.md index 69f6ee793c0f..1e1ce762f91f 100644 --- a/docs/ai-agents/connectors/asana/README.md +++ b/docs/ai-agents/connectors/asana/README.md @@ -130,7 +130,7 @@ See the official [Asana API reference](https://developers.asana.com/reference/re ## Version information -- **Package version:** 0.19.123 +- **Package version:** 0.19.124 - **Connector version:** 0.1.16 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/asana/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/ashby/README.md b/docs/ai-agents/connectors/ashby/README.md index 0a22eb7f3c71..e9e1c092719f 100644 --- a/docs/ai-agents/connectors/ashby/README.md +++ b/docs/ai-agents/connectors/ashby/README.md @@ -119,7 +119,7 @@ See the official [Ashby API reference](https://developers.ashbyhq.com/reference) ## Version information -- **Package version:** 0.1.20 +- **Package version:** 0.1.21 - **Connector version:** 0.1.3 -- **Generated with Connector SDK commit SHA:** 6ad04bc3fb66fc474336c37d69c79fb843ea1609 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/ashby/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/chargebee/README.md b/docs/ai-agents/connectors/chargebee/README.md index 8330783060f1..69bbbe938a85 100644 --- a/docs/ai-agents/connectors/chargebee/README.md +++ b/docs/ai-agents/connectors/chargebee/README.md @@ -123,7 +123,7 @@ See the official [Chargebee API reference](https://apidocs.chargebee.com/docs/ap ## Version information -- **Package version:** 0.1.6 +- **Package version:** 0.1.7 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/chargebee/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/clickup-api/README.md b/docs/ai-agents/connectors/clickup-api/README.md index 064fd9360868..6bd3b7671d4f 100644 --- a/docs/ai-agents/connectors/clickup-api/README.md +++ b/docs/ai-agents/connectors/clickup-api/README.md @@ -135,7 +135,7 @@ See the official [Clickup-Api API reference](https://developer.clickup.com/refer ## Version information -- **Package version:** 0.1.6 +- **Package version:** 0.1.7 - **Connector version:** 0.1.2 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/clickup-api/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/confluence/README.md b/docs/ai-agents/connectors/confluence/README.md index 1b732b37807e..6b1fbde3d05d 100644 --- a/docs/ai-agents/connectors/confluence/README.md +++ b/docs/ai-agents/connectors/confluence/README.md @@ -113,7 +113,7 @@ See the official [Confluence API reference](https://developer.atlassian.com/clou ## Version information -- **Package version:** 0.1.5 +- **Package version:** 0.1.6 - **Connector version:** 1.0.0 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/confluence/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/facebook-marketing/README.md b/docs/ai-agents/connectors/facebook-marketing/README.md index 790c373def62..1e5ed24606bb 100644 --- a/docs/ai-agents/connectors/facebook-marketing/README.md +++ b/docs/ai-agents/connectors/facebook-marketing/README.md @@ -135,7 +135,7 @@ See the official [Facebook-Marketing API reference](https://developers.facebook. ## Version information -- **Package version:** 0.1.59 +- **Package version:** 0.1.60 - **Connector version:** 1.0.21 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/facebook-marketing/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/freshdesk/README.md b/docs/ai-agents/connectors/freshdesk/README.md index 05dea6455109..331d897cefc0 100644 --- a/docs/ai-agents/connectors/freshdesk/README.md +++ b/docs/ai-agents/connectors/freshdesk/README.md @@ -118,7 +118,7 @@ See the official [Freshdesk API reference](https://developers.freshdesk.com/api/ ## Version information -- **Package version:** 0.1.17 +- **Package version:** 0.1.18 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/freshdesk/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/github/README.md b/docs/ai-agents/connectors/github/README.md index 435be1b147a0..9d027b9ed120 100644 --- a/docs/ai-agents/connectors/github/README.md +++ b/docs/ai-agents/connectors/github/README.md @@ -134,7 +134,7 @@ See the official [Github API reference](https://docs.github.com/en/rest). ## Version information -- **Package version:** 0.18.124 +- **Package version:** 0.18.125 - **Connector version:** 0.1.17 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/github/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/gitlab/README.md b/docs/ai-agents/connectors/gitlab/README.md index c73889e5da7b..fd9e3bec4e27 100644 --- a/docs/ai-agents/connectors/gitlab/README.md +++ b/docs/ai-agents/connectors/gitlab/README.md @@ -120,7 +120,7 @@ See the official [Gitlab API reference](https://docs.gitlab.com/ee/api/rest/). ## Version information -- **Package version:** 0.1.6 +- **Package version:** 0.1.7 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/gitlab/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/gmail/README.md b/docs/ai-agents/connectors/gmail/README.md index 2509ca09655e..c0e7e50f25d1 100644 --- a/docs/ai-agents/connectors/gmail/README.md +++ b/docs/ai-agents/connectors/gmail/README.md @@ -133,7 +133,7 @@ See the official [Gmail API reference](https://developers.google.com/gmail/api/r ## Version information -- **Package version:** 0.1.21 +- **Package version:** 0.1.22 - **Connector version:** 0.1.3 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/gmail/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/gong/README.md b/docs/ai-agents/connectors/gong/README.md index 8518cff778cf..0967cb02c859 100644 --- a/docs/ai-agents/connectors/gong/README.md +++ b/docs/ai-agents/connectors/gong/README.md @@ -127,7 +127,7 @@ See the official [Gong API reference](https://gong.app.gong.io/settings/api/docu ## Version information -- **Package version:** 0.19.127 +- **Package version:** 0.19.128 - **Connector version:** 0.1.20 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/gong/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/google-ads/README.md b/docs/ai-agents/connectors/google-ads/README.md index cd23976ff9c1..ed2addc59ccd 100644 --- a/docs/ai-agents/connectors/google-ads/README.md +++ b/docs/ai-agents/connectors/google-ads/README.md @@ -122,7 +122,7 @@ See the official [Google-Ads API reference](https://developers.google.com/google ## Version information -- **Package version:** 0.1.17 +- **Package version:** 0.1.18 - **Connector version:** 1.0.6 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/google-ads/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/google-analytics-data-api/README.md b/docs/ai-agents/connectors/google-analytics-data-api/README.md index ce83bd4642b9..135fada7b1cc 100644 --- a/docs/ai-agents/connectors/google-analytics-data-api/README.md +++ b/docs/ai-agents/connectors/google-analytics-data-api/README.md @@ -122,7 +122,7 @@ See the official [Google-Analytics-Data-Api API reference](https://developers.go ## Version information -- **Package version:** 0.1.12 +- **Package version:** 0.1.13 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/google-analytics-data-api/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/google-drive/README.md b/docs/ai-agents/connectors/google-drive/README.md index 29792bad38e0..fd481b8ab0c0 100644 --- a/docs/ai-agents/connectors/google-drive/README.md +++ b/docs/ai-agents/connectors/google-drive/README.md @@ -129,7 +129,7 @@ See the official [Google-Drive API reference](https://developers.google.com/work ## Version information -- **Package version:** 0.1.91 +- **Package version:** 0.1.92 - **Connector version:** 0.2.2 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/google-drive/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/google-search-console/README.md b/docs/ai-agents/connectors/google-search-console/README.md index d04fa9a9dabb..8c4bfbfacb0c 100644 --- a/docs/ai-agents/connectors/google-search-console/README.md +++ b/docs/ai-agents/connectors/google-search-console/README.md @@ -117,7 +117,7 @@ See the official [Google-Search-Console API reference](https://developers.google ## Version information -- **Package version:** 0.1.5 +- **Package version:** 0.1.6 - **Connector version:** 1.0.0 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/google-search-console/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/granola/README.md b/docs/ai-agents/connectors/granola/README.md index dc31785753f1..19b23f9c5ab5 100644 --- a/docs/ai-agents/connectors/granola/README.md +++ b/docs/ai-agents/connectors/granola/README.md @@ -106,7 +106,7 @@ See the official [Granola API reference](https://docs.granola.ai/introduction). ## Version information -- **Package version:** 0.1.18 +- **Package version:** 0.1.19 - **Connector version:** 1.0.3 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/granola/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/greenhouse/README.md b/docs/ai-agents/connectors/greenhouse/README.md index 641719a07171..7ee506d74d67 100644 --- a/docs/ai-agents/connectors/greenhouse/README.md +++ b/docs/ai-agents/connectors/greenhouse/README.md @@ -122,7 +122,7 @@ See the official [Greenhouse API reference](https://developers.greenhouse.io/har ## Version information -- **Package version:** 0.17.115 +- **Package version:** 0.17.116 - **Connector version:** 0.1.7 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/greenhouse/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/harvest/README.md b/docs/ai-agents/connectors/harvest/README.md index c3df600422f2..8cc18452291c 100644 --- a/docs/ai-agents/connectors/harvest/README.md +++ b/docs/ai-agents/connectors/harvest/README.md @@ -130,7 +130,7 @@ See the official [Harvest API reference](https://help.getharvest.com/api-v2/). ## Version information -- **Package version:** 0.1.6 +- **Package version:** 0.1.7 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/harvest/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/hubspot/README.md b/docs/ai-agents/connectors/hubspot/README.md index a351cea26357..3e6ba708fb1d 100644 --- a/docs/ai-agents/connectors/hubspot/README.md +++ b/docs/ai-agents/connectors/hubspot/README.md @@ -117,7 +117,7 @@ See the official [Hubspot API reference](https://developers.hubspot.com/docs/api ## Version information -- **Package version:** 0.15.122 +- **Package version:** 0.15.123 - **Connector version:** 0.1.14 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/hubspot/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/incident-io/README.md b/docs/ai-agents/connectors/incident-io/README.md index 8d0908cc93fb..2e4b67a52179 100644 --- a/docs/ai-agents/connectors/incident-io/README.md +++ b/docs/ai-agents/connectors/incident-io/README.md @@ -124,7 +124,7 @@ See the official [Incident-Io API reference](https://api-docs.incident.io/). ## Version information -- **Package version:** 0.1.10 +- **Package version:** 0.1.11 - **Connector version:** 1.0.3 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/incident-io/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/intercom/README.md b/docs/ai-agents/connectors/intercom/README.md index 5fb8fe9c2064..9577e3ab30a8 100644 --- a/docs/ai-agents/connectors/intercom/README.md +++ b/docs/ai-agents/connectors/intercom/README.md @@ -127,7 +127,7 @@ See the official [Intercom API reference](https://developers.intercom.com/docs/r ## Version information -- **Package version:** 0.1.90 +- **Package version:** 0.1.91 - **Connector version:** 0.1.9 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/intercom/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/jira/README.md b/docs/ai-agents/connectors/jira/README.md index e96ef5df91a6..ed8682da3c58 100644 --- a/docs/ai-agents/connectors/jira/README.md +++ b/docs/ai-agents/connectors/jira/README.md @@ -121,7 +121,7 @@ See the official [Jira API reference](https://developer.atlassian.com/cloud/jira ## Version information -- **Package version:** 0.1.111 +- **Package version:** 0.1.112 - **Connector version:** 1.1.7 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/jira/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/klaviyo/README.md b/docs/ai-agents/connectors/klaviyo/README.md index c68a1b863a37..7787efb1b878 100644 --- a/docs/ai-agents/connectors/klaviyo/README.md +++ b/docs/ai-agents/connectors/klaviyo/README.md @@ -119,7 +119,7 @@ See the official [Klaviyo API reference](https://developers.klaviyo.com/en/refer ## Version information -- **Package version:** 0.1.46 +- **Package version:** 0.1.47 - **Connector version:** 1.0.3 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/klaviyo/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/linear/README.md b/docs/ai-agents/connectors/linear/README.md index 821349235dde..efd443dae683 100644 --- a/docs/ai-agents/connectors/linear/README.md +++ b/docs/ai-agents/connectors/linear/README.md @@ -121,7 +121,7 @@ See the official [Linear API reference](https://linear.app/developers/graphql). ## Version information -- **Package version:** 0.19.118 +- **Package version:** 0.19.119 - **Connector version:** 0.1.12 -- **Generated with Connector SDK commit SHA:** 128ac5a7ba99d76a190accd255caf509ff09afde +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/linear/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/linkedin-ads/README.md b/docs/ai-agents/connectors/linkedin-ads/README.md index 532aaf05aa74..b7c679eebae7 100644 --- a/docs/ai-agents/connectors/linkedin-ads/README.md +++ b/docs/ai-agents/connectors/linkedin-ads/README.md @@ -115,7 +115,7 @@ See the official [Linkedin-Ads API reference](https://learn.microsoft.com/en-us/ ## Version information -- **Package version:** 0.1.6 +- **Package version:** 0.1.7 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/linkedin-ads/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/mailchimp/README.md b/docs/ai-agents/connectors/mailchimp/README.md index 21f620d73640..b014d03d54af 100644 --- a/docs/ai-agents/connectors/mailchimp/README.md +++ b/docs/ai-agents/connectors/mailchimp/README.md @@ -123,7 +123,7 @@ See the official [Mailchimp API reference](https://mailchimp.com/developer/marke ## Version information -- **Package version:** 0.1.75 +- **Package version:** 0.1.76 - **Connector version:** 1.0.8 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/mailchimp/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/monday/README.md b/docs/ai-agents/connectors/monday/README.md index 6c8ec941981e..f8d366f4f3ce 100644 --- a/docs/ai-agents/connectors/monday/README.md +++ b/docs/ai-agents/connectors/monday/README.md @@ -114,7 +114,7 @@ See the official [Monday API reference](https://developer.monday.com/api-referen ## Version information -- **Package version:** 0.1.13 +- **Package version:** 0.1.14 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/monday/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/notion/README.md b/docs/ai-agents/connectors/notion/README.md index c43003d12a96..26a4b3b10cb4 100644 --- a/docs/ai-agents/connectors/notion/README.md +++ b/docs/ai-agents/connectors/notion/README.md @@ -114,7 +114,7 @@ See the official [Notion API reference](https://developers.notion.com/reference/ ## Version information -- **Package version:** 0.1.20 +- **Package version:** 0.1.21 - **Connector version:** 0.1.5 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/notion/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/orb/README.md b/docs/ai-agents/connectors/orb/README.md index 835d5682d15e..903a896f25ef 100644 --- a/docs/ai-agents/connectors/orb/README.md +++ b/docs/ai-agents/connectors/orb/README.md @@ -120,7 +120,7 @@ See the official [Orb API reference](https://docs.withorb.com/api-reference). ## Version information -- **Package version:** 0.1.50 +- **Package version:** 0.1.51 - **Connector version:** 0.1.6 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/orb/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/paypal-transaction/README.md b/docs/ai-agents/connectors/paypal-transaction/README.md index ad36bb6cebb8..ac5cec4f83c6 100644 --- a/docs/ai-agents/connectors/paypal-transaction/README.md +++ b/docs/ai-agents/connectors/paypal-transaction/README.md @@ -114,7 +114,7 @@ See the official [Paypal-Transaction API reference](https://developer.paypal.com ## Version information -- **Package version:** 0.1.5 +- **Package version:** 0.1.6 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/paypal-transaction/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/pinterest/README.md b/docs/ai-agents/connectors/pinterest/README.md index e905f867bd56..122e753215a6 100644 --- a/docs/ai-agents/connectors/pinterest/README.md +++ b/docs/ai-agents/connectors/pinterest/README.md @@ -122,7 +122,7 @@ See the official [Pinterest API reference](https://developers.pinterest.com/docs ## Version information -- **Package version:** 0.1.5 +- **Package version:** 0.1.6 - **Connector version:** 0.1.1 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/pinterest/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/pylon/README.md b/docs/ai-agents/connectors/pylon/README.md index 6143f3e4358d..bda5a7ae3193 100644 --- a/docs/ai-agents/connectors/pylon/README.md +++ b/docs/ai-agents/connectors/pylon/README.md @@ -132,7 +132,7 @@ See the official [Pylon API reference](https://docs.usepylon.com/pylon-docs/deve ## Version information -- **Package version:** 0.1.17 +- **Package version:** 0.1.18 - **Connector version:** 0.1.5 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/pylon/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/salesforce/README.md b/docs/ai-agents/connectors/salesforce/README.md index 7c6e50362ce5..9f6740833df0 100644 --- a/docs/ai-agents/connectors/salesforce/README.md +++ b/docs/ai-agents/connectors/salesforce/README.md @@ -124,7 +124,7 @@ See the official [Salesforce API reference](https://developer.salesforce.com/doc ## Version information -- **Package version:** 0.1.114 +- **Package version:** 0.1.115 - **Connector version:** 1.0.15 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/salesforce/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/sendgrid/README.md b/docs/ai-agents/connectors/sendgrid/README.md index 35f9bcf2c409..cf20b3c171fe 100644 --- a/docs/ai-agents/connectors/sendgrid/README.md +++ b/docs/ai-agents/connectors/sendgrid/README.md @@ -121,7 +121,7 @@ See the official [Sendgrid API reference](https://docs.sendgrid.com/api-referenc ## Version information -- **Package version:** 0.1.13 +- **Package version:** 0.1.14 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/sendgrid/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/sentry/README.md b/docs/ai-agents/connectors/sentry/README.md index d554f165b876..2d44ea3fa699 100644 --- a/docs/ai-agents/connectors/sentry/README.md +++ b/docs/ai-agents/connectors/sentry/README.md @@ -107,7 +107,7 @@ See the official [Sentry API reference](https://docs.sentry.io/api/). ## Version information -- **Package version:** 0.1.5 +- **Package version:** 0.1.6 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/sentry/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/shopify/README.md b/docs/ai-agents/connectors/shopify/README.md index 3e168e5cf2bd..cd7a47842944 100644 --- a/docs/ai-agents/connectors/shopify/README.md +++ b/docs/ai-agents/connectors/shopify/README.md @@ -143,7 +143,7 @@ See the official [Shopify API reference](https://shopify.dev/docs/api/admin-rest ## Version information -- **Package version:** 0.1.71 +- **Package version:** 0.1.72 - **Connector version:** 0.1.9 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/shopify/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/slack/README.md b/docs/ai-agents/connectors/slack/README.md index ef8f08e5f942..6024cf085a47 100644 --- a/docs/ai-agents/connectors/slack/README.md +++ b/docs/ai-agents/connectors/slack/README.md @@ -132,7 +132,7 @@ See the official [Slack API reference](https://api.slack.com/methods). ## Version information -- **Package version:** 0.1.84 +- **Package version:** 0.1.85 - **Connector version:** 0.1.16 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/slack/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/snapchat-marketing/README.md b/docs/ai-agents/connectors/snapchat-marketing/README.md index cd12c1e10857..53feaec6c5ff 100644 --- a/docs/ai-agents/connectors/snapchat-marketing/README.md +++ b/docs/ai-agents/connectors/snapchat-marketing/README.md @@ -116,7 +116,7 @@ See the official [Snapchat-Marketing API reference](https://developers.snap.com/ ## Version information -- **Package version:** 0.1.5 +- **Package version:** 0.1.6 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/snapchat-marketing/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/stripe/README.md b/docs/ai-agents/connectors/stripe/README.md index ce412e49f478..632e4f62c368 100644 --- a/docs/ai-agents/connectors/stripe/README.md +++ b/docs/ai-agents/connectors/stripe/README.md @@ -124,7 +124,7 @@ See the official [Stripe API reference](https://docs.stripe.com/api). ## Version information -- **Package version:** 0.5.120 +- **Package version:** 0.5.121 - **Connector version:** 0.1.12 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/stripe/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/tiktok-marketing/README.md b/docs/ai-agents/connectors/tiktok-marketing/README.md index 612ea555ee60..07a15c55337e 100644 --- a/docs/ai-agents/connectors/tiktok-marketing/README.md +++ b/docs/ai-agents/connectors/tiktok-marketing/README.md @@ -120,7 +120,7 @@ See the official [Tiktok-Marketing API reference](https://business-api.tiktok.co ## Version information -- **Package version:** 0.1.21 +- **Package version:** 0.1.22 - **Connector version:** 1.1.4 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/tiktok-marketing/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/twilio/README.md b/docs/ai-agents/connectors/twilio/README.md index 230f62c11f18..8057b6d1a0ab 100644 --- a/docs/ai-agents/connectors/twilio/README.md +++ b/docs/ai-agents/connectors/twilio/README.md @@ -124,7 +124,7 @@ See the official [Twilio API reference](https://www.twilio.com/docs/usage/api). ## Version information -- **Package version:** 0.1.6 +- **Package version:** 0.1.7 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/twilio/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/typeform/README.md b/docs/ai-agents/connectors/typeform/README.md index 092b4ab06063..4321780229cc 100644 --- a/docs/ai-agents/connectors/typeform/README.md +++ b/docs/ai-agents/connectors/typeform/README.md @@ -109,7 +109,7 @@ See the official [Typeform API reference](https://developer.typeform.com/). ## Version information -- **Package version:** 0.1.6 +- **Package version:** 0.1.7 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** 0f76b45606e0337a4c88a046c79788c39f91f87a +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/typeform/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/woocommerce/README.md b/docs/ai-agents/connectors/woocommerce/README.md index a15f9544b262..40e2f5f331ac 100644 --- a/docs/ai-agents/connectors/woocommerce/README.md +++ b/docs/ai-agents/connectors/woocommerce/README.md @@ -130,7 +130,7 @@ See the official [Woocommerce API reference](https://woocommerce.github.io/wooco ## Version information -- **Package version:** 0.1.6 +- **Package version:** 0.1.7 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/woocommerce/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/zendesk-chat/README.md b/docs/ai-agents/connectors/zendesk-chat/README.md index 618d433304e4..223cfea81280 100644 --- a/docs/ai-agents/connectors/zendesk-chat/README.md +++ b/docs/ai-agents/connectors/zendesk-chat/README.md @@ -135,7 +135,7 @@ See the official [Zendesk-Chat API reference](https://developer.zendesk.com/api- ## Version information -- **Package version:** 0.1.70 +- **Package version:** 0.1.71 - **Connector version:** 0.1.9 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/zendesk-chat/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/zendesk-support/README.md b/docs/ai-agents/connectors/zendesk-support/README.md index 88e421468221..c6647fb8abe3 100644 --- a/docs/ai-agents/connectors/zendesk-support/README.md +++ b/docs/ai-agents/connectors/zendesk-support/README.md @@ -131,7 +131,7 @@ See the official [Zendesk-Support API reference](https://developer.zendesk.com/a ## Version information -- **Package version:** 0.18.124 +- **Package version:** 0.18.125 - **Connector version:** 0.1.17 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/zendesk-support/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/zendesk-talk/README.md b/docs/ai-agents/connectors/zendesk-talk/README.md index 34d2866b4ac9..21482f23f6e7 100644 --- a/docs/ai-agents/connectors/zendesk-talk/README.md +++ b/docs/ai-agents/connectors/zendesk-talk/README.md @@ -120,7 +120,7 @@ See the official [Zendesk-Talk API reference](https://developer.zendesk.com/api- ## Version information -- **Package version:** 0.1.6 +- **Package version:** 0.1.7 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/zendesk-talk/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/zoho-crm/README.md b/docs/ai-agents/connectors/zoho-crm/README.md index 8d8efe4b4cfd..d052eac917b7 100644 --- a/docs/ai-agents/connectors/zoho-crm/README.md +++ b/docs/ai-agents/connectors/zoho-crm/README.md @@ -134,7 +134,7 @@ See the official [Zoho-Crm API reference](https://www.zoho.com/crm/developer/doc ## Version information -- **Package version:** 0.1.4 +- **Package version:** 0.1.5 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** bbb4625615c5a514170db99dfb0a413153726447 +- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/zoho-crm/CHANGELOG.md) \ No newline at end of file From 4267e499def821eef645b0b22958e7734295520d Mon Sep 17 00:00:00 2001 From: "octavia-bot[bot]" <108746235+octavia-bot[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 22:10:32 +0000 Subject: [PATCH 013/379] docs: sync agent connector docs from airbyte-agent-connectors repo (#75523) Co-authored-by: ian-at-airbyte <187576150+ian-at-airbyte@users.noreply.github.com> --- docs/ai-agents/connectors/airtable/README.md | 4 ++-- docs/ai-agents/connectors/amazon-ads/README.md | 4 ++-- .../connectors/amazon-seller-partner/README.md | 4 ++-- docs/ai-agents/connectors/amplitude/README.md | 4 ++-- docs/ai-agents/connectors/asana/README.md | 4 ++-- docs/ai-agents/connectors/ashby/README.md | 4 ++-- docs/ai-agents/connectors/chargebee/README.md | 4 ++-- docs/ai-agents/connectors/clickup-api/README.md | 4 ++-- docs/ai-agents/connectors/confluence/README.md | 4 ++-- .../connectors/facebook-marketing/README.md | 4 ++-- docs/ai-agents/connectors/freshdesk/README.md | 4 ++-- docs/ai-agents/connectors/github/README.md | 4 ++-- docs/ai-agents/connectors/gitlab/README.md | 4 ++-- docs/ai-agents/connectors/gmail/README.md | 4 ++-- docs/ai-agents/connectors/gong/README.md | 4 ++-- docs/ai-agents/connectors/google-ads/README.md | 4 ++-- .../connectors/google-analytics-data-api/README.md | 4 ++-- docs/ai-agents/connectors/google-drive/README.md | 4 ++-- .../connectors/google-search-console/README.md | 4 ++-- docs/ai-agents/connectors/granola/README.md | 4 ++-- docs/ai-agents/connectors/greenhouse/README.md | 4 ++-- docs/ai-agents/connectors/harvest/README.md | 4 ++-- docs/ai-agents/connectors/hubspot/README.md | 4 ++-- docs/ai-agents/connectors/incident-io/README.md | 4 ++-- docs/ai-agents/connectors/intercom/README.md | 4 ++-- docs/ai-agents/connectors/jira/README.md | 4 ++-- docs/ai-agents/connectors/klaviyo/README.md | 4 ++-- docs/ai-agents/connectors/linear/README.md | 9 ++++++--- docs/ai-agents/connectors/linear/REFERENCE.md | 14 ++++++++++---- docs/ai-agents/connectors/linkedin-ads/README.md | 4 ++-- docs/ai-agents/connectors/mailchimp/README.md | 4 ++-- docs/ai-agents/connectors/monday/README.md | 4 ++-- docs/ai-agents/connectors/notion/README.md | 4 ++-- docs/ai-agents/connectors/orb/README.md | 4 ++-- .../connectors/paypal-transaction/README.md | 4 ++-- docs/ai-agents/connectors/pinterest/README.md | 4 ++-- docs/ai-agents/connectors/pylon/README.md | 4 ++-- docs/ai-agents/connectors/salesforce/README.md | 4 ++-- docs/ai-agents/connectors/sendgrid/README.md | 4 ++-- docs/ai-agents/connectors/sentry/README.md | 4 ++-- docs/ai-agents/connectors/shopify/README.md | 4 ++-- docs/ai-agents/connectors/slack/README.md | 4 ++-- .../connectors/snapchat-marketing/README.md | 4 ++-- docs/ai-agents/connectors/stripe/README.md | 4 ++-- .../connectors/tiktok-marketing/README.md | 4 ++-- docs/ai-agents/connectors/twilio/README.md | 4 ++-- docs/ai-agents/connectors/typeform/README.md | 4 ++-- docs/ai-agents/connectors/woocommerce/README.md | 4 ++-- docs/ai-agents/connectors/zendesk-chat/README.md | 4 ++-- .../ai-agents/connectors/zendesk-support/README.md | 4 ++-- docs/ai-agents/connectors/zendesk-talk/README.md | 4 ++-- docs/ai-agents/connectors/zoho-crm/README.md | 4 ++-- 52 files changed, 116 insertions(+), 107 deletions(-) diff --git a/docs/ai-agents/connectors/airtable/README.md b/docs/ai-agents/connectors/airtable/README.md index 8a8317545e52..506ad0be6a4b 100644 --- a/docs/ai-agents/connectors/airtable/README.md +++ b/docs/ai-agents/connectors/airtable/README.md @@ -109,7 +109,7 @@ See the official [Airtable API reference](https://airtable.com/developers/web/ap ## Version information -- **Package version:** 0.1.50 +- **Package version:** 0.1.51 - **Connector version:** 1.0.6 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/airtable/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/amazon-ads/README.md b/docs/ai-agents/connectors/amazon-ads/README.md index e64b0b4f15cc..f1c70fb2fb3a 100644 --- a/docs/ai-agents/connectors/amazon-ads/README.md +++ b/docs/ai-agents/connectors/amazon-ads/README.md @@ -108,7 +108,7 @@ See the official [Amazon-Ads API reference](https://advertising.amazon.com/API/d ## Version information -- **Package version:** 0.1.69 +- **Package version:** 0.1.70 - **Connector version:** 1.0.9 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/amazon-ads/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/amazon-seller-partner/README.md b/docs/ai-agents/connectors/amazon-seller-partner/README.md index 7975acd0813d..2807e49f7918 100644 --- a/docs/ai-agents/connectors/amazon-seller-partner/README.md +++ b/docs/ai-agents/connectors/amazon-seller-partner/README.md @@ -113,7 +113,7 @@ See the official [Amazon-Seller-Partner API reference](https://developer-docs.am ## Version information -- **Package version:** 0.1.8 +- **Package version:** 0.1.9 - **Connector version:** 1.0.3 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/amazon-seller-partner/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/amplitude/README.md b/docs/ai-agents/connectors/amplitude/README.md index 4a3a0e3c38d9..4b8a00963585 100644 --- a/docs/ai-agents/connectors/amplitude/README.md +++ b/docs/ai-agents/connectors/amplitude/README.md @@ -107,7 +107,7 @@ See the official [Amplitude API reference](https://www.docs.developers.amplitude ## Version information -- **Package version:** 0.1.10 +- **Package version:** 0.1.11 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/amplitude/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/asana/README.md b/docs/ai-agents/connectors/asana/README.md index 1e1ce762f91f..f0e2feb080dc 100644 --- a/docs/ai-agents/connectors/asana/README.md +++ b/docs/ai-agents/connectors/asana/README.md @@ -130,7 +130,7 @@ See the official [Asana API reference](https://developers.asana.com/reference/re ## Version information -- **Package version:** 0.19.124 +- **Package version:** 0.19.125 - **Connector version:** 0.1.16 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/asana/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/ashby/README.md b/docs/ai-agents/connectors/ashby/README.md index e9e1c092719f..05c8491cd53f 100644 --- a/docs/ai-agents/connectors/ashby/README.md +++ b/docs/ai-agents/connectors/ashby/README.md @@ -119,7 +119,7 @@ See the official [Ashby API reference](https://developers.ashbyhq.com/reference) ## Version information -- **Package version:** 0.1.21 +- **Package version:** 0.1.22 - **Connector version:** 0.1.3 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/ashby/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/chargebee/README.md b/docs/ai-agents/connectors/chargebee/README.md index 69bbbe938a85..4c279e21528f 100644 --- a/docs/ai-agents/connectors/chargebee/README.md +++ b/docs/ai-agents/connectors/chargebee/README.md @@ -123,7 +123,7 @@ See the official [Chargebee API reference](https://apidocs.chargebee.com/docs/ap ## Version information -- **Package version:** 0.1.7 +- **Package version:** 0.1.8 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/chargebee/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/clickup-api/README.md b/docs/ai-agents/connectors/clickup-api/README.md index 6bd3b7671d4f..ccd3b02e7a79 100644 --- a/docs/ai-agents/connectors/clickup-api/README.md +++ b/docs/ai-agents/connectors/clickup-api/README.md @@ -135,7 +135,7 @@ See the official [Clickup-Api API reference](https://developer.clickup.com/refer ## Version information -- **Package version:** 0.1.7 +- **Package version:** 0.1.8 - **Connector version:** 0.1.2 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/clickup-api/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/confluence/README.md b/docs/ai-agents/connectors/confluence/README.md index 6b1fbde3d05d..5cd7f29ca73a 100644 --- a/docs/ai-agents/connectors/confluence/README.md +++ b/docs/ai-agents/connectors/confluence/README.md @@ -113,7 +113,7 @@ See the official [Confluence API reference](https://developer.atlassian.com/clou ## Version information -- **Package version:** 0.1.6 +- **Package version:** 0.1.7 - **Connector version:** 1.0.0 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/confluence/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/facebook-marketing/README.md b/docs/ai-agents/connectors/facebook-marketing/README.md index 1e5ed24606bb..698b8282e2d1 100644 --- a/docs/ai-agents/connectors/facebook-marketing/README.md +++ b/docs/ai-agents/connectors/facebook-marketing/README.md @@ -135,7 +135,7 @@ See the official [Facebook-Marketing API reference](https://developers.facebook. ## Version information -- **Package version:** 0.1.60 +- **Package version:** 0.1.61 - **Connector version:** 1.0.21 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/facebook-marketing/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/freshdesk/README.md b/docs/ai-agents/connectors/freshdesk/README.md index 331d897cefc0..fca25deb9664 100644 --- a/docs/ai-agents/connectors/freshdesk/README.md +++ b/docs/ai-agents/connectors/freshdesk/README.md @@ -118,7 +118,7 @@ See the official [Freshdesk API reference](https://developers.freshdesk.com/api/ ## Version information -- **Package version:** 0.1.18 +- **Package version:** 0.1.19 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/freshdesk/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/github/README.md b/docs/ai-agents/connectors/github/README.md index 9d027b9ed120..53b457e15d54 100644 --- a/docs/ai-agents/connectors/github/README.md +++ b/docs/ai-agents/connectors/github/README.md @@ -134,7 +134,7 @@ See the official [Github API reference](https://docs.github.com/en/rest). ## Version information -- **Package version:** 0.18.125 +- **Package version:** 0.18.126 - **Connector version:** 0.1.17 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/github/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/gitlab/README.md b/docs/ai-agents/connectors/gitlab/README.md index fd9e3bec4e27..63814df4e8e5 100644 --- a/docs/ai-agents/connectors/gitlab/README.md +++ b/docs/ai-agents/connectors/gitlab/README.md @@ -120,7 +120,7 @@ See the official [Gitlab API reference](https://docs.gitlab.com/ee/api/rest/). ## Version information -- **Package version:** 0.1.7 +- **Package version:** 0.1.8 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/gitlab/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/gmail/README.md b/docs/ai-agents/connectors/gmail/README.md index c0e7e50f25d1..843f79f0e278 100644 --- a/docs/ai-agents/connectors/gmail/README.md +++ b/docs/ai-agents/connectors/gmail/README.md @@ -133,7 +133,7 @@ See the official [Gmail API reference](https://developers.google.com/gmail/api/r ## Version information -- **Package version:** 0.1.22 +- **Package version:** 0.1.23 - **Connector version:** 0.1.3 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/gmail/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/gong/README.md b/docs/ai-agents/connectors/gong/README.md index 0967cb02c859..0b713147192f 100644 --- a/docs/ai-agents/connectors/gong/README.md +++ b/docs/ai-agents/connectors/gong/README.md @@ -127,7 +127,7 @@ See the official [Gong API reference](https://gong.app.gong.io/settings/api/docu ## Version information -- **Package version:** 0.19.128 +- **Package version:** 0.19.129 - **Connector version:** 0.1.20 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/gong/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/google-ads/README.md b/docs/ai-agents/connectors/google-ads/README.md index ed2addc59ccd..d64282651c37 100644 --- a/docs/ai-agents/connectors/google-ads/README.md +++ b/docs/ai-agents/connectors/google-ads/README.md @@ -122,7 +122,7 @@ See the official [Google-Ads API reference](https://developers.google.com/google ## Version information -- **Package version:** 0.1.18 +- **Package version:** 0.1.19 - **Connector version:** 1.0.6 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/google-ads/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/google-analytics-data-api/README.md b/docs/ai-agents/connectors/google-analytics-data-api/README.md index 135fada7b1cc..a3eefcac967f 100644 --- a/docs/ai-agents/connectors/google-analytics-data-api/README.md +++ b/docs/ai-agents/connectors/google-analytics-data-api/README.md @@ -122,7 +122,7 @@ See the official [Google-Analytics-Data-Api API reference](https://developers.go ## Version information -- **Package version:** 0.1.13 +- **Package version:** 0.1.14 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/google-analytics-data-api/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/google-drive/README.md b/docs/ai-agents/connectors/google-drive/README.md index fd481b8ab0c0..65f23bd495b2 100644 --- a/docs/ai-agents/connectors/google-drive/README.md +++ b/docs/ai-agents/connectors/google-drive/README.md @@ -129,7 +129,7 @@ See the official [Google-Drive API reference](https://developers.google.com/work ## Version information -- **Package version:** 0.1.92 +- **Package version:** 0.1.93 - **Connector version:** 0.2.2 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/google-drive/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/google-search-console/README.md b/docs/ai-agents/connectors/google-search-console/README.md index 8c4bfbfacb0c..a9b7ef18ca44 100644 --- a/docs/ai-agents/connectors/google-search-console/README.md +++ b/docs/ai-agents/connectors/google-search-console/README.md @@ -117,7 +117,7 @@ See the official [Google-Search-Console API reference](https://developers.google ## Version information -- **Package version:** 0.1.6 +- **Package version:** 0.1.7 - **Connector version:** 1.0.0 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/google-search-console/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/granola/README.md b/docs/ai-agents/connectors/granola/README.md index 19b23f9c5ab5..7e2957aa87f3 100644 --- a/docs/ai-agents/connectors/granola/README.md +++ b/docs/ai-agents/connectors/granola/README.md @@ -106,7 +106,7 @@ See the official [Granola API reference](https://docs.granola.ai/introduction). ## Version information -- **Package version:** 0.1.19 +- **Package version:** 0.1.20 - **Connector version:** 1.0.3 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/granola/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/greenhouse/README.md b/docs/ai-agents/connectors/greenhouse/README.md index 7ee506d74d67..a2705082dc90 100644 --- a/docs/ai-agents/connectors/greenhouse/README.md +++ b/docs/ai-agents/connectors/greenhouse/README.md @@ -122,7 +122,7 @@ See the official [Greenhouse API reference](https://developers.greenhouse.io/har ## Version information -- **Package version:** 0.17.116 +- **Package version:** 0.17.117 - **Connector version:** 0.1.7 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/greenhouse/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/harvest/README.md b/docs/ai-agents/connectors/harvest/README.md index 8cc18452291c..f4bc51120b22 100644 --- a/docs/ai-agents/connectors/harvest/README.md +++ b/docs/ai-agents/connectors/harvest/README.md @@ -130,7 +130,7 @@ See the official [Harvest API reference](https://help.getharvest.com/api-v2/). ## Version information -- **Package version:** 0.1.7 +- **Package version:** 0.1.8 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/harvest/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/hubspot/README.md b/docs/ai-agents/connectors/hubspot/README.md index 3e6ba708fb1d..46c8a0215565 100644 --- a/docs/ai-agents/connectors/hubspot/README.md +++ b/docs/ai-agents/connectors/hubspot/README.md @@ -117,7 +117,7 @@ See the official [Hubspot API reference](https://developers.hubspot.com/docs/api ## Version information -- **Package version:** 0.15.123 +- **Package version:** 0.15.124 - **Connector version:** 0.1.14 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/hubspot/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/incident-io/README.md b/docs/ai-agents/connectors/incident-io/README.md index 2e4b67a52179..56e87ce8f6d8 100644 --- a/docs/ai-agents/connectors/incident-io/README.md +++ b/docs/ai-agents/connectors/incident-io/README.md @@ -124,7 +124,7 @@ See the official [Incident-Io API reference](https://api-docs.incident.io/). ## Version information -- **Package version:** 0.1.11 +- **Package version:** 0.1.12 - **Connector version:** 1.0.3 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/incident-io/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/intercom/README.md b/docs/ai-agents/connectors/intercom/README.md index 9577e3ab30a8..38582b8825b0 100644 --- a/docs/ai-agents/connectors/intercom/README.md +++ b/docs/ai-agents/connectors/intercom/README.md @@ -127,7 +127,7 @@ See the official [Intercom API reference](https://developers.intercom.com/docs/r ## Version information -- **Package version:** 0.1.91 +- **Package version:** 0.1.92 - **Connector version:** 0.1.9 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/intercom/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/jira/README.md b/docs/ai-agents/connectors/jira/README.md index ed8682da3c58..8ece46abf4d0 100644 --- a/docs/ai-agents/connectors/jira/README.md +++ b/docs/ai-agents/connectors/jira/README.md @@ -121,7 +121,7 @@ See the official [Jira API reference](https://developer.atlassian.com/cloud/jira ## Version information -- **Package version:** 0.1.112 +- **Package version:** 0.1.113 - **Connector version:** 1.1.7 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/jira/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/klaviyo/README.md b/docs/ai-agents/connectors/klaviyo/README.md index 7787efb1b878..7f84362df888 100644 --- a/docs/ai-agents/connectors/klaviyo/README.md +++ b/docs/ai-agents/connectors/klaviyo/README.md @@ -119,7 +119,7 @@ See the official [Klaviyo API reference](https://developers.klaviyo.com/en/refer ## Version information -- **Package version:** 0.1.47 +- **Package version:** 0.1.48 - **Connector version:** 1.0.3 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/klaviyo/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/linear/README.md b/docs/ai-agents/connectors/linear/README.md index efd443dae683..914ab81a6009 100644 --- a/docs/ai-agents/connectors/linear/README.md +++ b/docs/ai-agents/connectors/linear/README.md @@ -24,6 +24,9 @@ The Linear connector is optimized to handle prompts like these. - Assign a recent issue to a teammate - Unassign the current assignee from a recent issue - Reassign a recent issue from one teammate to another +- Create a new issue in the 'Backend Improvements' project +- Add a recent issue to a specific project +- Move an issue to a different project - Analyze the workload distribution across my development team - What are the top priority issues in our current sprint? - Identify the most active projects in our organization right now @@ -121,7 +124,7 @@ See the official [Linear API reference](https://linear.app/developers/graphql). ## Version information -- **Package version:** 0.19.119 -- **Connector version:** 0.1.12 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Package version:** 0.19.121 +- **Connector version:** 0.1.13 +- **Generated with Connector SDK commit SHA:** 2afeb237479950157f43a4d8bc3eeb181f5fd1c1 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/linear/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/linear/REFERENCE.md b/docs/ai-agents/connectors/linear/REFERENCE.md index 16e629307755..4703c7726a3f 100644 --- a/docs/ai-agents/connectors/linear/REFERENCE.md +++ b/docs/ai-agents/connectors/linear/REFERENCE.md @@ -134,7 +134,8 @@ await linear.issues.create( title="", description="", state_id="", - priority=0 + priority=0, + project_id="" ) ``` @@ -152,7 +153,8 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con "title": "", "description": "", "stateId": "", - "priority": 0 + "priority": 0, + "projectId": "" } }' ``` @@ -167,6 +169,7 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | `description` | `string` | No | The description of the issue (supports markdown) | | `stateId` | `string` | No | The ID of the workflow state for the issue | | `priority` | `integer` | No | The priority of the issue (0=No priority, 1=Urgent, 2=High, 3=Medium, 4=Low) | +| `projectId` | `string` | No | The ID of the project to add the issue to. Get project IDs from the projects list. |
@@ -197,7 +200,8 @@ await linear.issues.update( description="", state_id="", priority=0, - assignee_id="" + assignee_id="", + project_id="" ) ``` @@ -216,7 +220,8 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con "description": "", "stateId": "", "priority": 0, - "assigneeId": "" + "assigneeId": "", + "projectId": "" } }' ``` @@ -232,6 +237,7 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | `stateId` | `string` | No | The ID of the new workflow state for the issue | | `priority` | `integer` | No | The new priority of the issue (0=No priority, 1=Urgent, 2=High, 3=Medium, 4=Low) | | `assigneeId` | `string` | No | The ID of the user to assign to this issue. Get user IDs from the users list. | +| `projectId` | `string` | No | The ID of the project to add this issue to. Get project IDs from the projects list. |
diff --git a/docs/ai-agents/connectors/linkedin-ads/README.md b/docs/ai-agents/connectors/linkedin-ads/README.md index b7c679eebae7..e07c7c096b45 100644 --- a/docs/ai-agents/connectors/linkedin-ads/README.md +++ b/docs/ai-agents/connectors/linkedin-ads/README.md @@ -115,7 +115,7 @@ See the official [Linkedin-Ads API reference](https://learn.microsoft.com/en-us/ ## Version information -- **Package version:** 0.1.7 +- **Package version:** 0.1.8 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/linkedin-ads/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/mailchimp/README.md b/docs/ai-agents/connectors/mailchimp/README.md index b014d03d54af..6fdf61a2f5a1 100644 --- a/docs/ai-agents/connectors/mailchimp/README.md +++ b/docs/ai-agents/connectors/mailchimp/README.md @@ -123,7 +123,7 @@ See the official [Mailchimp API reference](https://mailchimp.com/developer/marke ## Version information -- **Package version:** 0.1.76 +- **Package version:** 0.1.77 - **Connector version:** 1.0.8 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/mailchimp/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/monday/README.md b/docs/ai-agents/connectors/monday/README.md index f8d366f4f3ce..6a41ba5fff00 100644 --- a/docs/ai-agents/connectors/monday/README.md +++ b/docs/ai-agents/connectors/monday/README.md @@ -114,7 +114,7 @@ See the official [Monday API reference](https://developer.monday.com/api-referen ## Version information -- **Package version:** 0.1.14 +- **Package version:** 0.1.15 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/monday/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/notion/README.md b/docs/ai-agents/connectors/notion/README.md index 26a4b3b10cb4..d5cdab78ea38 100644 --- a/docs/ai-agents/connectors/notion/README.md +++ b/docs/ai-agents/connectors/notion/README.md @@ -114,7 +114,7 @@ See the official [Notion API reference](https://developers.notion.com/reference/ ## Version information -- **Package version:** 0.1.21 +- **Package version:** 0.1.22 - **Connector version:** 0.1.5 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/notion/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/orb/README.md b/docs/ai-agents/connectors/orb/README.md index 903a896f25ef..8150631106bb 100644 --- a/docs/ai-agents/connectors/orb/README.md +++ b/docs/ai-agents/connectors/orb/README.md @@ -120,7 +120,7 @@ See the official [Orb API reference](https://docs.withorb.com/api-reference). ## Version information -- **Package version:** 0.1.51 +- **Package version:** 0.1.52 - **Connector version:** 0.1.6 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/orb/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/paypal-transaction/README.md b/docs/ai-agents/connectors/paypal-transaction/README.md index ac5cec4f83c6..d187107c7a85 100644 --- a/docs/ai-agents/connectors/paypal-transaction/README.md +++ b/docs/ai-agents/connectors/paypal-transaction/README.md @@ -114,7 +114,7 @@ See the official [Paypal-Transaction API reference](https://developer.paypal.com ## Version information -- **Package version:** 0.1.6 +- **Package version:** 0.1.7 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/paypal-transaction/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/pinterest/README.md b/docs/ai-agents/connectors/pinterest/README.md index 122e753215a6..c058e976de9f 100644 --- a/docs/ai-agents/connectors/pinterest/README.md +++ b/docs/ai-agents/connectors/pinterest/README.md @@ -122,7 +122,7 @@ See the official [Pinterest API reference](https://developers.pinterest.com/docs ## Version information -- **Package version:** 0.1.6 +- **Package version:** 0.1.7 - **Connector version:** 0.1.1 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/pinterest/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/pylon/README.md b/docs/ai-agents/connectors/pylon/README.md index bda5a7ae3193..649004b36b5e 100644 --- a/docs/ai-agents/connectors/pylon/README.md +++ b/docs/ai-agents/connectors/pylon/README.md @@ -132,7 +132,7 @@ See the official [Pylon API reference](https://docs.usepylon.com/pylon-docs/deve ## Version information -- **Package version:** 0.1.18 +- **Package version:** 0.1.19 - **Connector version:** 0.1.5 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/pylon/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/salesforce/README.md b/docs/ai-agents/connectors/salesforce/README.md index 9f6740833df0..aa1a2fd51d73 100644 --- a/docs/ai-agents/connectors/salesforce/README.md +++ b/docs/ai-agents/connectors/salesforce/README.md @@ -124,7 +124,7 @@ See the official [Salesforce API reference](https://developer.salesforce.com/doc ## Version information -- **Package version:** 0.1.115 +- **Package version:** 0.1.116 - **Connector version:** 1.0.15 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/salesforce/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/sendgrid/README.md b/docs/ai-agents/connectors/sendgrid/README.md index cf20b3c171fe..19ad54566b9b 100644 --- a/docs/ai-agents/connectors/sendgrid/README.md +++ b/docs/ai-agents/connectors/sendgrid/README.md @@ -121,7 +121,7 @@ See the official [Sendgrid API reference](https://docs.sendgrid.com/api-referenc ## Version information -- **Package version:** 0.1.14 +- **Package version:** 0.1.15 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/sendgrid/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/sentry/README.md b/docs/ai-agents/connectors/sentry/README.md index 2d44ea3fa699..0aa0ca84da42 100644 --- a/docs/ai-agents/connectors/sentry/README.md +++ b/docs/ai-agents/connectors/sentry/README.md @@ -107,7 +107,7 @@ See the official [Sentry API reference](https://docs.sentry.io/api/). ## Version information -- **Package version:** 0.1.6 +- **Package version:** 0.1.7 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/sentry/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/shopify/README.md b/docs/ai-agents/connectors/shopify/README.md index cd7a47842944..fdb5bf6e9c2d 100644 --- a/docs/ai-agents/connectors/shopify/README.md +++ b/docs/ai-agents/connectors/shopify/README.md @@ -143,7 +143,7 @@ See the official [Shopify API reference](https://shopify.dev/docs/api/admin-rest ## Version information -- **Package version:** 0.1.72 +- **Package version:** 0.1.73 - **Connector version:** 0.1.9 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/shopify/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/slack/README.md b/docs/ai-agents/connectors/slack/README.md index 6024cf085a47..5ada9760e2f8 100644 --- a/docs/ai-agents/connectors/slack/README.md +++ b/docs/ai-agents/connectors/slack/README.md @@ -132,7 +132,7 @@ See the official [Slack API reference](https://api.slack.com/methods). ## Version information -- **Package version:** 0.1.85 +- **Package version:** 0.1.86 - **Connector version:** 0.1.16 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/slack/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/snapchat-marketing/README.md b/docs/ai-agents/connectors/snapchat-marketing/README.md index 53feaec6c5ff..3eded05817bc 100644 --- a/docs/ai-agents/connectors/snapchat-marketing/README.md +++ b/docs/ai-agents/connectors/snapchat-marketing/README.md @@ -116,7 +116,7 @@ See the official [Snapchat-Marketing API reference](https://developers.snap.com/ ## Version information -- **Package version:** 0.1.6 +- **Package version:** 0.1.7 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/snapchat-marketing/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/stripe/README.md b/docs/ai-agents/connectors/stripe/README.md index 632e4f62c368..6a4aea629e4a 100644 --- a/docs/ai-agents/connectors/stripe/README.md +++ b/docs/ai-agents/connectors/stripe/README.md @@ -124,7 +124,7 @@ See the official [Stripe API reference](https://docs.stripe.com/api). ## Version information -- **Package version:** 0.5.121 +- **Package version:** 0.5.122 - **Connector version:** 0.1.12 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/stripe/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/tiktok-marketing/README.md b/docs/ai-agents/connectors/tiktok-marketing/README.md index 07a15c55337e..9d2cdd9960f4 100644 --- a/docs/ai-agents/connectors/tiktok-marketing/README.md +++ b/docs/ai-agents/connectors/tiktok-marketing/README.md @@ -120,7 +120,7 @@ See the official [Tiktok-Marketing API reference](https://business-api.tiktok.co ## Version information -- **Package version:** 0.1.22 +- **Package version:** 0.1.23 - **Connector version:** 1.1.4 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/tiktok-marketing/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/twilio/README.md b/docs/ai-agents/connectors/twilio/README.md index 8057b6d1a0ab..920c5cbd41ad 100644 --- a/docs/ai-agents/connectors/twilio/README.md +++ b/docs/ai-agents/connectors/twilio/README.md @@ -124,7 +124,7 @@ See the official [Twilio API reference](https://www.twilio.com/docs/usage/api). ## Version information -- **Package version:** 0.1.7 +- **Package version:** 0.1.8 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/twilio/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/typeform/README.md b/docs/ai-agents/connectors/typeform/README.md index 4321780229cc..e0aab9c0cfc4 100644 --- a/docs/ai-agents/connectors/typeform/README.md +++ b/docs/ai-agents/connectors/typeform/README.md @@ -109,7 +109,7 @@ See the official [Typeform API reference](https://developer.typeform.com/). ## Version information -- **Package version:** 0.1.7 +- **Package version:** 0.1.8 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/typeform/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/woocommerce/README.md b/docs/ai-agents/connectors/woocommerce/README.md index 40e2f5f331ac..ae83efb6a5ec 100644 --- a/docs/ai-agents/connectors/woocommerce/README.md +++ b/docs/ai-agents/connectors/woocommerce/README.md @@ -130,7 +130,7 @@ See the official [Woocommerce API reference](https://woocommerce.github.io/wooco ## Version information -- **Package version:** 0.1.7 +- **Package version:** 0.1.8 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/woocommerce/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/zendesk-chat/README.md b/docs/ai-agents/connectors/zendesk-chat/README.md index 223cfea81280..f5316ed7c53a 100644 --- a/docs/ai-agents/connectors/zendesk-chat/README.md +++ b/docs/ai-agents/connectors/zendesk-chat/README.md @@ -135,7 +135,7 @@ See the official [Zendesk-Chat API reference](https://developer.zendesk.com/api- ## Version information -- **Package version:** 0.1.71 +- **Package version:** 0.1.72 - **Connector version:** 0.1.9 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/zendesk-chat/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/zendesk-support/README.md b/docs/ai-agents/connectors/zendesk-support/README.md index c6647fb8abe3..6f2a538fc264 100644 --- a/docs/ai-agents/connectors/zendesk-support/README.md +++ b/docs/ai-agents/connectors/zendesk-support/README.md @@ -131,7 +131,7 @@ See the official [Zendesk-Support API reference](https://developer.zendesk.com/a ## Version information -- **Package version:** 0.18.125 +- **Package version:** 0.18.126 - **Connector version:** 0.1.17 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/zendesk-support/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/zendesk-talk/README.md b/docs/ai-agents/connectors/zendesk-talk/README.md index 21482f23f6e7..abfb7a907584 100644 --- a/docs/ai-agents/connectors/zendesk-talk/README.md +++ b/docs/ai-agents/connectors/zendesk-talk/README.md @@ -120,7 +120,7 @@ See the official [Zendesk-Talk API reference](https://developer.zendesk.com/api- ## Version information -- **Package version:** 0.1.7 +- **Package version:** 0.1.8 - **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/zendesk-talk/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/zoho-crm/README.md b/docs/ai-agents/connectors/zoho-crm/README.md index d052eac917b7..fe3ea0ada354 100644 --- a/docs/ai-agents/connectors/zoho-crm/README.md +++ b/docs/ai-agents/connectors/zoho-crm/README.md @@ -134,7 +134,7 @@ See the official [Zoho-Crm API reference](https://www.zoho.com/crm/developer/doc ## Version information -- **Package version:** 0.1.5 +- **Package version:** 0.1.6 - **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** 20f00dda69661bd8f1fe16371d553e41a819e109 +- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/zoho-crm/CHANGELOG.md) \ No newline at end of file From 8371d51e4bdd5c9a6aa51703858a644dba9e44ea Mon Sep 17 00:00:00 2001 From: "octavia-bot[bot]" <108746235+octavia-bot[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2026 00:36:07 +0000 Subject: [PATCH 014/379] docs: sync agent connector docs from airbyte-agent-connectors repo (#75525) Co-authored-by: ian-at-airbyte <187576150+ian-at-airbyte@users.noreply.github.com> --- docs/ai-agents/connectors/hubspot/AUTH.md | 50 +++++++++++++++++++-- docs/ai-agents/connectors/hubspot/README.md | 15 +++---- 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/docs/ai-agents/connectors/hubspot/AUTH.md b/docs/ai-agents/connectors/hubspot/AUTH.md index 9d4ead6348df..01ccd001274e 100644 --- a/docs/ai-agents/connectors/hubspot/AUTH.md +++ b/docs/ai-agents/connectors/hubspot/AUTH.md @@ -24,10 +24,10 @@ Example request: ```python from airbyte_agent_hubspot import HubspotConnector -from airbyte_agent_hubspot.models import HubspotAuthConfig +from airbyte_agent_hubspot.models import HubspotOauth2AuthConfig connector = HubspotConnector( - auth_config=HubspotAuthConfig( + auth_config=HubspotOauth2AuthConfig( client_id="", client_secret="", refresh_token="", @@ -37,7 +37,25 @@ connector = HubspotConnector( ``` #### Token -This authentication method isn't available for this connector. + +`credentials` fields you need: + +| Field Name | Type | Required | Description | +|------------|------|----------|-------------| +| `private_app_token` | `str` | Yes | Access token from a HubSpot Private App | + +Example request: + +```python +from airbyte_agent_hubspot import HubspotConnector +from airbyte_agent_hubspot.models import HubspotPrivateAppAuthConfig + +connector = HubspotConnector( + auth_config=HubspotPrivateAppAuthConfig( + private_app_token="" + ) +) +``` ### Hosted execution @@ -174,7 +192,31 @@ https://yourapp.com/oauth/callback?connector_id= Extract the `connector_id` from the callback URL and store it for future operations. For error handling and a complete implementation example, see [Build your own OAuth flow](https://docs.airbyte.com/ai-agents/platform/authenticate/build-auth/build-your-own#part-3-handle-the-callback). #### Token -This authentication method isn't available for this connector. +Create a connector with Token credentials. + + +`credentials` fields you need: + +| Field Name | Type | Required | Description | +|------------|------|----------|-------------| +| `private_app_token` | `str` | Yes | Access token from a HubSpot Private App | + +Example request: + + +```bash +curl -X POST "https://api.airbyte.ai/api/v1/integrations/connectors" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "customer_name": "", + "connector_type": "Hubspot", + "name": "My Hubspot Connector", + "credentials": { + "private_app_token": "" + } + }' +``` #### Execution diff --git a/docs/ai-agents/connectors/hubspot/README.md b/docs/ai-agents/connectors/hubspot/README.md index 46c8a0215565..41014b350e17 100644 --- a/docs/ai-agents/connectors/hubspot/README.md +++ b/docs/ai-agents/connectors/hubspot/README.md @@ -49,14 +49,11 @@ In open source mode, you provide API credentials directly to the connector. ```python from airbyte_agent_hubspot import HubspotConnector -from airbyte_agent_hubspot.models import HubspotAuthConfig +from airbyte_agent_hubspot.models import HubspotPrivateAppAuthConfig connector = HubspotConnector( - auth_config=HubspotAuthConfig( - client_id="", - client_secret="", - refresh_token="", - access_token="" + auth_config=HubspotPrivateAppAuthConfig( + private_app_token="" ) ) @@ -117,7 +114,7 @@ See the official [Hubspot API reference](https://developers.hubspot.com/docs/api ## Version information -- **Package version:** 0.15.124 -- **Connector version:** 0.1.14 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.15.125 +- **Connector version:** 0.1.15 +- **Generated with Connector SDK commit SHA:** 547c701420fd178a856f06b58309e9ac6c78f310 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/hubspot/CHANGELOG.md) \ No newline at end of file From a986d848ff73775f319e204a3c53766c4745bec6 Mon Sep 17 00:00:00 2001 From: Yarden Carmeli Date: Fri, 27 Mar 2026 16:31:02 +0300 Subject: [PATCH 015/379] docs: Update MongoDB migration guide (#75489) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- docs/integrations/sources/mongodb-v2-migrations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/integrations/sources/mongodb-v2-migrations.md b/docs/integrations/sources/mongodb-v2-migrations.md index f155d193ff52..293bbe33e6f8 100644 --- a/docs/integrations/sources/mongodb-v2-migrations.md +++ b/docs/integrations/sources/mongodb-v2-migrations.md @@ -14,9 +14,9 @@ The issue has been identified and resolved. If you updated your source configuration during the incident window, you may find that your source config is now empty. In this case, simply re-enter your connection details and resume syncing as usual. -If you are using **CDC (Incremental) syncs** and your oplog position was lost during this window, you will need to [refresh your connection](https://docs.airbyte.com/platform/operator-guides/refreshes). If you need assistance with this, please reach out to [Support](https://support.airbyte.com). +If you are using **CDC (Incremental) syncs** and your oplog position was lost during this window, you will need to [refresh your connection](https://docs.airbyte.com/platform/operator-guides/refreshes). If you needed to run a full refresh to recover your sync, please reach out to our [Support](https://support.airbyte.com). -If you have any questions, don't hesitate to contact our Support team. +If you have any further questions, don't hesitate to contact us. ## Upgrading to 2.0.0 From d77e469a469b149d717e0f101da48b2a6bd9e91e Mon Sep 17 00:00:00 2001 From: Ian Alton Date: Fri, 27 Mar 2026 11:09:05 -0700 Subject: [PATCH 016/379] docs(source-uptick): revert incorrect incremental sync status for 35 streams (#75479) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- docs/integrations/sources/uptick.md | 74 ++++++++++++++--------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/docs/integrations/sources/uptick.md b/docs/integrations/sources/uptick.md index 8d51baf98923..4a0ad9bf95be 100644 --- a/docs/integrations/sources/uptick.md +++ b/docs/integrations/sources/uptick.md @@ -101,30 +101,30 @@ The Uptick connector syncs data from the following streams, organized by functio | Stream Name | Primary Key | Pagination | Supports Full Sync | Supports Incremental | |-------------|-------------|------------|---------------------|----------------------| | `tasks` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `taskcategories` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `clients` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `clientgroups` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `properties` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `invoices` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `projects` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `servicequotes` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `defectquotes` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `suppliers` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `purchaseorders` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `purchaseorderlineitems` | `id` | `DefaultPaginator` | ✅ | ✅ | +| `taskcategories` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `clients` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `clientgroups` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `properties` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `invoices` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `projects` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `servicequotes` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `defectquotes` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `suppliers` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `purchaseorders` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `purchaseorderlineitems` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | | `assets` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `routines` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `billingcards` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `purchaseorderbills` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `purchaseorderbilllineitems` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `purchaseorderdockets` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `invoicelineitems` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `users` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `servicegroups` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `costcentres` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `accreditationtypes` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `accreditations` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `branches` | `id` | `DefaultPaginator` | ✅ | ✅ | +| `routines` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `billingcards` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `purchaseorderbills` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `purchaseorderbilllineitems` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `purchaseorderdockets` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `invoicelineitems` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `users` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `servicegroups` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `costcentres` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `accreditationtypes` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `accreditations` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `branches` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | | `creditnotes` | `id` | `DefaultPaginator` | ✅ | ✅ | | `creditnotelineitems` | `id` | `DefaultPaginator` | ✅ | ✅ | | `remarks` | `id` | `DefaultPaginator` | ✅ | ✅ | @@ -132,20 +132,20 @@ The Uptick connector syncs data from the following streams, organized by functio | `assettypevariants` | `id` | `DefaultPaginator` | ✅ | ✅ | | `products` | `id` | `DefaultPaginator` | ✅ | ✅ | | `rounds` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `tasksessions` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `contractors` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `appointments` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `billingcontracts` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `billingcontractlineitems` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `defectquotelineitems` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `servicequotefixedlineitems` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `servicequotedoandchargelineitems` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `servicequoteproductlineitems` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `remarkevents` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `routineservices` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `routineservicelevels` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `routineservicetypes` | `id` | `DefaultPaginator` | ✅ | ✅ | -| `routineserviceleveltypes` | `id` | `DefaultPaginator` | ✅ | ✅ | +| `tasksessions` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `contractors` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `appointments` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `billingcontracts` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `billingcontractlineitems` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `defectquotelineitems` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `servicequotefixedlineitems` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `servicequotedoandchargelineitems` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `servicequoteproductlineitems` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `remarkevents` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `routineservices` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `routineservicelevels` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `routineservicetypes` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | +| `routineserviceleveltypes` | `id` | `DefaultPaginator` | ✅ | ❌ (no soft delete) | | `servicetasks` | `id` | `DefaultPaginator` | ✅ | ✅ | | `subtasks` | `id` | `DefaultPaginator` | ✅ | ✅ | | `task_profitability` | `task_id` | `DefaultPaginator` | ✅ | ✅ | From e27a49a6295d74c45efee2b0fdfe35d5ad24a9c3 Mon Sep 17 00:00:00 2001 From: sophiecuiy Date: Fri, 27 Mar 2026 12:07:39 -0700 Subject: [PATCH 017/379] feat(source-gitlab): Increase default concurrency from 8 to 10 (4.4.23-rc.3) (#75537) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-gitlab/manifest.yaml | 2 +- airbyte-integrations/connectors/source-gitlab/metadata.yaml | 2 +- docs/integrations/sources/gitlab.md | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-gitlab/manifest.yaml b/airbyte-integrations/connectors/source-gitlab/manifest.yaml index 4ef7acf26136..180446384bea 100644 --- a/airbyte-integrations/connectors/source-gitlab/manifest.yaml +++ b/airbyte-integrations/connectors/source-gitlab/manifest.yaml @@ -946,7 +946,7 @@ definitions: concurrency_level: type: ConcurrencyLevel - default_concurrency: "{{ config.get('num_workers', 8) }}" + default_concurrency: "{{ config.get('num_workers', 10) }}" max_concurrency: 25 streams: diff --git a/airbyte-integrations/connectors/source-gitlab/metadata.yaml b/airbyte-integrations/connectors/source-gitlab/metadata.yaml index 871335f0e4fa..43fcc17a6780 100644 --- a/airbyte-integrations/connectors/source-gitlab/metadata.yaml +++ b/airbyte-integrations/connectors/source-gitlab/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: api connectorType: source definitionId: 5e6175e5-68e1-4c17-bff9-56103bbb0d80 - dockerImageTag: 4.4.23-rc.2 + dockerImageTag: 4.4.23-rc.3 dockerRepository: airbyte/source-gitlab documentationUrl: https://docs.airbyte.com/integrations/sources/gitlab externalDocumentationUrls: diff --git a/docs/integrations/sources/gitlab.md b/docs/integrations/sources/gitlab.md index a097f9ff38cb..b587a94adc67 100644 --- a/docs/integrations/sources/gitlab.md +++ b/docs/integrations/sources/gitlab.md @@ -131,6 +131,7 @@ You can adjust the **Number of Concurrent Workers** setting to control how many | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 4.4.23-rc.3 | 2026-03-27 | [75537](https://github.com/airbytehq/airbyte/pull/75537) | Increase default concurrency from 8 to 10 for progressive rollout tuning | | 4.4.23-rc.2 | 2026-03-25 | [75480](https://github.com/airbytehq/airbyte/pull/75480) | Comment out HTTPAPIBudget to isolate concurrency tuning during progressive rollout | | 4.4.23-rc.1 | 2026-03-09 | [70858](https://github.com/airbytehq/airbyte/pull/70858) | Add HTTPAPIBudget and concurrency_level for improved sync performance | | 4.4.22 | 2026-02-24 | [73774](https://github.com/airbytehq/airbyte/pull/73774) | Update dependencies | From 2fba6cdffe78f48f6b6aad276c0fb680d23a3887 Mon Sep 17 00:00:00 2001 From: Ian Alton Date: Fri, 27 Mar 2026 13:10:02 -0700 Subject: [PATCH 018/379] docs(ai-agents): replace open source MCP server docs with hosted MCP server docs (#75473) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- docs/ai-agents/mcp-server/cli-reference.md | 130 --------- docs/ai-agents/mcp-server/configuration.md | 249 ------------------ docs/ai-agents/mcp-server/readme.md | 217 +++++++++++++-- docs/ai-agents/mcp-server/troubleshooting.md | 55 ---- docs/ai-agents/mcp-server/usage.md | 149 ----------- .../quickstarts/tutorial-mcp-server.md | 192 -------------- 6 files changed, 194 insertions(+), 798 deletions(-) delete mode 100644 docs/ai-agents/mcp-server/cli-reference.md delete mode 100644 docs/ai-agents/mcp-server/configuration.md delete mode 100644 docs/ai-agents/mcp-server/troubleshooting.md delete mode 100644 docs/ai-agents/mcp-server/usage.md delete mode 100644 docs/ai-agents/tutorials/quickstarts/tutorial-mcp-server.md diff --git a/docs/ai-agents/mcp-server/cli-reference.md b/docs/ai-agents/mcp-server/cli-reference.md deleted file mode 100644 index d1a56a5e0947..000000000000 --- a/docs/ai-agents/mcp-server/cli-reference.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -sidebar_label: "Command line tool reference" -sidebar_position: 4 ---- - -# Command line reference - -All commands use `uv run agent-engine `. Use `--help` on any command for full options. - -## Global flags - -| Flag | Description | -| --- | --- | -| `--config-dir`, `-d` | Config directory (default: `~/.airbyte_agent_mcp`). Can also be set with the `AIRBYTE_CONFIG_DIR` environment variable. | -| `--org` | Organization ID to use, overriding the default set by `agent-engine login`. | - -## `agent-engine connectors list-oss` - -List available open source connectors from the Airbyte registry. - -```bash -uv run agent-engine connectors list-oss -uv run agent-engine connectors list-oss --pattern salesforce -``` - -| Flag | Description | -| ----------------- | ------------------------- | -| `--pattern`, `-p` | Filter connectors by name | - -## `agent-engine connectors list-cloud` - -List connectors configured in your Agent Engine organization. Requires [`agent-engine login`](#agent-engine-login) first. - -```bash -uv run agent-engine connectors list-cloud -uv run agent-engine connectors list-cloud --customer acme -``` - -| Flag | Description | -| ---------------- | ----------------------- | -| `--customer`, `-c` | Filter by customer name | -| `--customer-id` | Filter by customer ID | - -## `agent-engine connectors configure` - -Generate a connector configuration file by inspecting the connector's authentication requirements. - -```bash -uv run agent-engine connectors configure --package airbyte-agent-gong -uv run agent-engine connectors configure --connector-id -``` - -| Flag | Description | -| ---------------------- | ---------------------------------------------------- | -| `--package` | PyPI package name, local path, or `git+https://` URL | -| `--connector-id`, `-c` | Agent Engine connector ID | -| `--version`, `-v` | Package version (PyPI only) | -| `--filename`, `-f` | Output file path (auto-generated if not specified) | -| `--overwrite`, `-o` | Overwrite the output file if it already exists | - -## `agent-engine login` - -Save Agent Engine credentials to the global config directory. Prompts for your Client ID and Secret, then stores them for subsequent commands. - -```bash -uv run agent-engine login -``` - -| Flag | Description | -| ------------------- | -------------------------------------------- | -| `` | Your Agent Engine organization ID (required) | - -## `agent-engine orgs` - -Manage logged-in organizations. - -```bash -uv run agent-engine orgs list -uv run agent-engine orgs default -uv run agent-engine orgs default -``` - -| Subcommand | Description | -| ------------------ | -------------------------------- | -| `list` | List all logged-in organizations | -| `default` | Show the default organization | -| `default ` | Set the default organization | - -## `agent-engine mcp serve` - -Start the MCP server with a connector configuration. - -```bash -uv run agent-engine mcp serve connector-gong-package.yaml -uv run agent-engine mcp serve connector-gong-package.yaml --transport http --port 8080 -``` - -| Flag | Default | Description | -| ------------------- | ----------- | -------------------------------------- | -| `--transport`, `-t` | `stdio` | Transport protocol (`stdio` or `http`) | -| `--host`, `-h` | `127.0.0.1` | Host to bind to (HTTP only) | -| `--port`, `-p` | `8000` | Port to bind to (HTTP only) | - -## `agent-engine mcp add-to` - -Register the MCP server with an agent. Supported targets: `claude-code`, `claude-desktop`, `cursor`, `codex`. - -```bash -uv run agent-engine mcp add-to claude-code connector-gong-package.yaml -uv run agent-engine mcp add-to cursor connector-gong-package.yaml --scope project -``` - -| Flag | Default | Description | -| --------------- | ------- | -------------------------------------------------------------- | -| `--name`, `-n` | Auto | Name for the MCP server (default: `airbyte-`) | -| `--scope`, `-s` | `user` | Configuration scope: `user` or `project` (Claude Code, Cursor) | - -## `agent-engine chat` - -Chat with connector data using natural language in the terminal. Uses Claude and requires an `ANTHROPIC_API_KEY` environment variable. Pass a prompt argument for one-shot mode, or omit it to start an interactive REPL. - -```bash -uv run agent-engine chat connector-gong-package.yaml "show me 5 recent calls" -uv run agent-engine chat connector-gong-package.yaml -``` - -| Flag | Default | Description | -| --------------- | ----------------- | -------------------------------------------- | -| `--model`, `-m` | `claude-opus-4-6` | Anthropic model to use | -| `--quiet`, `-q` | `false` | Only show the final answer (hide tool calls) | diff --git a/docs/ai-agents/mcp-server/configuration.md b/docs/ai-agents/mcp-server/configuration.md deleted file mode 100644 index 749a32dce832..000000000000 --- a/docs/ai-agents/mcp-server/configuration.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -sidebar_position: 2 ---- - -# Configure the MCP server - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -You configure the Agent Engine MCP server with a YAML file that specifies which connector to use and how to authenticate. This page covers the configuration file format, execution modes, credential management, and aggregate configurations for running multiple connectors. - -If you need help getting started with the MCP server, complete the [tutorial](../tutorials/quickstarts/tutorial-mcp-server) first. - -## Configuration file format - -Place the configuration file in the folder from which you run the MCP server. The file has two required sections. - -| Key | Description | -| ------------- | ----------------------------------------------------------------------------------------------------------------- | -| `connector` | Specifies the connector source. This can be a PyPI package, a git URL, a local path, or an agent connector ID. | -| `credentials` | A key-value map of authentication fields. Values use `${env.VAR_NAME}` syntax to reference environment variables. | - -This is an example of the file format. - -```yaml title="connector-gong-package.yaml" -connector: - package: airbyte-agent-gong -credentials: - access_key: ${env.GONG_ACCESS_KEY} - access_key_secret: ${env.GONG_ACCESS_KEY_SECRET} -``` - -Some connectors also accept a `config` section for additional parameters like subdomains or workspace IDs. The `agent-engine connectors configure` command generates the correct structure for each connector. - -You can [configure multiple connectors](#use-multiple-connectors-with-one-mcp-server) in the same MCP server. - -## Open source mode - -In open source mode, the MCP server installs a connector package and calls the third-party API directly using your credentials. This mode only supports the operations the third-party API provides. It doesn't support using the Agent Engine's search or the [context store](../platform/context-store). Search operations are only possible if the third-party has search endpoints, and are limited to the capabilities and rate limiting of those endpoints. - -### PyPI packages - -The most common configuration. Run `uv run agent-engine connectors list-oss` to see available packages and their versions, then specify a package name from the Airbyte connector registry. - -```yaml title="connector-gong-package.yaml" -connector: - package: airbyte-agent-gong -credentials: - access_key: ${env.GONG_ACCESS_KEY} - access_key_secret: ${env.GONG_ACCESS_KEY_SECRET} -``` - -To pin a specific version: - -```yaml title="connector-gong-package.yaml" -connector: - package: airbyte-agent-gong - version: 0.1.13 -credentials: - access_key: ${env.GONG_ACCESS_KEY} - access_key_secret: ${env.GONG_ACCESS_KEY_SECRET} -``` - -### Git URLs - -Point the connector to a git repository. - -```yaml title="connector-gong-package.yaml" -connector: - git: https://github.com/org/repo.git -credentials: - token: ${env.MY_TOKEN} -``` - -You can specify a branch or tag with `ref` and a subdirectory with `subdirectory`. - -```yaml title="connector-gong-package.yaml" -connector: - git: https://github.com/org/repo.git - ref: main - subdirectory: connectors/my-connector -credentials: - token: ${env.MY_TOKEN} -``` - -### Local path - -Point the connector to a local directory. - -```yaml title="connector-gong-package.yaml" -connector: - path: ../integrations/my-connector/.generated -credentials: - token: ${env.MY_TOKEN} -``` - -### Manage credentials - -Credential values use `${env.VAR_NAME}` syntax. The MCP server resolves these placeholders at startup by reading from the process environment. - -```yaml -credentials: - access_key: ${env.GONG_ACCESS_KEY} - access_key_secret: ${env.GONG_ACCESS_KEY_SECRET} -``` - -The `agent-engine` command line tool automatically loads `.env` files from the current working directory. Create a `.env` file alongside your connector configuration: - -```text title=".env" -GONG_ACCESS_KEY=your-access-key -GONG_ACCESS_KEY_SECRET=your-secret -``` - -:::warning -Never commit your `.env` file to version control. Add `.env` to your `.gitignore` file. If you commit credentials by mistake, rotate them immediately. -::: - -## Hosted mode - -In hosted mode, the MCP server proxies API calls through the Agent Engine. This mode supports search and filter queries because Agent Engine keeps data indexed in the [context store](../platform/context-store). - -Hosted mode uses your Agent Engine credentials (client ID and secret) instead of third-party API credentials. You authenticate once, then the CLI remembers your credentials for subsequent commands. - -### Before you begin - -Before you can use a connector in hosted mode, you need to [authenticate with that connector](../platform/authenticate/hosted). - -### Step 1: Log in to Agent Engine - -Run `agent-engine login` with your organization ID. This opens a link to your Airbyte authentication page where you can find your Client ID and Secret. - -```bash -uv run agent-engine login -``` - -The command prompts for your client ID and secret, saves them to `~/.airbyte_agent_mcp/orgs//.env`, and sets the organization as the default. All subsequent `agent-engine` commands automatically load these credentials. - -### Step 2: Find your connector ID - -List the connectors configured in your organization: - -```bash -uv run agent-engine connectors list-cloud -``` - -Use `--customer` to filter by customer name: - -```bash -uv run agent-engine connectors list-cloud --customer acme -``` - -### Step 3: Generate a configuration - -Pass the connector ID from the previous step: - -```bash -uv run agent-engine connectors configure --connector-id -``` - -This generates a configuration file like this: - -```yaml title="connector-gong-cloud.yaml" -connector: - connector_id: -credentials: - airbyte_client_id: ${env.AIRBYTE_CLIENT_ID} - airbyte_client_secret: ${env.AIRBYTE_CLIENT_SECRET} -``` - -### Managing multiple organizations - -If you work with multiple Agent Engine organizations, you can log into each one and switch between them. - -```bash -uv run agent-engine orgs list # List logged-in organizations -uv run agent-engine orgs default # Set the default organization -uv run agent-engine --org # Override for a single command -``` - -## Use multiple connectors with one MCP server {#use-multiple-connectors-with-one-mcp-server} - -You don't need to create separate MCP servers for each connector. Instead, create a YAML file that references all your individual connector config files. - -| Key | Description | -| --------- | --------------------------------------------------------------------------------------------------- | -| `name` | Sets the MCP server name | -| `configs` | Lists paths to individual connector configuration files, relative to the aggregate file's directory | - -```yaml title="connectors.yaml" -name: airbyte-crm-suite -configs: - - connector-gong-package.yaml - - connector-salesforce-cloud.yaml -``` - -The `name` field sets the MCP server name. The `configs` field lists paths to individual connector configuration files (relative to the aggregate file's directory). - -Then, register the aggregate config with your agent the same way you would a single connector. - - - - -This command runs `claude mcp add` under the hood and registers the server at the user scope. - -```bash -uv run agent-engine mcp add-to claude-code connectors.yaml -``` - -To register at the project scope instead, add `--scope project` to that command. - - - - -This command modifies your Claude Desktop configuration file directly. - -```bash -uv run agent-engine mcp add-to claude-desktop connectors.yaml -``` - - - - -This modifies the Cursor MCP configuration file. - -```bash -uv run agent-engine mcp add-to cursor connectors.yaml -``` - -To register at the project scope instead of user scope, add a `--scope project` flag. - - - - -This command runs `codex mcp add` to register the server. - -```bash -uv run agent-engine mcp add-to codex connectors.yaml -``` - - - - -You can optionally specify a custom name for the server with `--name`: - -```bash -uv run agent-engine mcp add-to claude-code connector-github-package.yaml --name my-server-name -``` - -For a full list of all `agent-engine` commands and their options, see the [CLI reference](cli-reference). diff --git a/docs/ai-agents/mcp-server/readme.md b/docs/ai-agents/mcp-server/readme.md index 00c47ad0f815..e1a79843651f 100644 --- a/docs/ai-agents/mcp-server/readme.md +++ b/docs/ai-agents/mcp-server/readme.md @@ -2,50 +2,221 @@ sidebar_position: 6 --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # Agent Engine MCP server -Airbyte's Agent Engine MCP server lets AI agents interact with your data sources through the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/). Instead of writing code to fetch data, you configure a connector and register it with your agent. The agent then calls the connector's operations automatically based on your natural language prompts. +The Airbyte Agent Engine MCP server connects your AI agent to your data through the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/). It gives your agent authenticated access to the platforms you use every day, like your CRM, support desk, analytics tools, and more, so your agent can read and write data on your behalf. See [Connectors](../connectors) for a list of available connectors. + +Airbyte hosts and manages this remote MCP server, so there's nothing to install. + +## Requirements + +Before you begin, make sure you have the following: + +- **An Agent Engine account.** Sign up at [app.airbyte.ai](https://app.airbyte.ai) if you don't have one. + +- **An AI agent that supports MCP.** For example, Claude Desktop, Claude Code, Cursor, or Codex. + +- **Credentials for the connectors you want to use.** Each service requires its own authentication. For example, you need a Linear API key to connect Linear, or Salesforce OAuth credentials to connect Salesforce. + +## Add the MCP server to your agent + +Select your client below for setup instructions. Each client requires you to authenticate with your Airbyte account before you can use the MCP server. + + + + +Add the MCP server to your Claude Code command line tool. + +1. Run the following command in your terminal: + + ```bash + claude mcp add --transport http airbyte-agent https://mcp.airbyte.ai/mcp + ``` + +2. Run Claude Code with `claude`. + +3. Type `/mcp`. + +4. Select the **airbyte-agent** MCP you added in step 1. + +5. Select **Authenticate**. Your web browser opens. + +6. If you're not logged into the Agent Engine, log in now. + +7. Grant access to the Agent Engine MCP. + +8. Return to Claude Code and begin using the MCP server. + + + + +Add the MCP server to your Cursor app. + +1. Go to **Cursor** > **Settings** > **Cursor Settings** > **Tools and MCP**. + +2. Click **Add custom MCP**. + +3. In `mcp.json`, add: + + ```json + { + "mcpServers": { + "Airbyte Agent Engine MCP": { + "url": "https://mcp.airbyte.ai/mcp" + } + } + } + ``` + +4. Close `mcp.json` and return to Cursor Settings. + +5. Find the Airbyte MCP server and click **Connect**. + +6. If you're not logged into the Agent Engine, log in now. + +7. Grant access to the Agent Engine MCP. + +8. Return to Cursor. The MCP server tools are now available. + + + + +Claude Desktop uses Custom Connectors for remote MCP servers. Don't use the `claude_desktop_config.json` file, as it only supports local servers. + +1. Open Claude Desktop and go to **Settings** > **Connectors**. + +2. Click **Add custom connector**. + +3. Enter the server name and URL: `https://mcp.airbyte.ai/mcp` + +4. Click **Add**. + +5. Find the Airbyte connector in the list and click **Connect**. Your browser opens. + +6. Log in with your Airbyte account and grant access. + +7. Return to Claude Desktop. The MCP server is automatically enabled. If it isn't, in your chat, click **+** > **Connectors** > **Airbyte** to turn it on. + + + + +Add the MCP server to your Codex command line tool. + +1. Run the following command in your terminal to add the server: + + ```bash + codex mcp add airbyte --url https://mcp.airbyte.ai/mcp + ``` + +2. Codex detects that the server requires OAuth and opens your browser. + +3. Log in with your Airbyte account and grant access. + +4. Launch Codex with `codex`. + +5. Begin using the MCP server. + + + + +The Airbyte MCP server works with any client that supports OAuth authentication and Streamable HTTP transport. Use the following server URL in your client's MCP configuration: + +```text +https://mcp.airbyte.ai/mcp +``` + +Most clients that support remote MCP servers accept a JSON configuration like this: + +```json +{ + "mcpServers": { + "Airbyte Agent Engine MCP": { + "url": "https://mcp.airbyte.ai/mcp" + } + } +} +``` + +When your client first connects, it detects that the server requires OAuth. It may or may not open your browser automatically. You may need to click a button to do this. Log in with your app.airbyte.ai account and grant access. After you authenticate, the MCP server's tools are available to your agent. + + + + +## Example usage + +After you connect the MCP server, your agent can discover and call its tools automatically based on your prompts. The following examples show common actions. + +### Add a connector + +To connect a new data source, prompt your agent with the service you want to connect. The MCP can use any Airbyte [agent connector](../connectors). The agent handles the setup, including starting a browser-based credential flow where you enter your credentials securely. + +```text +Connect my Linear account +``` -## What the MCP server does +The agent: -The MCP server sits between your agent and Airbyte's [agent connectors](../connectors/). It exposes each connector's operations as MCP tools that AI assistants can discover and call. When you prompt your agent, like `show me the 10 most recent Gong calls`, the agent calls the MCP server, which calls the connector, which calls the API. +1. Starts a credential flow and gives you a URL to visit. +2. You visit the URL and enter your credentials in the browser. +3. The agent confirms the connector was created and is ready to query. -The server handles: +:::note +Credentials are always entered in the browser, never in the chat. +::: -- Discovering available entities and actions from the connector +### Remove a connector -- Executing operations and returning structured results +To remove a connector you no longer need: -- Truncating large text fields to reduce token usage +```text +Delete my Linear connector +``` -- Field selection and exclusion to control what data the API returns +### Query data -- Downloading binary content like call recordings +After you connect a data source, prompt your agent. The agent discovers the available entities, understands their schemas, and executes the right queries. -## When to use the MCP server +```text +Show me the 10 most recent Gong calls +``` -The MCP server is the fastest way to give an AI coding tool access to your data. It requires no code. You configure a YAML file, register the server, and start prompting. +```text +Find all open deals in Salesforce worth more than $50,000 +``` -## How it works +```text +List HubSpot contacts who were created this week +``` -You configure each server instance with a YAML file that specifies which connector to use and how to authenticate. You can run a single connector per server, or use an [aggregate configuration](configuration#use-multiple-connectors-with-one-mcp-server) to run multiple connectors in one server. +```text +How many Zendesk tickets are in "open" status? +``` -The server supports two execution modes: +The agent uses field selection to return only the data you need, which reduces token usage and improves response quality. -- **Open source mode**: The server installs a connector package (from PyPI, a git URL, or a local path) and calls the third-party API directly using your credentials. +## Troubleshooting -- **Hosted mode**: The server calls the Airbyte Cloud API, which manages credentials and provides additional capabilities like indexed search through the [context store](../platform/context-store). +### Authentication fails -A command line tool called `agent-engine` manages the full lifecycle: +- Make sure you have an active account at [app.airbyte.ai](https://app.airbyte.ai). +- Try logging out of your agent's MCP integration and reconnecting to trigger a fresh OAuth flow. +- If you joined a new Airbyte organization, authenticate again to refresh your access. -1. **Discover** connectors with `agent-engine connectors list-oss` or `agent-engine connectors list-cloud`. +### Agent can't find the MCP server -2. **Configure** a connector with `agent-engine connectors configure`, which generates a YAML config file. +- Restart your agent after adding the MCP server configuration. +- Verify the server URL is exactly `https://mcp.airbyte.ai/mcp` in your configuration. +- Check that your client supports Streamable HTTP or OAuth-based MCP servers. -3. **Register** the server with your AI tool using `agent-engine mcp add-to`. +### Connector credential flow doesn't complete -4. **Use** the server by prompting your AI tool with natural language questions. +- Make sure you visited the credential URL the agent provided and completed the form in the browser. +- If the flow timed out, ask the agent to start a new credential flow. -## Get started +### Queries return unexpected results -Follow the [Agent Engine MCP server tutorial](../tutorials/quickstarts/tutorial-mcp-server) to install the MCP server, configure a connector, and register it with your AI tool. You can be up and running in about 5 minutes. +- Ask the agent to describe the available entities before querying, so it picks the right one. +- For time-based queries, the agent resolves relative dates like "this week" or "last month" automatically. diff --git a/docs/ai-agents/mcp-server/troubleshooting.md b/docs/ai-agents/mcp-server/troubleshooting.md deleted file mode 100644 index 40be5a802120..000000000000 --- a/docs/ai-agents/mcp-server/troubleshooting.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -sidebar_label: "Troubleshooting" -sidebar_position: 5 ---- - -# Troubleshoot the MCP server - -This page covers common issues you may encounter when using the Agent Engine MCP server. - -## MCP server not found - -Your agent can't discover the MCP server's tools. - -- Ensure you restarted your agent after registering the server. -- Verify the registration succeeded by checking your agent's MCP server list or configuration file. - -## Environment variable errors - -The MCP server fails to start or returns credential errors. - -- Verify your `.env` file is in the same directory where you run `agent-engine` commands. -- Confirm the variable names in your `.env` file match the `${env.VAR_NAME}` placeholders in your YAML configuration. -- Check that there are no extra spaces or characters in your `.env` values. - -## HTTP 401 errors - -Authentication failed. - -- **Open source mode**: Your API credential is invalid or expired. Generate a new credential from the third-party service and update your `.env` file. -- **Hosted mode**: Your Agent Engine credentials are invalid. Run `uv run agent-engine login ` to re-enter your Client ID and Secret. - -## HTTP 403 errors - -Authentication succeeded but the request is forbidden. - -- Your API credential doesn't have the required permissions. Check the third-party service's documentation for the scopes or roles your credential needs. - -## Long text fields are truncated - -For `list` and `search` results, the MCP server truncates text fields longer than 200 characters to reduce token usage. Truncated fields are marked with `[truncated]`. To get the full value: - -1. Use the `get` action with the record ID. -2. If `get` is not available, retry the original query with `skip_truncation=true` and tight `select_fields` and `limit`. - -## Search returns no results - -If `search` returns no results but you expect data: - -- The `search` action only works in [hosted mode](configuration#hosted-mode) with the [context store](../platform/context-store) enabled. In open source mode, use `list` with date boundary parameters instead. -- The search index may lag behind by hours. Try `list` with date boundary parameters instead. -- Try `fuzzy` matching instead of `like` in your filter (e.g., `{"fuzzy": {"name": "search term"}}`). - -## Date range queries miss recent data - -When querying date ranges that include today, the search index may not have the latest records. Issue both a `search` call and a `list` call with date boundary parameters, then merge results and deduplicate by ID. diff --git a/docs/ai-agents/mcp-server/usage.md b/docs/ai-agents/mcp-server/usage.md deleted file mode 100644 index 8b1a0bbf51af..000000000000 --- a/docs/ai-agents/mcp-server/usage.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -sidebar_label: "Advanced use" -sidebar_position: 3 ---- - -# Advanced use of the MCP server - -This page covers the MCP tools that the server exposes, field selection and exclusion, downloads, transport modes, and the terminal chat interface. - -## MCP tools reference - -When you register the MCP server with your agent, it exposes the following tools. Your agent discovers and calls these tools automatically based on your prompts. - -### `__execute` - -The primary tool. Executes an operation on a connector entity. - -| Parameter | Type | Description | -| ----------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `entity` | string | Entity name, like `users`, `calls`, or `issues`. | -| `action` | string | Operation to perform: `list`, `get`, `search`, or `download`. The `search` action is available in [hosted mode](configuration#hosted-mode) and supports filtering, sorting, and pagination. The `list` action returns all records and is available in both modes. | -| `params` | object or string | Operation parameters (varies by entity and action). | -| `select_fields` | list of strings | Fields to include in the response. | -| `exclude_fields` | list of strings | Fields to remove from the response. | -| `skip_truncation` | boolean | Disable long-text truncation for list/search responses. | - -### `__connector_info` - -Returns connector metadata including the connector name, version, and a list of available entities with their supported actions and parameters. Call this tool to discover what data the connector can access. - -### `__entity_schema` - -Returns the JSON schema for a specific entity. Call this tool to understand the structure of an entity's data before querying it. - -| Parameter | Type | Description | -| --- | --- | --- | -| `entity` | string | Entity name to get the schema for | - -### `get_instructions` - -Returns the built-in instructions for using the MCP server effectively, including best practices for action selection, field selection, query sizing, and date range handling. - -### `current_datetime` - -Returns the current date and time in ISO 8601 format (UTC). Agents should call this before any time-based query to get accurate date references. - -## Field selection and exclusion - -Every `execute` call should include either `select_fields` or `exclude_fields` to control what data is returned. This reduces token usage and improves response quality. - -### `select_fields` (allowlist) - -Returns only the specified fields: - -```text -select_fields=["id", "title", "started", "primaryUserId"] -``` - -### `exclude_fields` (blocklist) - -Returns all fields except the specified ones: - -```text -exclude_fields=["content", "interaction", "parties", "context"] -``` - -If you provide both, `select_fields` takes priority and `exclude_fields` is ignored. - -### Dot notation for nested fields - -Both `select_fields` and `exclude_fields` support dot notation to target nested fields: - -```text -select_fields=["id", "title", "content.topics", "content.brief"] -exclude_fields=["content.trackers", "interaction.speakers"] -``` - -## Downloads - -Some entities support a `download` action for binary content like call recordings. The MCP server saves downloaded files to a local directory and returns metadata about the saved file: - -```json -{ - "download": { - "file_path": "~/.airbyte_agent_mcp/downloads/call_audio_a1b2c3d4e5f6.mp3", - "size_bytes": 1048576, - "entity": "call_audio", - "message": "File downloaded and saved to: ~/.airbyte_agent_mcp/downloads/call_audio_a1b2c3d4e5f6.mp3 (1,048,576 bytes)." - } -} -``` - -Files are saved to `~/.airbyte_agent_mcp/downloads/` (or `~/.airbyte_agent_mcp/orgs//downloads/` in hosted mode). The file name is generated from the entity name and a random identifier, and the extension is detected automatically from the file content. - -## Transport modes - -### stdio (default) - -The default transport mode. The MCP server communicates over standard input/output, which is how most AI coding tools expect to interact with MCP servers. This is what `agent-engine mcp add-to` configures. - -### HTTP - -For integrations that need an HTTP endpoint: - -```bash -uv run agent-engine mcp serve connector-gong-package.yaml --transport http --port 8080 -``` - -| Flag | Default | Description | -| --- | --- | --- | -| `--transport`, `-t` | `stdio` | Transport protocol (`stdio` or `http`) | -| `--host`, `-h` | `127.0.0.1` | Host to bind to | -| `--port`, `-p` | `8000` | Port to bind to | - -## Terminal chat - -The `agent-engine chat` command is a lightweight terminal agent for querying your connector data with natural language. It uses Claude to interpret your questions, call the MCP server tools, and return formatted answers without needing an IDE integration. This is useful for testing your connector setup or running ad-hoc data queries. - -`agent-engine chat` requires an `ANTHROPIC_API_KEY` environment variable and only supports Anthropic models. The default model is `claude-opus-4-6`. Use `--model` to select a different Anthropic model. - -### One-shot mode - -Pass a prompt as an argument to get a single response. Tool call progress is written to stderr, so you can pipe the final answer to a file: - -```bash -uv run agent-engine chat connector-gong-package.yaml "show me 5 recent calls" -``` - -Use `--quiet` to hide tool call details and show only the final answer. - -```bash -uv run agent-engine chat connector-gong-package.yaml "show me 5 recent calls" --quiet -``` - -You can also use an aggregate configuration. - -```bash -uv run agent-engine chat connectors.yaml "show me 5 users from each system" -``` - -### Interactive REPL - -Omit the prompt to start an interactive session. The REPL maintains conversation history across turns, so you can ask follow-up questions. - -```bash -uv run agent-engine chat connector-gong-package.yaml -``` - -Type `exit`, `quit`, or press Ctrl-C to end the session. diff --git a/docs/ai-agents/tutorials/quickstarts/tutorial-mcp-server.md b/docs/ai-agents/tutorials/quickstarts/tutorial-mcp-server.md deleted file mode 100644 index 563212df5787..000000000000 --- a/docs/ai-agents/tutorials/quickstarts/tutorial-mcp-server.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -sidebar_label: "Agent Engine MCP" -sidebar_position: 4 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Agent Engine MCP server tutorial - -In this tutorial, you install Airbyte's Agent Engine MCP server, configure a connector, and register the server with your agent. Once registered, you can use natural language to query your data sources. You don't have to write any code. - -This tutorial uses GitHub as an example, but you can substitute any [agent connector](../../connectors/) that Airbyte supports. - -## Overview - -This tutorial is for somewhat technical users who work with data and AI agents. You can complete it in about 5 minutes. - -The tutorial assumes you have basic familiarity with: - -- Python and package management with [uv](https://github.com/astral-sh/uv) - -- MCP servers - -## Before you start - -Before you begin this tutorial, ensure you have the following. - -- [Python](https://www.python.org/downloads/) version 3.13 or later - -- [uv](https://docs.astral.sh/uv/getting-started/installation/) - -- A [GitHub personal access token](https://github.com/settings/tokens). For this tutorial, a classic token with `repo` scope is sufficient. - -- An agent that supports MCP servers - -## Part 1: Create a project - -Create a directory for your MCP server configuration and initialize a `uv` project. - -```bash -mkdir my-mcp-server && cd my-mcp-server -uv init --python 3.13 -``` - -Add `airbyte-agent-mcp` as a dependency. This installs the package and makes the `agent-engine` command-line tool available through `uv run`. You use `agent-engine` to discover connectors, generate configurations, and register the MCP server with your agent. - -```bash -uv add airbyte-agent-mcp -``` - -## Part 2: List available connectors - -Run the following command to see the available open source connectors. This queries the Airbyte connector registry and displays a table of available connectors, their package names, versions, and definition IDs. - -```bash -uv run agent-engine connectors list-oss -``` - -To filter connectors by name, use the `--pattern` flag - -```bash -uv run agent-engine connectors list-oss --pattern github -``` - -## Part 3: Generate a connector configuration - -Generate a configuration file for the GitHub connector: - -```bash -uv run agent-engine connectors configure --package airbyte-agent-github -``` - -This installs the connector package, inspects its authentication requirements, and generates a YAML configuration file called `connector-github-package.yaml`. The file looks like this: - -```yaml title="connector-github-package.yaml" -connector: - package: airbyte-agent-github -credentials: - access_token: ${env.GITHUB_ACCESS_TOKEN} -``` - -The `${env.GITHUB_ACCESS_TOKEN}` placeholder tells the MCP server to read the value from an environment variable. You set this in the next step. - -:::note -Some connectors support multiple authentication methods. The `configure` command may include commented-out alternatives in the generated file. You only need to configure one method. -::: - -## Part 4: Set your credentials - -Create a `.env` file in the same directory as your connector configuration. Replace the placeholder with your actual GitHub personal access token. - -```text title=".env" -GITHUB_ACCESS_TOKEN=your-github-personal-access-token -``` - -The `agent-engine` command line tool automatically loads `.env` files from the current directory. The `${env.VAR}` syntax in your YAML configuration resolves to the values in this file. - -:::warning -Never commit your `.env` file to version control. If you do this by mistake, rotate your secrets immediately. -::: - -## Part 5: Register with your agent - -Register the MCP server with your preferred agent. - - - - -This command runs `claude mcp add` under the hood and registers the server at the user scope. - -```bash -uv run agent-engine mcp add-to claude-code connector-github-package.yaml -``` - -To register at the project scope instead, add `--scope project` to that command. - - - - -This command modifies your Claude Desktop configuration file directly. - -```bash -uv run agent-engine mcp add-to claude-desktop connector-github-package.yaml -``` - - - - -This modifies the Cursor MCP configuration file. - -```bash -uv run agent-engine mcp add-to cursor connector-github-package.yaml -``` - -To register at the project scope instead of user scope, add a `--scope project` flag. - - - - -This command runs `codex mcp add` to register the server. - -```bash -uv run agent-engine mcp add-to codex connector-github-package.yaml -``` - - - - -You can optionally specify a custom name for the server with `--name`. If you don't specify a name, the server name is based on the connector. For example, `airbyte-github`. - -```bash -uv run agent-engine mcp add-to claude-code connector-github-package.yaml --name my-server-name -``` - -## Part 6: Use the MCP server - -1. Restart your agent so it picks up the new MCP server registration. - -2. Once restarted, prompt your agent with natural language questions about your GitHub data. Try prompts like: - - - `List the 5 most recent open issues in airbytehq/airbyte` - - - `Show me the latest pull requests in my-org/my-repo` - - - `What are the open issues assigned to octocat?` - -Your agent discovers the MCP server's tools automatically and calls them based on your prompts. The MCP server handles executing the connector operations and returning the results. If your agent fails to retrieve data, see [Troubleshoot the MCP server](../../mcp-server/troubleshooting). - -## Summary - -In this tutorial, you learned how to: - -- Set up a project with the Agent Engine MCP server - -- Discover available connectors with the `agent-engine` command line tool - -- Generate a connector configuration file - -- Set credentials using environment variables - -- Register the MCP server with your agent - -- Query data using natural language prompts - -## Next steps - -- Try other connectors. Run `uv run agent-engine connectors list-oss` to see all available connectors and repeat these steps with a different data source. - -- Learn how to [configure the MCP server](../../mcp-server/configuration) for advanced scenarios like Agent Engine hosted execution, git-based packages, and aggregate configurations with multiple connectors. - -- Learn about [field selection, downloads, and other advanced features](../../mcp-server/usage). From 3914761104750377ba0c0ac33b30425127285806 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2026 20:14:39 +0000 Subject: [PATCH 019/379] docs(source-gitlab): improve rate limits, fix outdated tier names, document 403 behavior (#75538) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- docs/integrations/sources/gitlab.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/integrations/sources/gitlab.md b/docs/integrations/sources/gitlab.md index b587a94adc67..eb2e3a9be559 100644 --- a/docs/integrations/sources/gitlab.md +++ b/docs/integrations/sources/gitlab.md @@ -80,8 +80,8 @@ This connector outputs the following streams: - [Branches](https://docs.gitlab.com/ee/api/branches.html) - [Commits](https://docs.gitlab.com/ee/api/commits.html) (Incremental) - [Deployments](https://docs.gitlab.com/ee/api/deployments/index.html) -- [Epic Issues](https://docs.gitlab.com/ee/api/epic_issues.html) (GitLab Ultimate and GitLab.com Gold only) -- [Epics](https://docs.gitlab.com/ee/api/epics.html) (GitLab Ultimate and GitLab.com Gold only) +- [Epic Issues](https://docs.gitlab.com/ee/api/epic_issues.html) (GitLab Ultimate only) +- [Epics](https://docs.gitlab.com/ee/api/epics.html) (GitLab Ultimate only) - [Group Issue Boards](https://docs.gitlab.com/ee/api/group_boards.html) - [Group Labels](https://docs.gitlab.com/ee/api/group_labels.html) - [Group Members](https://docs.gitlab.com/ee/api/members.html) @@ -109,7 +109,7 @@ This connector uses GitLab API v4. It works with both GitLab.com and self-hosted ### Rate limits -GitLab.com enforces [per-endpoint rate limits](https://docs.gitlab.com/ee/user/gitlab_com/#gitlabcom-specific-rate-limits) on its REST API. Key limits that affect this connector include: +GitLab.com enforces per-endpoint rate limits on its REST API. The following defaults apply to [Groups API](https://docs.gitlab.com/administration/settings/rate_limit_on_members_api/), [Projects API](https://docs.gitlab.com/administration/settings/rate_limit_on_projects_api/), and general authenticated traffic: | Endpoint | Rate limit | | :--- | :--- | @@ -120,9 +120,13 @@ GitLab.com enforces [per-endpoint rate limits](https://docs.gitlab.com/ee/user/g | `GET /projects/:id/members/all` | 200 requests/min | | All other authenticated requests | 2,000 requests/min | -Self-hosted GitLab instances may have different rate limits configured by the administrator. If you encounter rate limit errors that are not automatically retried, [create an issue](https://github.com/airbytehq/airbyte/issues). +Self-hosted GitLab instances may have different rate limits configured by the administrator. The connector automatically retries requests that receive HTTP 429 responses. If you encounter persistent rate limit errors, [create an issue](https://github.com/airbytehq/airbyte/issues). -You can adjust the **Number of Concurrent Workers** setting to control how many parallel requests the connector makes. The default value of 8 is suitable for most GitLab.com users. Lower this value if you share your API quota with other integrations. +You can adjust the **Number of Concurrent Workers** setting to control how many parallel requests the connector makes. Lower this value if you share your API quota with other integrations or if you experience rate limiting. + +### Inaccessible resources + +The connector silently skips any group, project, or resource that returns an HTTP 403 (Forbidden) response. If you notice missing data, verify that your access token has the required permissions for the groups and projects you want to sync. ## Changelog From 8ce1756e048135a5ed7e1d685be3b58fa4e6972c Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2026 21:59:31 +0000 Subject: [PATCH 020/379] feat(source-gong): migrate OAuth scope to scopes object array (#75195) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: aldo.gonzalez@airbyte.io Co-authored-by: Serhii Lazebnyi --- .../connectors/source-gong/manifest.yaml | 11 +++++++++-- .../connectors/source-gong/metadata.yaml | 2 +- docs/integrations/sources/gong.md | 1 + 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/airbyte-integrations/connectors/source-gong/manifest.yaml b/airbyte-integrations/connectors/source-gong/manifest.yaml index b268184441ba..b680ef0736a1 100644 --- a/airbyte-integrations/connectors/source-gong/manifest.yaml +++ b/airbyte-integrations/connectors/source-gong/manifest.yaml @@ -548,7 +548,7 @@ spec: predicate_value: OAuth2.0 oauth_config_specification: oauth_connector_input_specification: - consent_url: https://app.gong.io/oauth2/authorize?client_id={{client_id_value}}&redirect_uri={{redirect_uri_value}}&response_type=code&state={{state_value}}&scope={{scope_value | urlEncode}} + consent_url: https://app.gong.io/oauth2/authorize?client_id={{client_id_value}}&redirect_uri={{redirect_uri_value}}&response_type=code&state={{state_value}}&{{scopes_param}} access_token_url: https://app.gong.io/oauth2/generate-customer-token access_token_headers: Authorization: "Basic {{ (client_id_value ~ ':' ~ client_secret_value) | b64encode }}" @@ -557,7 +557,14 @@ spec: grant_type: authorization_code redirect_uri: "{{ redirect_uri_value }}" code: "{{ auth_code_value }}" - scope: api:calls:read:basic api:calls:read:extensive api:users:read api:stats:scorecards api:stats:interaction + scopes: + - scope: "api:calls:read:basic" + - scope: "api:calls:read:extensive" + - scope: "api:calls:read:transcript" + - scope: "api:users:read" + - scope: "api:stats:scorecards" + - scope: "api:stats:interaction" + - scope: "api:settings:scorecards:read" extract_output: - access_token - refresh_token diff --git a/airbyte-integrations/connectors/source-gong/metadata.yaml b/airbyte-integrations/connectors/source-gong/metadata.yaml index de766ad3b253..d89b7715f054 100644 --- a/airbyte-integrations/connectors/source-gong/metadata.yaml +++ b/airbyte-integrations/connectors/source-gong/metadata.yaml @@ -7,7 +7,7 @@ data: connectorSubtype: api connectorType: source definitionId: 32382e40-3b49-4b99-9c5c-4076501914e7 - dockerImageTag: 0.6.2 + dockerImageTag: 0.6.3 dockerRepository: airbyte/source-gong documentationUrl: https://docs.airbyte.com/integrations/sources/gong githubIssueLabel: source-gong diff --git a/docs/integrations/sources/gong.md b/docs/integrations/sources/gong.md index 47973d11b217..c2731ea0569d 100644 --- a/docs/integrations/sources/gong.md +++ b/docs/integrations/sources/gong.md @@ -77,6 +77,7 @@ The call transcripts stream fetches transcripts one call at a time as a substrea | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------ | +| 0.6.3 | 2026-03-26 | [75195](https://github.com/airbytehq/airbyte/pull/75195) | Migrate OAuth scope to scopes object array for granular scopes support | | 0.6.2 | 2026-03-24 | [75388](https://github.com/airbytehq/airbyte/pull/75388) | Update dependencies | | 0.6.1 | 2026-03-20 | [75253](https://github.com/airbytehq/airbyte/pull/75253) | Fix incremental sync for extensiveCalls and answeredScorecards not filtering server-side | | 0.6.0 | 2026-03-18 | [75132](https://github.com/airbytehq/airbyte/pull/75132) | Add incremental sync support for callTranscripts stream | From 9645724d901680eb933316985fb6ff38d1a919f8 Mon Sep 17 00:00:00 2001 From: "octavia-bot[bot]" <108746235+octavia-bot[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2026 22:11:45 +0000 Subject: [PATCH 021/379] docs: sync agent connector docs from airbyte-agent-connectors repo (#75548) Co-authored-by: ian-at-airbyte <187576150+ian-at-airbyte@users.noreply.github.com> --- .../connectors/google-analytics-data-api/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/ai-agents/connectors/google-analytics-data-api/README.md b/docs/ai-agents/connectors/google-analytics-data-api/README.md index a3eefcac967f..f0f0b6450a6d 100644 --- a/docs/ai-agents/connectors/google-analytics-data-api/README.md +++ b/docs/ai-agents/connectors/google-analytics-data-api/README.md @@ -122,7 +122,7 @@ See the official [Google-Analytics-Data-Api API reference](https://developers.go ## Version information -- **Package version:** 0.1.14 -- **Connector version:** 1.0.2 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.15 +- **Connector version:** 1.0.3 +- **Generated with Connector SDK commit SHA:** 07e3903513e36163d0cec8f1bc552df4bd6c022d - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/google-analytics-data-api/CHANGELOG.md) \ No newline at end of file From 08e7729876d035c51cf79356a9b70587b7576f7d Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2026 22:11:50 +0000 Subject: [PATCH 022/379] docs(source-gong): update OAuth scopes in prerequisites and fix changelog date (#75547) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- docs/integrations/sources/gong.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/integrations/sources/gong.md b/docs/integrations/sources/gong.md index c2731ea0569d..85a413ae4255 100644 --- a/docs/integrations/sources/gong.md +++ b/docs/integrations/sources/gong.md @@ -10,7 +10,8 @@ This page contains the setup guide and reference information for the [Gong](http - A Gong account with technical administrator permissions - For API Key authentication: an access key and access key secret generated from the Gong API settings -- For OAuth 2.0 authentication: the following API scopes must be granted: `api:calls:read:basic`, `api:calls:read:extensive`, `api:users:read`, `api:stats:scorecards`, `api:stats:interaction` +- For OAuth 2.0 authentication: the following API scopes must be granted: `api:calls:read:basic`, `api:calls:read:extensive`, `api:calls:read:transcript`, `api:users:read`, `api:stats:scorecards`, `api:stats:interaction`, `api:settings:scorecards:read` +- For API Key authentication: the API key must have the same scopes listed above granted in the Gong API settings ## Setup guide @@ -77,7 +78,7 @@ The call transcripts stream fetches transcripts one call at a time as a substrea | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------ | -| 0.6.3 | 2026-03-26 | [75195](https://github.com/airbytehq/airbyte/pull/75195) | Migrate OAuth scope to scopes object array for granular scopes support | +| 0.6.3 | 2026-03-27 | [75195](https://github.com/airbytehq/airbyte/pull/75195) | Migrate OAuth scope to scopes object array for granular scopes support | | 0.6.2 | 2026-03-24 | [75388](https://github.com/airbytehq/airbyte/pull/75388) | Update dependencies | | 0.6.1 | 2026-03-20 | [75253](https://github.com/airbytehq/airbyte/pull/75253) | Fix incremental sync for extensiveCalls and answeredScorecards not filtering server-side | | 0.6.0 | 2026-03-18 | [75132](https://github.com/airbytehq/airbyte/pull/75132) | Add incremental sync support for callTranscripts stream | From 671c4e1feb12a8bada5a4dd8fbe476f7d049ed8b Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2026 23:33:34 +0000 Subject: [PATCH 023/379] feat(source-slack): add oauth_connector_input_specification for granular scopes (#75197) Co-authored-by: Serhii Lazebnyi Co-authored-by: Serhii Lazebnyi --- .../connectors/source-slack/manifest.yaml | 25 ++++++++++++++++++- .../connectors/source-slack/metadata.yaml | 2 +- docs/integrations/sources/slack.md | 1 + 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-slack/manifest.yaml b/airbyte-integrations/connectors/source-slack/manifest.yaml index b6856f89cf32..9111d3cfabe5 100644 --- a/airbyte-integrations/connectors/source-slack/manifest.yaml +++ b/airbyte-integrations/connectors/source-slack/manifest.yaml @@ -508,7 +508,30 @@ spec: - option_title predicate_value: Default OAuth2.0 authorization oauth_config_specification: -# oauth_user_input_from_connector_config_specification: + oauth_connector_input_specification: + consent_url: "https://slack.com/oauth/v2/authorize?{{client_id_param}}&{{redirect_uri_param}}&{{state_param}}&{{scopes_param}}" + access_token_url: "https://slack.com/api/oauth.v2.access" + access_token_headers: + Content-Type: "application/x-www-form-urlencoded" + access_token_params: + code: "{{ auth_code_value }}" + client_id: "{{ client_id_value }}" + client_secret: "{{ client_secret_value }}" + redirect_uri: "{{ redirect_uri_value }}" + scopes: + - scope: "channels:history" + - scope: "channels:join" + - scope: "channels:read" + - scope: "groups:read" + - scope: "groups:history" + - scope: "users:read" + - scope: "im:history" + - scope: "mpim:history" + - scope: "im:read" + - scope: "mpim:read" + scopes_join_strategy: comma + extract_output: + - access_token complete_oauth_output_specification: type: object additionalProperties: false diff --git a/airbyte-integrations/connectors/source-slack/metadata.yaml b/airbyte-integrations/connectors/source-slack/metadata.yaml index 9ec002a1c48a..b0e57e4bbd26 100644 --- a/airbyte-integrations/connectors/source-slack/metadata.yaml +++ b/airbyte-integrations/connectors/source-slack/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: api connectorType: source definitionId: c2281cee-86f9-4a86-bb48-d23286b4c7bd - dockerImageTag: 3.1.13 + dockerImageTag: 3.1.14 dockerRepository: airbyte/source-slack documentationUrl: https://docs.airbyte.com/integrations/sources/slack externalDocumentationUrls: diff --git a/docs/integrations/sources/slack.md b/docs/integrations/sources/slack.md index da804e347c00..707f9d9a7fc2 100644 --- a/docs/integrations/sources/slack.md +++ b/docs/integrations/sources/slack.md @@ -183,6 +183,7 @@ These two streams are effectively limited to **one request per minute**. Conside | Version | Date | Pull Request | Subject | |:-----------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 3.1.14 | 2026-03-27 | [75197](https://github.com/airbytehq/airbyte/pull/75197) | Add declarative OAuth with `oauth_connector_input_specification` and granular scopes | | 3.1.13 | 2026-03-24 | [75329](https://github.com/airbytehq/airbyte/pull/75329) | Update dependencies | | 3.1.12 | 2026-03-10 | [74598](https://github.com/airbytehq/airbyte/pull/74598) | Update dependencies | | 3.1.11 | 2026-02-24 | [73948](https://github.com/airbytehq/airbyte/pull/73948) | Update dependencies | From 13b14ff5ba6107c3d19612cf1d70e1850d49a777 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Fri, 27 Mar 2026 18:17:03 -0700 Subject: [PATCH 024/379] ci: delete 6 dead workflows that depend on airbyte-ci (#75552) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../approve-regression-tests-command.yml | 125 ------- .../workflows/internal-airbyte-ci-release.yml | 132 -------- .../workflows/internal-airbyte-ci-tests.yml | 134 -------- .github/workflows/run-cat-tests-command.yml | 101 ------ .github/workflows/run-live-tests-command.yml | 177 ---------- .../run-regression-tests-command.yml | 315 ------------------ 6 files changed, 984 deletions(-) delete mode 100644 .github/workflows/approve-regression-tests-command.yml delete mode 100644 .github/workflows/internal-airbyte-ci-release.yml delete mode 100644 .github/workflows/internal-airbyte-ci-tests.yml delete mode 100644 .github/workflows/run-cat-tests-command.yml delete mode 100644 .github/workflows/run-live-tests-command.yml delete mode 100644 .github/workflows/run-regression-tests-command.yml diff --git a/.github/workflows/approve-regression-tests-command.yml b/.github/workflows/approve-regression-tests-command.yml deleted file mode 100644 index ae6640a6a541..000000000000 --- a/.github/workflows/approve-regression-tests-command.yml +++ /dev/null @@ -1,125 +0,0 @@ -name: Approve Regression Tests -permissions: - pull-requests: write - statuses: write -on: - workflow_dispatch: - inputs: - pr: - description: "Pull request number. Used to pull the proper branch ref, including on forks." - type: number - required: false - comment-id: - description: "Optional. The comment-id of the slash command. Used to update the comment with the status." - required: false - connector-name: - description: "Optional. Name of the connector whose regression tests are approved." - required: false - - # These must be declared, but they are unused and ignored. - # TODO: Infer 'repo' and 'gitref' from PR number on other workflows, so we can remove these. - repo: - description: "Repo (Ignored)" - required: false - default: "airbytehq/airbyte" - gitref: - description: "Ref (Ignored)" - required: false - -run-name: "Approve Regression Tests #${{ github.event.inputs.pr }}" - -jobs: - approve-regression-tests: - name: "Approve Regression Tests" - runs-on: ubuntu-24.04 - steps: - - name: Get job variables - id: job-vars - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - shell: bash - run: | - PR_JSON=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.inputs.pr }}) - echo "PR_JSON: $PR_JSON" - echo "repo=$(echo "$PR_JSON" | jq -r .head.repo.full_name)" >> $GITHUB_OUTPUT - BRANCH=$(echo "$PR_JSON" | jq -r .head.ref) - echo "branch=$BRANCH" >> $GITHUB_OUTPUT - echo "run-url=https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" >> $GITHUB_OUTPUT - LATEST_COMMIT=$(gh api repos/${{ github.repository }}/commits/$BRANCH | jq -r .sha) - echo "latest_commit=$LATEST_COMMIT" >> $GITHUB_OUTPUT - - - name: Append comment with job run link - # If comment-id is not provided, this will create a new - # comment with the job run link. - id: first-comment-action - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 - with: - comment-id: ${{ github.event.inputs.comment-id }} - issue-number: ${{ github.event.inputs.pr }} - body: | - - > [Check job output.][1] - - [1]: ${{ steps.job-vars.outputs.run-url }} - - - name: Approve regression tests - id: approve-regression-tests - if: github.event.inputs.connector-name != null - run: | - echo "approving regression test status check for ${{ github.event.inputs.connector-name }} if it exists ...." - response=$(curl --write-out '%{http_code}' --silent --output /dev/null \ - --request POST \ - --url ${{ github.api_url }}/repos/${{ github.repository }}/statuses/${{ steps.job-vars.outputs.latest_commit }} \ - --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \ - --header 'content-type: application/json' \ - --data '{ - "state": "success", - "context": "Regression Tests on ${{ github.event.inputs.connector-name }}", - "target_url": "https://github.com/airbytehq/airbyte/tree/master/airbyte-ci/connectors/live-tests" - }') - if [ $response -ne 201 ]; then - echo "Failed to approve regression tests for ${{ github.event.inputs.connector-name }}. HTTP status code: $response" - exit 1 - else - echo "Regression tests for ${{ github.event.inputs.connector-name }} approved." - fi - - - name: Update global regression test approval - id: update-global-regression-test-approval - if: github.event.inputs.connector-name == null - run: | - echo "updating regression test approval status check if it exists ...." - response=$(curl --write-out '%{http_code}' --silent --output /dev/null \ - --request POST \ - --url ${{ github.api_url }}/repos/${{ github.repository }}/statuses/${{ steps.job-vars.outputs.latest_commit }} \ - --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \ - --header 'content-type: application/json' \ - --data '{ - "state": "success", - "context": "Regression Test Results Reviewed and Approved", - "target_url": "https://github.com/airbytehq/airbyte/tree/master/airbyte-ci/connectors/live-tests" - }') - if [ $response -ne 201 ]; then - echo "Failed to update regression test approval status check. HTTP status code: $response" - exit 1 - else - echo "Regression test status check updated." - fi - - - name: Append success comment - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 - if: success() - with: - comment-id: ${{ steps.first-comment-action.outputs.comment-id }} - reactions: "+1" - body: | - > ✅ Approving regression tests - - - name: Append failure comment - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 - if: failure() - with: - comment-id: ${{ steps.first-comment-action.outputs.comment-id }} - reactions: confused - body: | - > ❌ Regression test approval failed diff --git a/.github/workflows/internal-airbyte-ci-release.yml b/.github/workflows/internal-airbyte-ci-release.yml deleted file mode 100644 index fcc2b257ec60..000000000000 --- a/.github/workflows/internal-airbyte-ci-release.yml +++ /dev/null @@ -1,132 +0,0 @@ -name: Connector Ops CI - Airbyte CI Release - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -on: - push: - paths: - - "airbyte-ci/connectors/pipelines/**" - workflow_dispatch: - -env: - DEV_GCS_BUCKET_NAME: dev-airbyte-cloud-connector-metadata-service-2 - PROD_GCS_BUCKET_NAME: prod-airbyte-cloud-connector-metadata-service - BINARY_FILE_NAME: airbyte-ci - -jobs: - build: - runs-on: ${{ matrix.os }}-latest - strategy: - fail-fast: false - matrix: - os: ["ubuntu", "macos"] - - steps: - - name: Checkout Airbyte - id: checkout_airbyte - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - with: - ref: ${{ github.sha }} # This is required to make sure that the same commit is checked out on all runners - - - name: Get short SHA - id: get_short_sha - uses: benjlevesque/short-sha@36eb8c530990ceac5ddf3c0bc32d02c677ae9706 # v2.2 - - - name: Install Python - id: install_python - uses: actions/setup-python@7f4fc3e22c37d6ff65e88745f38bd3157c663f7c # v4.9.1 - with: - python-version: "3.11" - check-latest: true - update-environment: true - - - name: Install Poetry - id: install_poetry - uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1.4.1 - with: - version: 1.8.5 - - - name: Install Dependencies - id: install_dependencies - working-directory: airbyte-ci/connectors/pipelines/ - run: poetry install --with dev - - - name: Build release - id: build_release - working-directory: airbyte-ci/connectors/pipelines/ - run: poetry run poe build-release-binary ${{ env.BINARY_FILE_NAME }} - - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: airbyte-ci-${{ matrix.os }}-${{ steps.get_short_sha.outputs.sha }} - path: airbyte-ci/connectors/pipelines/dist/${{ env.BINARY_FILE_NAME }} - - - name: Authenticate to Google Cloud Dev - id: auth_dev - uses: google-github-actions/auth@3a3c4c57d294ef65efaaee4ff17b22fa88dd3c69 # v1.3.0 - with: - credentials_json: "${{ secrets.METADATA_SERVICE_DEV_GCS_CREDENTIALS }}" - - - name: Upload pre-release to GCS dev bucket - id: upload_pre_release_to_gcs - if: github.ref != 'refs/heads/master' - uses: google-github-actions/upload-cloud-storage@e95a15f226403ed658d3e65f40205649f342ba2c # v1.0.3 - with: - path: airbyte-ci/connectors/pipelines/dist/${{ env.BINARY_FILE_NAME }} - destination: ${{ env.DEV_GCS_BUCKET_NAME }}/airbyte-ci/releases/${{ matrix.os }}/${{ steps.get_short_sha.outputs.sha }} - headers: |- - cache-control:public, max-age=10 - - - name: Print pre-release public url - id: print_pre_release_public_url - run: | - echo "https://storage.googleapis.com/${{ env.DEV_GCS_BUCKET_NAME }}/airbyte-ci/releases/${{ matrix.os }}/${{ steps.get_short_sha.outputs.sha }}/${{ env.BINARY_FILE_NAME }}" - - # if master, upload per version and latest to prod bucket - - - name: Set version from poetry version --short - id: set_version - if: github.ref == 'refs/heads/master' - working-directory: airbyte-ci/connectors/pipelines/ - run: | - echo "version=$(poetry version --short)" >> $GITHUB_OUTPUT - - - name: Authenticate to Google Cloud Prod - id: auth_prod - uses: google-github-actions/auth@3a3c4c57d294ef65efaaee4ff17b22fa88dd3c69 # v1.3.0 - with: - credentials_json: "${{ secrets.METADATA_SERVICE_PROD_GCS_CREDENTIALS }}" - - - name: Upload version release to GCS prod bucket - id: upload_version_release_to_gcs - if: github.ref == 'refs/heads/master' - uses: google-github-actions/upload-cloud-storage@e95a15f226403ed658d3e65f40205649f342ba2c # v1.0.3 - with: - path: airbyte-ci/connectors/pipelines/dist/${{ env.BINARY_FILE_NAME }} - destination: ${{ env.PROD_GCS_BUCKET_NAME }}/airbyte-ci/releases/${{ matrix.os }}/${{ steps.set_version.outputs.version }} - headers: |- - cache-control:public, max-age=10 - - - name: Print release version public url - id: print_version_release_public_url - if: github.ref == 'refs/heads/master' - run: | - echo "https://storage.googleapis.com/${{ env.PROD_GCS_BUCKET_NAME }}/airbyte-ci/releases/${{ matrix.os }}/${{ steps.set_version.outputs.version }}/${{ env.BINARY_FILE_NAME }}" - - - name: Upload latest release to GCS prod bucket - id: upload_latest_release_to_gcs - if: github.ref == 'refs/heads/master' - uses: google-github-actions/upload-cloud-storage@e95a15f226403ed658d3e65f40205649f342ba2c # v1.0.3 - with: - path: airbyte-ci/connectors/pipelines/dist/${{ env.BINARY_FILE_NAME }} - destination: ${{ env.PROD_GCS_BUCKET_NAME }}/airbyte-ci/releases/${{ matrix.os }}/latest - headers: |- - cache-control:public, max-age=10 - - - name: Print latest release public url - id: print_latest_release_public_url - if: github.ref == 'refs/heads/master' - run: | - echo "https://storage.googleapis.com/${{ env.PROD_GCS_BUCKET_NAME }}/airbyte-ci/releases/${{ matrix.os }}/latest/${{ env.BINARY_FILE_NAME }}" diff --git a/.github/workflows/internal-airbyte-ci-tests.yml b/.github/workflows/internal-airbyte-ci-tests.yml deleted file mode 100644 index d20c93f1cf52..000000000000 --- a/.github/workflows/internal-airbyte-ci-tests.yml +++ /dev/null @@ -1,134 +0,0 @@ -name: Internal CI Tooling Checks - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -on: - workflow_dispatch: - inputs: - airbyte_ci_subcommand: - description: "Subcommand to pass to the 'airbyte-ci test' command" - default: "--poetry-package-path=airbyte-ci/connectors/pipelines" - pull_request: - types: - - opened - - reopened - - synchronize -jobs: - changes: - name: Detect Changes - runs-on: ubuntu-24.04 - outputs: - internal_poetry_packages: ${{ steps.changes.outputs.internal_poetry_packages }} - - steps: - - name: Checkout Airbyte - if: github.event_name != 'pull_request' - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - - id: changes - uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50 # v2.11.1 - with: - # Note: expressions within a filter are OR'ed - filters: | - # This list is duplicated in `pipelines/airbyte_ci/test/__init__.py` - internal_poetry_packages: - - airbyte-ci/connectors/pipelines/** - - airbyte-ci/connectors/connectors_insights/** - - airbyte-ci/connectors/connector_ops/** - - airbyte-ci/connectors/ci_credentials/** - - airbyte-ci/connectors/erd/** - - airbyte-ci/connectors/metadata_service/lib/** - - airbyte-integrations/bases/connector-acceptance-test/** - - run-tests: - needs: changes - # We only run the Internal Poetry packages CI job if there are changes to the packages on a non-forked PR - if: needs.changes.outputs.internal_poetry_packages == 'true' && github.event.pull_request.head.repo.fork != true - name: Internal Poetry packages CI - runs-on: tooling-test-large - permissions: - pull-requests: read - statuses: write - steps: - - name: Checkout Airbyte - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - with: - fetch-depth: 0 - ref: ${{ github.event.pull_request.head.ref }} - - name: Checkout Airbyte Python CDK - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - with: - repository: airbytehq/airbyte-python-cdk - ref: main - # We can't clone into a parent directory of the repo, so we clone into - # a subdirectory and then move it over as a sibling directory. - # This will be used for the `--use-local-cdk` flag in `airbyte-ci` command - path: airbyte-python-cdk - - name: Move airbyte-python-cdk to sibling directory path - shell: bash - run: mv ./airbyte-python-cdk ../airbyte-python-cdk - - name: Show local paths checked out - shell: bash - run: | - set -x - echo "Current directory: $(pwd)" - ls -la - ls -la ../airbyte-python-cdk || echo "No airbyte-python-cdk directory" - - - name: Extract branch name [WORKFLOW DISPATCH] - shell: bash - if: github.event_name == 'workflow_dispatch' - run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT - id: extract_branch - - name: Fetch last commit id from remote branch [PULL REQUESTS] - if: github.event_name == 'pull_request' - id: fetch_last_commit_id_pr - run: echo "commit_id=$(git ls-remote --heads origin refs/heads/${{ github.head_ref }} | cut -f 1)" >> $GITHUB_OUTPUT - - name: Fetch last commit id from remote branch [WORKFLOW DISPATCH] - if: github.event_name == 'workflow_dispatch' - id: fetch_last_commit_id_wd - run: echo "commit_id=$(git rev-parse origin/${{ steps.extract_branch.outputs.branch }})" >> $GITHUB_OUTPUT - - - name: Authenticate as GitHub App - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 - id: get-app-token - with: - owner: "airbytehq" - repositories: "airbyte" - app-id: ${{ secrets.OCTAVIA_BOT_APP_ID }} - private-key: ${{ secrets.OCTAVIA_BOT_PRIVATE_KEY }} - - - name: Run poe tasks for modified internal packages [PULL REQUEST] - if: github.event_name == 'pull_request' - id: run-airbyte-ci-test-pr - uses: ./.github/actions/run-airbyte-ci - with: - context: "pull_request" - dagger_cloud_token: ${{ secrets.DAGGER_CLOUD_TOKEN_CACHE_5 }} - docker_hub_password: ${{ secrets.DOCKER_HUB_PASSWORD }} - docker_hub_username: ${{ secrets.DOCKER_HUB_USERNAME }} - gcp_gsm_credentials: ${{ secrets.GCP_GSM_CREDENTIALS }} - gcs_credentials: ${{ secrets.METADATA_SERVICE_PROD_GCS_CREDENTIALS }} - git_branch: ${{ github.head_ref }} - git_revision: ${{ steps.fetch_last_commit_id_pr.outputs.commit_id }} - github_token: ${{ steps.get-app-token.outputs.token }} - sentry_dsn: ${{ secrets.SENTRY_AIRBYTE_CI_DSN }} - subcommand: "test --modified" - - - name: Run poe tasks for requested internal packages [WORKFLOW DISPATCH] - id: run-airbyte-ci-test-workflow-dispatch - if: github.event_name == 'workflow_dispatch' - uses: ./.github/actions/run-airbyte-ci - with: - context: "manual" - dagger_cloud_token: ${{ secrets.DAGGER_CLOUD_TOKEN_CACHE_5 }} - docker_hub_password: ${{ secrets.DOCKER_HUB_PASSWORD }} - docker_hub_username: ${{ secrets.DOCKER_HUB_USERNAME }} - gcp_gsm_credentials: ${{ secrets.GCP_GSM_CREDENTIALS }} - gcs_credentials: ${{ secrets.METADATA_SERVICE_PROD_GCS_CREDENTIALS }} - git_branch: ${{ steps.extract_branch.outputs.branch }} - git_revision: ${{ steps.fetch_last_commit_id_pr.outputs.commit_id }} - github_token: ${{ steps.get-app-token.outputs.token }} - sentry_dsn: ${{ secrets.SENTRY_AIRBYTE_CI_DSN }} - subcommand: "test ${{ inputs.airbyte_ci_subcommand}}" diff --git a/.github/workflows/run-cat-tests-command.yml b/.github/workflows/run-cat-tests-command.yml deleted file mode 100644 index 6aa1827fe28b..000000000000 --- a/.github/workflows/run-cat-tests-command.yml +++ /dev/null @@ -1,101 +0,0 @@ -name: On-Demand CAT Tests (Legacy) -# This workflow is used to run the legacy CAT tests for modified connectors. -# It can be triggered manually via slash command or workflow dispatch. - -on: - workflow_dispatch: - inputs: - repo: - description: "The repository name" - required: false - type: string - gitref: - description: "The git reference (branch or tag)" - required: false - type: string - comment-id: - description: "The ID of the comment triggering the workflow" - required: false - type: number - pr: - description: "The pull request number, if applicable" - required: false - type: number - -run-name: "Run connector CAT tests in PR: #${{ github.event.inputs.pr }}" -concurrency: - group: ${{ github.workflow }}-${{ github.event.inputs.pr }} - # Cancel any previous runs on the same branch if they are still in progress - cancel-in-progress: true - -jobs: - run-cat-tests: - name: "On-Demand CAT Tests" - runs-on: ubuntu-24.04 - steps: - - name: Get job variables - id: job-vars - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - shell: bash - run: | - PR_JSON=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.inputs.pr }}) - echo "repo=$(echo "$PR_JSON" | jq -r .head.repo.full_name)" >> $GITHUB_OUTPUT - echo "branch=$(echo "$PR_JSON" | jq -r .head.ref)" >> $GITHUB_OUTPUT - echo "pr_title=$(echo "$PR_JSON" | jq -r .title)" >> $GITHUB_OUTPUT - echo "run-url=https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" >> $GITHUB_OUTPUT - - - name: Append comment with job run link - # If comment-id is not provided, this will create a new - # comment with the job run link. - id: first-comment-action - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 - with: - comment-id: ${{ github.event.inputs.comment-id }} - issue-number: ${{ github.event.inputs.pr }} - body: | - > Connector CAT tests started... [Check job output.](${{ steps.job-vars.outputs.run-url }}) - > - > If the connector supports live tests or regression tests, you may want to run those now also: - > - [Run Live Tests](https://github.com/airbytehq/airbyte/actions/workflows/live_tests.yml) - > - [Run Regression Tests](https://github.com/airbytehq/airbyte/actions/workflows/regression_tests.yml) - > - - - name: Checkout Airbyte - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - with: - repository: ${{ steps.job-vars.outputs.repo }} - ref: ${{ steps.job-vars.outputs.branch }} - fetch-depth: 0 - - # NOTE: We still use a PAT here (rather than a GitHub App) because the workflow needs - # permissions to add commits to our main repo as well as forks. This will only work on - # forks if the user installs the app into their fork. Until we document this as a clear - # path, we will have to keep using the PAT. - - name: Run CAT tests with `airbyte-ci` - if: github.event_name == 'workflow_dispatch' - uses: ./.github/actions/run-airbyte-ci - with: - context: "pull_request" - dagger_cloud_token: ${{ secrets.DAGGER_CLOUD_TOKEN_CACHE_3 }} - docker_hub_password: ${{ secrets.DOCKER_HUB_PASSWORD }} - docker_hub_username: ${{ secrets.DOCKER_HUB_USERNAME }} - gcp_gsm_credentials: ${{ secrets.GCP_GSM_CREDENTIALS }} - gcp_integration_tester_credentials: ${{ secrets.GCLOUD_INTEGRATION_TESTER }} - sentry_dsn: ${{ secrets.SENTRY_AIRBYTE_CI_DSN }} - github_token: ${{ secrets.GH_PAT_APPROVINGTON_OCTAVIA }} - s3_build_cache_access_key_id: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} - s3_build_cache_secret_key: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} - git_branch: ${{ steps.job-vars.outputs.branch }} - git_revision: ${{ steps.job-vars.outputs.commit_id }} - subcommand: "connectors --modified test --only-step=acceptance" - - - name: Append completion comment - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 - if: always() - with: - comment-id: ${{ steps.first-comment-action.outputs.comment-id }} - reactions: confused - body: | - > CAT Tests completed. - > _**Important: Please check the job output to verify the results.**_ diff --git a/.github/workflows/run-live-tests-command.yml b/.github/workflows/run-live-tests-command.yml deleted file mode 100644 index 1cd701c93bc0..000000000000 --- a/.github/workflows/run-live-tests-command.yml +++ /dev/null @@ -1,177 +0,0 @@ -name: On-Demand Live Connector Validation Tests - -concurrency: - # This is the name of the concurrency group. It is used to prevent concurrent runs of the same workflow. - # - # - github.head_ref is only defined on PR runs, it makes sure that the concurrency group is unique for pull requests - # ensuring that only one run per pull request is active at a time. - # - # - github.run_id is defined on all runs, it makes sure that the concurrency group is unique for workflow dispatches. - # This allows us to run multiple workflow dispatches in parallel. - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -on: - workflow_dispatch: - inputs: - # Global static-arg inputs for slash commands - repo: - description: "The repository name. Optional. Defaults to 'airbytehq/airbyte'." - required: false - default: "airbytehq/airbyte" - type: string - gitref: - description: "The git reference (branch or tag). Optional. Defaults to the default branch." - required: false - type: string - comment-id: - description: "The ID of the comment triggering the workflow. Optional." - required: false - type: number - pr: - description: "The pull request number, if applicable. Optional." - required: false - type: number - - # Workflow-specific inputs - connector_filter: - description: > - Connector filter. Will be passed to the `airbyte-ci connectors` command. - To select all modified connectors, use '--modified'. To select specific connectors, - pass one or or more `--name` args, e.g. '--name=source-faker --name=source-hardcoded-records'. - default: "--modified" - connection_id: - description: > - Connection ID. ID of the connection to test; use "auto" to let the - connection retriever choose a connection. - default: "auto" - streams: - description: > - (Optional) Streams. Which streams to include in tests. - If not set, these will be chosen automatically. - required: false - default: "" - type: string - should_read_with_state: - description: Whether to run tests against the read command with state - default: "true" - type: boolean - use_local_cdk: - description: Use the local CDK when building the target connector - default: "false" - type: boolean - disable_proxy: - description: Disable proxy for requests - default: "false" - type: boolean - - # Workaround: GitHub currently supports a max of 10 inputs for workflow_dispatch events. - # We need to consolidate some inputs to stay within this limit. - # connection_subset: - # description: The subset of connections to select from. - # default: "sandboxes" - # type: choice - # options: - # - sandboxes - # - all - -jobs: - live_tests: - name: Live Tests - runs-on: linux-24.04-large # Custom runner, defined in GitHub org settings - timeout-minutes: 360 # 6 hours - steps: - - name: Checkout Airbyte - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - - name: Extract branch name [WORKFLOW DISPATCH] - shell: bash - if: github.event_name == 'workflow_dispatch' - run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT - id: extract_branch - - - name: Install Poetry - id: install_poetry - uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1.4.1 - with: - version: 1.8.5 - - - name: Make poetry venv in project - id: poetry_venv - run: poetry config virtualenvs.in-project true - - - name: Install Python packages - id: install_python_packages - working-directory: airbyte-ci/connectors/pipelines - run: poetry install - - - name: Fetch last commit id from remote branch [WORKFLOW DISPATCH] - if: github.event_name == 'workflow_dispatch' - id: fetch_last_commit_id_wd - run: echo "commit_id=$(git rev-parse origin/${{ steps.extract_branch.outputs.branch }})" >> $GITHUB_OUTPUT - - - name: Setup Stream Parameters - if: github.event_name == 'workflow_dispatch' - run: | - if [ -z "${{ github.event.inputs.streams }}" ]; then - echo "STREAM_PARAMS=" >> $GITHUB_ENV - else - STREAMS=$(echo "${{ github.event.inputs.streams }}" | sed 's/,/ --connector_live_tests.selected-streams=/g') - echo "STREAM_PARAMS=--connector_live_tests.selected-streams=$STREAMS" >> $GITHUB_ENV - fi - - - name: Setup Local CDK Flag - if: github.event_name == 'workflow_dispatch' - run: | - if ${{ github.event.inputs.use_local_cdk }}; then - echo "USE_LOCAL_CDK_FLAG=--use-local-cdk" >> $GITHUB_ENV - else - echo "USE_LOCAL_CDK_FLAG=" >> $GITHUB_ENV - fi - - - name: Setup State Flag - if: github.event_name == 'workflow_dispatch' - run: | - if ${{ github.event.inputs.should_read_with_state }}; then - echo "READ_WITH_STATE_FLAG=--connector_live_tests.should-read-with-state" >> $GITHUB_ENV - else - echo "READ_WITH_STATE_FLAG=" >> $GITHUB_ENV - fi - - - name: Setup Proxy Flag - if: github.event_name == 'workflow_dispatch' - run: | - if ${{ github.event.inputs.disable_proxy }}; then - echo "DISABLE_PROXY_FLAG=--connector_live_tests.disable-proxy" >> $GITHUB_ENV - else - echo "DISABLE_PROXY_FLAG=" >> $GITHUB_ENV - fi - - - name: Setup Connection Subset Option - if: github.event_name == 'workflow_dispatch' - run: | - echo "CONNECTION_SUBSET=--connector_live_tests.connection-subset=sandboxes" >> $GITHUB_ENV - # TODO: re-enable when we have resolved the more-than-10-inputs issue in workflow_dispatch. - # run: | - # echo "CONNECTION_SUBSET=--connector_live_tests.connection-subset=${{ github.event.inputs.connection_subset }}" >> $GITHUB_ENV - - # NOTE: We still use a PAT here (rather than a GitHub App) because the workflow needs - # permissions to add commits to our main repo as well as forks. This will only work on - # forks if the user installs the app into their fork. Until we document this as a clear - # path, we will have to keep using the PAT. - - name: Run Live Tests [WORKFLOW DISPATCH] - if: github.event_name == 'workflow_dispatch' # TODO: consider using the matrix strategy (https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs). See https://github.com/airbytehq/airbyte/pull/37659#discussion_r1583380234 for details. - uses: ./.github/actions/run-airbyte-ci - with: - context: "manual" - dagger_cloud_token: ${{ secrets.DAGGER_CLOUD_TOKEN_CACHE_3 }} - docker_hub_password: ${{ secrets.DOCKER_HUB_PASSWORD }} - docker_hub_username: ${{ secrets.DOCKER_HUB_USERNAME }} - gcp_gsm_credentials: ${{ secrets.GCP_GSM_CREDENTIALS }} - gcp_integration_tester_credentials: ${{ secrets.GCLOUD_INTEGRATION_TESTER }} - sentry_dsn: ${{ secrets.SENTRY_AIRBYTE_CI_DSN }} - git_branch: ${{ steps.extract_branch.outputs.branch }} - git_revision: ${{ steps.fetch_last_commit_id_pr.outputs.commit_id }} - github_token: ${{ secrets.GH_PAT_MAINTENANCE_OSS }} - s3_build_cache_access_key_id: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} - s3_build_cache_secret_key: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} - subcommand: connectors ${{ env.USE_LOCAL_CDK_FLAG }} ${{ inputs.connector_filter }} test --only-step connector_live_tests --connector_live_tests.test-suite=live --connector_live_tests.connection-id=${{ github.event.inputs.connection_id }} --connector_live_tests.pr-url="https://github.com/airbytehq/airbyte/pull/${{ github.event.inputs.pr }}" ${{ env.READ_WITH_STATE_FLAG }} ${{ env.DISABLE_PROXY_FLAG }} ${{ env.STREAM_PARAMS }} ${{ env.CONNECTION_SUBSET }} diff --git a/.github/workflows/run-regression-tests-command.yml b/.github/workflows/run-regression-tests-command.yml deleted file mode 100644 index 78dd5e0a74f0..000000000000 --- a/.github/workflows/run-regression-tests-command.yml +++ /dev/null @@ -1,315 +0,0 @@ -name: On-Demand Connector Regression Tests - -concurrency: - # This is the name of the concurrency group. It is used to prevent concurrent runs of the same workflow. - # - # - github.head_ref is only defined on PR runs, it makes sure that the concurrency group is unique for pull requests - # ensuring that only one run per pull request is active at a time. - # - # - github.run_id is defined on all runs, it makes sure that the concurrency group is unique for workflow dispatches. - # This allows us to run multiple workflow dispatches in parallel. - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -on: - workflow_dispatch: - inputs: - # Global static-arg inputs for slash commands - repo: - description: "The repository name" - required: false - default: "airbytehq/airbyte" - type: string - gitref: - description: "The git reference (branch or tag)" - required: false - type: string - comment-id: - description: "The ID of the comment triggering the workflow" - required: false - type: number - pr: - description: "The pull request number, if applicable" - required: false - type: number - - # Workflow-specific inputs - connector_filter: - description: > - Connector filter. Will be passed to the `airbyte-ci connectors` command. - To select all modified connectors, use '--modified'. To select specific connectors, - pass one or or more `--name` args, e.g. '--name=source-faker --name=source-hardcoded-records'. - default: "--modified" - connection_id: - description: > - Connection ID. ID of the connection to test; use "auto" to let the - connection retriever choose a connection. - default: "auto" - streams: - description: > - (Optional) Streams. Which streams to include in tests. - If not set, these will be chosen automatically. - required: false - default: "" - type: string - should_read_with_state: - description: Whether to run tests against the read command with state - default: "true" - type: boolean - use_local_cdk: - description: Use the local CDK when building the target connector - default: "false" - type: boolean - disable_proxy: - description: Disable proxy for requests - default: "false" - type: boolean - - # Workaround: GitHub currently supports a max of 10 inputs for workflow_dispatch events. - # We need to consolidate some inputs to stay within this limit. - # connection_subset: - # description: The subset of connections to select from. - # default: "sandboxes" - # type: choice - # options: - # - sandboxes - # - all - # control_version: - # description: The version to use as a control version. This is useful when the version defined in the cloud registry does not have a lot of usage (either because a progressive rollout is underway or because a new version has just been released). - # required: false - # type: string - -jobs: - regression_tests: - name: Regression Tests - runs-on: linux-24.04-large # Custom runner, defined in GitHub org settings - timeout-minutes: 360 # 6 hours - permissions: - contents: read - pull-requests: write - issues: write - steps: - - name: Append start with run link - id: pr-comment-id - if: github.event_name == 'workflow_dispatch' && github.event.inputs.pr != '' - uses: peter-evans/create-or-update-comment@v4 - with: - token: ${{ github.token }} - issue-number: ${{ github.event.inputs.pr }} - comment-id: ${{ github.event.inputs.comment-id }} - edit-mode: append - body: | - > Starting regression tests (filter: `${{ github.event.inputs.connector_filter || '--modified' }}`) - > Workflow run: [${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) - - - name: Install Python - id: install_python - uses: actions/setup-python@7f4fc3e22c37d6ff65e88745f38bd3157c663f7c # v4.9.1 - with: - python-version: "3.11" - check-latest: true - update-environment: true - - - name: Checkout Airbyte - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - - name: Extract branch name [WORKFLOW DISPATCH] - shell: bash - if: github.event_name == 'workflow_dispatch' - run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT - id: extract_branch - - - name: Install Poetry - id: install_poetry - uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1.4.1 - with: - version: 1.8.5 - - - name: Make poetry venv in project - id: poetry_venv - run: poetry config virtualenvs.in-project true - - - name: Install Python packages - id: install_python_packages - working-directory: airbyte-ci/connectors/pipelines - run: poetry install - - - name: Fetch last commit id from remote branch [WORKFLOW DISPATCH] - if: github.event_name == 'workflow_dispatch' - id: fetch_last_commit_id_wd - run: echo "commit_id=$(git rev-parse origin/${{ steps.extract_branch.outputs.branch }})" >> $GITHUB_OUTPUT - - - name: Setup Stream Parameters - if: github.event_name == 'workflow_dispatch' - run: | - if [ -z "${{ github.event.inputs.streams }}" ]; then - echo "STREAM_PARAMS=" >> $GITHUB_ENV - else - STREAMS=$(echo "${{ github.event.inputs.streams }}" | sed 's/,/ --connector_live_tests.selected-streams=/g') - echo "STREAM_PARAMS=--connector_live_tests.selected-streams=$STREAMS" >> $GITHUB_ENV - fi - - - name: Setup Local CDK Flag - if: github.event_name == 'workflow_dispatch' - run: | - if ${{ github.event.inputs.use_local_cdk }}; then - echo "USE_LOCAL_CDK_FLAG=--use-local-cdk" >> $GITHUB_ENV - else - echo "USE_LOCAL_CDK_FLAG=" >> $GITHUB_ENV - fi - - - name: Setup State Flag - if: github.event_name == 'workflow_dispatch' - run: | - if ${{ github.event.inputs.should_read_with_state }}; then - echo "READ_WITH_STATE_FLAG=--connector_live_tests.should-read-with-state" >> $GITHUB_ENV - else - echo "READ_WITH_STATE_FLAG=" >> $GITHUB_ENV - fi - - - name: Setup Proxy Flag - if: github.event_name == 'workflow_dispatch' - run: | - if ${{ github.event.inputs.disable_proxy }}; then - echo "DISABLE_PROXY_FLAG=--connector_live_tests.disable-proxy" >> $GITHUB_ENV - else - echo "DISABLE_PROXY_FLAG=" >> $GITHUB_ENV - fi - - - name: Setup Connection Subset Option - if: github.event_name == 'workflow_dispatch' - run: | - echo "CONNECTION_SUBSET=--connector_live_tests.connection-subset=sandboxes" >> $GITHUB_ENV - # TODO: re-enable when we have resolved the more-than-10-inputs issue in workflow_dispatch. - # run: | - # echo "CONNECTION_SUBSET=--connector_live_tests.connection-subset=${{ github.event.inputs.connection_subset }}" >> $GITHUB_ENV - - - name: Setup Control Version - if: github.event_name == 'workflow_dispatch' - run: | - echo "CONTROL_VERSION=" >> $GITHUB_ENV - # TODO: re-enable when we have resolved the more-than-10-inputs issue in workflow_dispatch. - # run: | - # if [ -n "${{ github.event.inputs.control_version }}" ]; then - # echo "CONTROL_VERSION=--connector_live_tests.control-version=${{ github.event.inputs.control_version }}" >> $GITHUB_ENV - # else - # echo "CONTROL_VERSION=" >> $GITHUB_ENV - # fi - - # NOTE: We still use a PAT here (rather than a GitHub App) because the workflow needs - # permissions to add commits to our main repo as well as forks. This will only work on - # forks if the user installs the app into their fork. Until we document this as a clear - # path, we will have to keep using the PAT. - - name: Run Regression Tests [WORKFLOW DISPATCH] - id: run-regression-tests - if: github.event_name == 'workflow_dispatch' # TODO: consider using the matrix strategy (https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs). See https://github.com/airbytehq/airbyte/pull/37659#discussion_r1583380234 for details. - uses: ./.github/actions/run-airbyte-ci - with: - context: "manual" - dagger_cloud_token: ${{ secrets.DAGGER_CLOUD_TOKEN_CACHE_3 }} - docker_hub_password: ${{ secrets.DOCKER_HUB_PASSWORD }} - docker_hub_username: ${{ secrets.DOCKER_HUB_USERNAME }} - gcp_gsm_credentials: ${{ secrets.GCP_GSM_CREDENTIALS }} - gcp_integration_tester_credentials: ${{ secrets.GCLOUD_INTEGRATION_TESTER }} - sentry_dsn: ${{ secrets.SENTRY_AIRBYTE_CI_DSN }} - git_branch: ${{ steps.extract_branch.outputs.branch }} - git_revision: ${{ steps.fetch_last_commit_id_pr.outputs.commit_id }} - github_token: ${{ secrets.GH_PAT_MAINTENANCE_OSS }} - s3_build_cache_access_key_id: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} - s3_build_cache_secret_key: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} - subcommand: connectors ${{ env.USE_LOCAL_CDK_FLAG }} ${{ inputs.connector_filter }} test --only-step connector_live_tests --connector_live_tests.test-suite=regression --connector_live_tests.connection-id=${{ github.event.inputs.connection_id }} --connector_live_tests.pr-url="https://github.com/airbytehq/airbyte/pull/${{ github.event.inputs.pr }}" ${{ env.READ_WITH_STATE_FLAG }} ${{ env.DISABLE_PROXY_FLAG }} ${{ env.STREAM_PARAMS }} ${{ env.CONNECTION_SUBSET }} ${{ env.CONTROL_VERSION }} --global-status-check-context="Regression Tests" --global-status-check-description='Running regression tests' - - - name: Locate regression test report - if: always() && github.event_name == 'workflow_dispatch' - id: locate-report - run: | - # Find the most recent report.html file in /tmp/live_tests_artifacts/ - REPORT_PATH=$(find /tmp/live_tests_artifacts -name "report.html" -type f -printf '%T@ %p\n' 2>/dev/null | sort -n | tail -1 | cut -f2- -d" ") - if [ -n "$REPORT_PATH" ]; then - echo "report_path=$REPORT_PATH" >> "$GITHUB_OUTPUT" - echo "Found report at: $REPORT_PATH" - else - echo "report_path=" >> "$GITHUB_OUTPUT" - echo "No report.html found in /tmp/live_tests_artifacts/" - fi - - - name: Upload regression test report - if: always() && github.event_name == 'workflow_dispatch' && steps.locate-report.outputs.report_path != '' - uses: actions/upload-artifact@v4 - with: - name: regression-test-report - path: ${{ steps.locate-report.outputs.report_path }} - if-no-files-found: ignore - - - name: Append regression outcome - if: always() && github.event_name == 'workflow_dispatch' && github.event.inputs.pr != '' - uses: peter-evans/create-or-update-comment@v4 - with: - token: ${{ github.token }} - comment-id: ${{ steps.pr-comment-id.outputs.comment-id }} - edit-mode: append - body: | - > Regression tests: ${{ steps.run-regression-tests.outcome == 'success' && '✅ PASSED' || steps.run-regression-tests.outcome == 'failure' && '❌ FAILED' || steps.run-regression-tests.outcome == 'cancelled' && '⚠️ CANCELLED' || steps.run-regression-tests.outcome == 'skipped' && '⏭️ SKIPPED' || '❓ UNKNOWN' }} - > Report: ${{ steps.locate-report.outputs.report_path != '' && 'artifact `regression-test-report` available in the run' || 'not generated' }} - - - name: Install live-tests dependencies for LLM evaluation - if: always() && github.event_name == 'workflow_dispatch' - working-directory: airbyte-ci/connectors/live-tests - run: poetry install - - - name: Install and Start Ollama - if: always() && github.event_name == 'workflow_dispatch' - run: | - curl -fsSL https://ollama.com/install.sh | sh - ollama serve & - sleep 5 - ollama pull llama3.2:3b - echo "Ollama server started and model pulled" - - - name: Evaluate Regression Test Report with LLM - if: always() && github.event_name == 'workflow_dispatch' && steps.locate-report.outputs.report_path != '' - id: llm-eval - continue-on-error: true - working-directory: airbyte-ci/connectors/live-tests - env: - OPENAI_API_KEY: ollama - OPENAI_BASE_URL: http://127.0.0.1:11434/v1 - EVAL_MODEL: llama3.2:3b - run: | - set -u - echo "ran=false" >> "$GITHUB_OUTPUT" - echo "result=error" >> "$GITHUB_OUTPUT" - - REPORT_PATH="${{ steps.locate-report.outputs.report_path }}" - - if [ -z "$REPORT_PATH" ]; then - echo "Error: No report path provided from locate-report step" >&2 - echo "## ⚠️ LLM Evaluation Skipped" >> "$GITHUB_STEP_SUMMARY" - echo "No regression test report found. The tests may have failed to generate a report." >> "$GITHUB_STEP_SUMMARY" - exit 1 - fi - - echo "Evaluating report at: $REPORT_PATH" - - # Run the evaluation script - OUT_JSON="$RUNNER_TEMP/llm_eval.json" - poetry run python src/live_tests/regression_tests/llm_evaluation/evaluate_report.py \ - --report-path "$REPORT_PATH" \ - --output-json "$OUT_JSON" - - # If we got here, script exit 0 and produced a judgment - PASS=$(jq -r '.evaluation.pass' "$OUT_JSON") - if [ "$PASS" = "true" ]; then RES="pass"; else RES="fail"; fi - echo "ran=true" >> "$GITHUB_OUTPUT" - echo "result=$RES" >> "$GITHUB_OUTPUT" - - - name: Append LLM outcome - if: always() && github.event_name == 'workflow_dispatch' && github.event.inputs.pr != '' - env: - EVAL_MODEL: llama3.2:3b - uses: peter-evans/create-or-update-comment@v4 - with: - token: ${{ github.token }} - comment-id: ${{ steps.pr-comment-id.outputs.comment-id }} - edit-mode: append - body: | - > LLM Evaluation: ${{ steps.llm-eval.outputs.ran == 'true' && (steps.llm-eval.outputs.result == 'pass' && '✅ PASS' || steps.llm-eval.outputs.result == 'fail' && '❌ FAIL' || '⚠️ ERROR') || '⚠️ Did not run' }}${{ steps.llm-eval.outputs.ran == 'true' && format(' (model: {0})', env.EVAL_MODEL) || '' }} From 9607e2d2cd112457ab8a14bffa362d42603d7155 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Fri, 27 Mar 2026 19:22:49 -0700 Subject: [PATCH 025/379] chore: rename BEHAVIOR.md to CONTRIBUTING.md, consolidate CLAUDE.md (#75555) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../connectors/source-airtable/CLAUDE.md | 5 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-amazon-ads/CLAUDE.md | 6 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../source-amazon-seller-partner/CLAUDE.md | 10 ------- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-amplitude/CLAUDE.md | 6 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-bing-ads/CLAUDE.md | 6 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-chargebee/CLAUDE.md | 5 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-gitlab/CLAUDE.md | 5 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../CLAUDE.md | 13 -------- .../{BEHAVIOR.md => CONTRIBUTING.md} | 4 +++ .../source-google-search-console/CLAUDE.md | 11 ------- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-google-sheets/CLAUDE.md | 6 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-harvest/CLAUDE.md | 10 ------- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-hubspot/CLAUDE.md | 28 ----------------- .../{BEHAVIOR.md => CONTRIBUTING.md} | 30 +++++++++++++++++++ .../connectors/source-instagram/CLAUDE.md | 6 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-intercom/CLAUDE.md | 6 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-jira/CLAUDE.md | 5 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-klaviyo/CLAUDE.md | 7 ----- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-linkedin-ads/CLAUDE.md | 13 -------- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-mailchimp/CLAUDE.md | 5 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-monday/CLAUDE.md | 7 ----- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-notion/CLAUDE.md | 5 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-pinterest/CLAUDE.md | 5 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-sendgrid/CLAUDE.md | 5 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-slack/CLAUDE.md | 6 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-stripe/CLAUDE.md | 9 ------ .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../source-tiktok-marketing/CLAUDE.md | 14 --------- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-typeform/CLAUDE.md | 5 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../source-zendesk-support/CLAUDE.md | 7 ----- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 .../connectors/source-zendesk-talk/CLAUDE.md | 5 ---- .../{BEHAVIOR.md => CONTRIBUTING.md} | 0 56 files changed, 34 insertions(+), 221 deletions(-) delete mode 100644 airbyte-integrations/connectors/source-airtable/CLAUDE.md rename airbyte-integrations/connectors/source-airtable/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-amazon-ads/CLAUDE.md rename airbyte-integrations/connectors/source-amazon-ads/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-amazon-seller-partner/CLAUDE.md rename airbyte-integrations/connectors/source-amazon-seller-partner/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-amplitude/CLAUDE.md rename airbyte-integrations/connectors/source-amplitude/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-bing-ads/CLAUDE.md rename airbyte-integrations/connectors/source-bing-ads/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-chargebee/CLAUDE.md rename airbyte-integrations/connectors/source-chargebee/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-gitlab/CLAUDE.md rename airbyte-integrations/connectors/source-gitlab/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-google-analytics-data-api/CLAUDE.md rename airbyte-integrations/connectors/source-google-analytics-data-api/{BEHAVIOR.md => CONTRIBUTING.md} (97%) delete mode 100644 airbyte-integrations/connectors/source-google-search-console/CLAUDE.md rename airbyte-integrations/connectors/source-google-search-console/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-google-sheets/CLAUDE.md rename airbyte-integrations/connectors/source-google-sheets/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-harvest/CLAUDE.md rename airbyte-integrations/connectors/source-harvest/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-hubspot/CLAUDE.md rename airbyte-integrations/connectors/source-hubspot/{BEHAVIOR.md => CONTRIBUTING.md} (89%) delete mode 100644 airbyte-integrations/connectors/source-instagram/CLAUDE.md rename airbyte-integrations/connectors/source-instagram/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-intercom/CLAUDE.md rename airbyte-integrations/connectors/source-intercom/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-jira/CLAUDE.md rename airbyte-integrations/connectors/source-jira/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-klaviyo/CLAUDE.md rename airbyte-integrations/connectors/source-klaviyo/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-linkedin-ads/CLAUDE.md rename airbyte-integrations/connectors/source-linkedin-ads/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-mailchimp/CLAUDE.md rename airbyte-integrations/connectors/source-mailchimp/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-monday/CLAUDE.md rename airbyte-integrations/connectors/source-monday/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-notion/CLAUDE.md rename airbyte-integrations/connectors/source-notion/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-pinterest/CLAUDE.md rename airbyte-integrations/connectors/source-pinterest/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-sendgrid/CLAUDE.md rename airbyte-integrations/connectors/source-sendgrid/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-slack/CLAUDE.md rename airbyte-integrations/connectors/source-slack/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-stripe/CLAUDE.md rename airbyte-integrations/connectors/source-stripe/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-tiktok-marketing/CLAUDE.md rename airbyte-integrations/connectors/source-tiktok-marketing/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-typeform/CLAUDE.md rename airbyte-integrations/connectors/source-typeform/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-zendesk-support/CLAUDE.md rename airbyte-integrations/connectors/source-zendesk-support/{BEHAVIOR.md => CONTRIBUTING.md} (100%) delete mode 100644 airbyte-integrations/connectors/source-zendesk-talk/CLAUDE.md rename airbyte-integrations/connectors/source-zendesk-talk/{BEHAVIOR.md => CONTRIBUTING.md} (100%) diff --git a/airbyte-integrations/connectors/source-airtable/CLAUDE.md b/airbyte-integrations/connectors/source-airtable/CLAUDE.md deleted file mode 100644 index 7e7fa6998b03..000000000000 --- a/airbyte-integrations/connectors/source-airtable/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -# source-airtable - -## Unique Behaviors -See [BEHAVIOR.md](./BEHAVIOR.md) for documented unique behaviors: -1. Single-use rotating refresh tokens diff --git a/airbyte-integrations/connectors/source-airtable/BEHAVIOR.md b/airbyte-integrations/connectors/source-airtable/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-airtable/BEHAVIOR.md rename to airbyte-integrations/connectors/source-airtable/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-amazon-ads/CLAUDE.md b/airbyte-integrations/connectors/source-amazon-ads/CLAUDE.md deleted file mode 100644 index 9dcbbe9fc52d..000000000000 --- a/airbyte-integrations/connectors/source-amazon-ads/CLAUDE.md +++ /dev/null @@ -1,6 +0,0 @@ -# source-amazon-ads - -## Key Documentation -- See `BEHAVIOR.md` for unique connector behaviors including: - 1. Async report generation with three-phase create/poll/download workflow - 2. HTTP 425 (Too Early) for duplicate concurrent report requests diff --git a/airbyte-integrations/connectors/source-amazon-ads/BEHAVIOR.md b/airbyte-integrations/connectors/source-amazon-ads/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-amazon-ads/BEHAVIOR.md rename to airbyte-integrations/connectors/source-amazon-ads/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-amazon-seller-partner/CLAUDE.md b/airbyte-integrations/connectors/source-amazon-seller-partner/CLAUDE.md deleted file mode 100644 index 074668a88d84..000000000000 --- a/airbyte-integrations/connectors/source-amazon-seller-partner/CLAUDE.md +++ /dev/null @@ -1,10 +0,0 @@ -# source-amazon-seller-partner - -## Key Documentation -- See `BEHAVIOR.md` for unique connector behaviors including: - 1. Gzip-compressed report responses in CSV, XML, or JSON formats - 2. Reactive token invalidation on 403 errors via global module reference - 3. Reciprocal Retry-After header interpretation for backoff timing - 4. Regression tests will not run locally — must test via Cloud dev image + progressive rollout - 5. Standard tests fail for vendor forecasting streams (sandbox permission issue since v4.4.7) - 6. Known stream failures in testing — permission errors, timeouts, job failures, invalid input (see tables in BEHAVIOR.md) diff --git a/airbyte-integrations/connectors/source-amazon-seller-partner/BEHAVIOR.md b/airbyte-integrations/connectors/source-amazon-seller-partner/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-amazon-seller-partner/BEHAVIOR.md rename to airbyte-integrations/connectors/source-amazon-seller-partner/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-amplitude/CLAUDE.md b/airbyte-integrations/connectors/source-amplitude/CLAUDE.md deleted file mode 100644 index bbc71553eff0..000000000000 --- a/airbyte-integrations/connectors/source-amplitude/CLAUDE.md +++ /dev/null @@ -1,6 +0,0 @@ -# source-amplitude - -## Unique Behaviors -See [BEHAVIOR.md](./BEHAVIOR.md) for documented unique behaviors: -1. Matrix-style API response extraction (xValues/series zipping) -2. Hard 4GB export size limit with timeout fallback diff --git a/airbyte-integrations/connectors/source-amplitude/BEHAVIOR.md b/airbyte-integrations/connectors/source-amplitude/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-amplitude/BEHAVIOR.md rename to airbyte-integrations/connectors/source-amplitude/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-bing-ads/CLAUDE.md b/airbyte-integrations/connectors/source-bing-ads/CLAUDE.md deleted file mode 100644 index df330582e86e..000000000000 --- a/airbyte-integrations/connectors/source-bing-ads/CLAUDE.md +++ /dev/null @@ -1,6 +0,0 @@ -# source-bing-ads - -## Key Documentation -- See `BEHAVIOR.md` for unique connector behaviors including: - 1. Duplicate records from predicate-based account filtering - 2. Bulk report downloads that may arrive uncompressed despite gzip expectation diff --git a/airbyte-integrations/connectors/source-bing-ads/BEHAVIOR.md b/airbyte-integrations/connectors/source-bing-ads/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-bing-ads/BEHAVIOR.md rename to airbyte-integrations/connectors/source-bing-ads/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-chargebee/CLAUDE.md b/airbyte-integrations/connectors/source-chargebee/CLAUDE.md deleted file mode 100644 index 297963e037df..000000000000 --- a/airbyte-integrations/connectors/source-chargebee/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -# source-chargebee - -## Unique Behaviors -See [BEHAVIOR.md](./BEHAVIOR.md) for documented unique behaviors: -1. Product Catalog version-gated streams (silently ignored via `configuration_incompatible`) diff --git a/airbyte-integrations/connectors/source-chargebee/BEHAVIOR.md b/airbyte-integrations/connectors/source-chargebee/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-chargebee/BEHAVIOR.md rename to airbyte-integrations/connectors/source-chargebee/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-gitlab/CLAUDE.md b/airbyte-integrations/connectors/source-gitlab/CLAUDE.md deleted file mode 100644 index ce77d13e64f6..000000000000 --- a/airbyte-integrations/connectors/source-gitlab/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -# source-gitlab - -## Unique Behaviors -See [BEHAVIOR.md](./BEHAVIOR.md) for documented unique behaviors: -1. Single-use rotating refresh tokens diff --git a/airbyte-integrations/connectors/source-gitlab/BEHAVIOR.md b/airbyte-integrations/connectors/source-gitlab/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-gitlab/BEHAVIOR.md rename to airbyte-integrations/connectors/source-gitlab/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-google-analytics-data-api/CLAUDE.md b/airbyte-integrations/connectors/source-google-analytics-data-api/CLAUDE.md deleted file mode 100644 index bdb3c239eb4b..000000000000 --- a/airbyte-integrations/connectors/source-google-analytics-data-api/CLAUDE.md +++ /dev/null @@ -1,13 +0,0 @@ -# source-google-analytics-data-api - -## Important -This is **Google Analytics 4 (GA4)** (`source-google-analytics-data-api`), NOT the deprecated Universal Analytics (`source-google-analytics-v4`). All work goes here. - -## Unique Behaviors -See [BEHAVIOR.md](./BEHAVIOR.md) for documented unique behaviors: -1. Positional key-value array extraction (headers and values returned separately) -2. Two-level Jinja interpolation in component mappings (`{% raw %}` for runtime vs template-level) -3. Fully dynamic stream construction from config (12+ ComponentMappingDefinitions, no static streams) -4. DimensionFilter config transformation (config schema differs from API request schema) -5. Cohort reports disable date ranges and incremental sync -6. Rate limit quota cannot be self-service increased — requires DoIT escalation (via Ralph or Davin) diff --git a/airbyte-integrations/connectors/source-google-analytics-data-api/BEHAVIOR.md b/airbyte-integrations/connectors/source-google-analytics-data-api/CONTRIBUTING.md similarity index 97% rename from airbyte-integrations/connectors/source-google-analytics-data-api/BEHAVIOR.md rename to airbyte-integrations/connectors/source-google-analytics-data-api/CONTRIBUTING.md index 698362900834..f028b0b882d3 100644 --- a/airbyte-integrations/connectors/source-google-analytics-data-api/BEHAVIOR.md +++ b/airbyte-integrations/connectors/source-google-analytics-data-api/CONTRIBUTING.md @@ -1,5 +1,9 @@ # source-google-analytics-data-api: Unique Behaviors +## Important +This is **Google Analytics 4 (GA4)** (`source-google-analytics-data-api`), NOT the deprecated Universal Analytics (`source-google-analytics-v4`). All work goes here. + + ## Important: Naming Convention — GA4 vs Universal Analytics This connector is **Google Analytics 4 (GA4)** with package name `source-google-analytics-data-api`. It is very commonly confused with the legacy connector **Google Analytics (Universal Analytics)** with package name `source-google-analytics-v4`. diff --git a/airbyte-integrations/connectors/source-google-search-console/CLAUDE.md b/airbyte-integrations/connectors/source-google-search-console/CLAUDE.md deleted file mode 100644 index aee2d29a1989..000000000000 --- a/airbyte-integrations/connectors/source-google-search-console/CLAUDE.md +++ /dev/null @@ -1,11 +0,0 @@ -# source-google-search-console - -Google Search Console API source connector built on the declarative framework with custom Python -components for state migration, dimension extraction, and schema generation. - -## Key Behavior Documentation - -See [BEHAVIOR.md](BEHAVIOR.md) for the most important non-obvious gotchas in this connector, including: -- POST-based Search Analytics with positional keys array that must be mapped to dimension names -- Configurable rate limits where most new projects default far below the connector's limit -- AggregationType override config for customers whose properties reject certain aggregation types diff --git a/airbyte-integrations/connectors/source-google-search-console/BEHAVIOR.md b/airbyte-integrations/connectors/source-google-search-console/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-google-search-console/BEHAVIOR.md rename to airbyte-integrations/connectors/source-google-search-console/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-google-sheets/CLAUDE.md b/airbyte-integrations/connectors/source-google-sheets/CLAUDE.md deleted file mode 100644 index f261176668bb..000000000000 --- a/airbyte-integrations/connectors/source-google-sheets/CLAUDE.md +++ /dev/null @@ -1,6 +0,0 @@ -# source-google-sheets - -## Unique Behaviors -See [BEHAVIOR.md](./BEHAVIOR.md) for documented unique behaviors: -1. Schema derived from row 1 with positional value matching and header deduplication -2. Batch row fetching with per-request 180-second timeout constraint diff --git a/airbyte-integrations/connectors/source-google-sheets/BEHAVIOR.md b/airbyte-integrations/connectors/source-google-sheets/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-google-sheets/BEHAVIOR.md rename to airbyte-integrations/connectors/source-google-sheets/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-harvest/CLAUDE.md b/airbyte-integrations/connectors/source-harvest/CLAUDE.md deleted file mode 100644 index 596e18450b7a..000000000000 --- a/airbyte-integrations/connectors/source-harvest/CLAUDE.md +++ /dev/null @@ -1,10 +0,0 @@ -# source-harvest - -Harvest time tracking API source connector built entirely on the declarative framework (no custom Python -components). - -## Key Behavior Documentation - -See [BEHAVIOR.md](BEHAVIOR.md) for the most important non-obvious gotchas in this connector, including: -- Graceful degradation that silently ignores 401/403/404 errors per stream -- Report streams use date-range slicing with a different cursor format than entity streams diff --git a/airbyte-integrations/connectors/source-harvest/BEHAVIOR.md b/airbyte-integrations/connectors/source-harvest/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-harvest/BEHAVIOR.md rename to airbyte-integrations/connectors/source-harvest/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-hubspot/CLAUDE.md b/airbyte-integrations/connectors/source-hubspot/CLAUDE.md deleted file mode 100644 index 1dfe63f9762e..000000000000 --- a/airbyte-integrations/connectors/source-hubspot/CLAUDE.md +++ /dev/null @@ -1,28 +0,0 @@ -# source-hubspot - -## Overview - -HubSpot CRM source connector using the declarative (low-code) framework with extensive custom Python -components in `components.py`. The connector syncs data from HubSpot's CRM, marketing, and engagement -APIs. - -## Key Files - -- `manifest.yaml` -- Declarative stream definitions, authentication, pagination, error handling, and - schemas (~7600 lines). -- `components.py` -- Custom Python components for behaviors that cannot be expressed in YAML alone. -- `BEHAVIOR.md` -- **Read this first.** Documents all non-obvious connector-specific behaviors - including hidden API calls during extraction, dual-endpoint selection, pagination workarounds, and - property chunking. Understanding these behaviors is critical before making changes. - -## Important Patterns - -- CRM search streams make additional association API calls inside the record extractor. See - `BEHAVIOR.md` section 1. -- The engagements stream dynamically selects between two different API endpoints. See `BEHAVIOR.md` - section 2. -- Pagination resets at 10,000 results for search endpoints. See `BEHAVIOR.md` section 3. -- Custom objects use `StateDelegatingStream` with two different sub-stream implementations. See - `BEHAVIOR.md` section 4. -- Many streams use character-based property chunking (15,000 char limit). See `BEHAVIOR.md` section 5. -- Authentication retries on 401 to handle mid-sync token expiration. See `BEHAVIOR.md` section 8. diff --git a/airbyte-integrations/connectors/source-hubspot/BEHAVIOR.md b/airbyte-integrations/connectors/source-hubspot/CONTRIBUTING.md similarity index 89% rename from airbyte-integrations/connectors/source-hubspot/BEHAVIOR.md rename to airbyte-integrations/connectors/source-hubspot/CONTRIBUTING.md index 298b0ffb1e69..a11b324d5435 100644 --- a/airbyte-integrations/connectors/source-hubspot/BEHAVIOR.md +++ b/airbyte-integrations/connectors/source-hubspot/CONTRIBUTING.md @@ -1,5 +1,35 @@ # source-hubspot: Unique Connector Behaviors +## Overview + +HubSpot CRM source connector using the declarative (low-code) framework with extensive custom Python +components in `components.py`. The connector syncs data from HubSpot's CRM, marketing, and engagement +APIs. + + +## Key Files + +- `manifest.yaml` -- Declarative stream definitions, authentication, pagination, error handling, and + schemas (~7600 lines). +- `components.py` -- Custom Python components for behaviors that cannot be expressed in YAML alone. +- `CONTRIBUTING.md` -- **Read this first.** Documents all non-obvious connector-specific behaviors + including hidden API calls during extraction, dual-endpoint selection, pagination workarounds, and + property chunking. Understanding these behaviors is critical before making changes. + + +## Important Patterns + +- CRM search streams make additional association API calls inside the record extractor. See + `CONTRIBUTING.md` section 1. +- The engagements stream dynamically selects between two different API endpoints. See `CONTRIBUTING.md` + section 2. +- Pagination resets at 10,000 results for search endpoints. See `CONTRIBUTING.md` section 3. +- Custom objects use `StateDelegatingStream` with two different sub-stream implementations. See + `CONTRIBUTING.md` section 4. +- Many streams use character-based property chunking (15,000 char limit). See `CONTRIBUTING.md` section 5. +- Authentication retries on 401 to handle mid-sync token expiration. See `CONTRIBUTING.md` section 8. + + This document describes the biggest non-obvious gotchas in `source-hubspot` that deviate from standard declarative connector patterns. Read this before making changes to the connector. diff --git a/airbyte-integrations/connectors/source-instagram/CLAUDE.md b/airbyte-integrations/connectors/source-instagram/CLAUDE.md deleted file mode 100644 index 8f122dbb0ed1..000000000000 --- a/airbyte-integrations/connectors/source-instagram/CLAUDE.md +++ /dev/null @@ -1,6 +0,0 @@ -# source-instagram - -## Key Documentation -- See `BEHAVIOR.md` for unique connector behaviors including: - 1. Hidden per-record API calls for carousel media children during transformation - 2. Access token generation for CAT tests (OAuth flow via Airbyte Cloud + DevTools) diff --git a/airbyte-integrations/connectors/source-instagram/BEHAVIOR.md b/airbyte-integrations/connectors/source-instagram/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-instagram/BEHAVIOR.md rename to airbyte-integrations/connectors/source-instagram/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-intercom/CLAUDE.md b/airbyte-integrations/connectors/source-intercom/CLAUDE.md deleted file mode 100644 index 00627ccf5d2d..000000000000 --- a/airbyte-integrations/connectors/source-intercom/CLAUDE.md +++ /dev/null @@ -1,6 +0,0 @@ -# source-intercom - -## Key Documentation -- See `BEHAVIOR.md` for unique connector behaviors including: - 1. Proactive rate limiting that throttles every request based on remaining capacity headers - 2. Companies Scroll API single active scroll constraint (blocks parallel syncs and substreams) diff --git a/airbyte-integrations/connectors/source-intercom/BEHAVIOR.md b/airbyte-integrations/connectors/source-intercom/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-intercom/BEHAVIOR.md rename to airbyte-integrations/connectors/source-intercom/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-jira/CLAUDE.md b/airbyte-integrations/connectors/source-jira/CLAUDE.md deleted file mode 100644 index cb7a37302cec..000000000000 --- a/airbyte-integrations/connectors/source-jira/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -# source-jira - -## Unique Behaviors -See [BEHAVIOR.md](./BEHAVIOR.md) for documented unique behaviors: -1. Global silent 400 error ignoring across all streams diff --git a/airbyte-integrations/connectors/source-jira/BEHAVIOR.md b/airbyte-integrations/connectors/source-jira/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-jira/BEHAVIOR.md rename to airbyte-integrations/connectors/source-jira/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-klaviyo/CLAUDE.md b/airbyte-integrations/connectors/source-klaviyo/CLAUDE.md deleted file mode 100644 index d5cd932b2c65..000000000000 --- a/airbyte-integrations/connectors/source-klaviyo/CLAUDE.md +++ /dev/null @@ -1,7 +0,0 @@ -# source-klaviyo - -## Key Documentation -- See `BEHAVIOR.md` for unique connector behaviors including: - 1. Hidden per-campaign API calls for recipient count and campaign messages - 2. JSON:API included relationship resolution for inline attribute data - 3. Endpoint-specific rate limit tiers (XS–XL) and per-stream concurrency mapping diff --git a/airbyte-integrations/connectors/source-klaviyo/BEHAVIOR.md b/airbyte-integrations/connectors/source-klaviyo/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-klaviyo/BEHAVIOR.md rename to airbyte-integrations/connectors/source-klaviyo/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-linkedin-ads/CLAUDE.md b/airbyte-integrations/connectors/source-linkedin-ads/CLAUDE.md deleted file mode 100644 index a2b222e6b925..000000000000 --- a/airbyte-integrations/connectors/source-linkedin-ads/CLAUDE.md +++ /dev/null @@ -1,13 +0,0 @@ -# source-linkedin-ads - -LinkedIn Ads API source connector built on the declarative framework with custom Python components. - -## Key Behavior Documentation - -See [BEHAVIOR.md](BEHAVIOR.md) for the most important non-obvious gotchas in this connector, including: -- Safe URL encoding that preserves LinkedIn's proprietary query parameter syntax -- Analytics property chunking with an 18-field limit per request (~5 HTTP calls per record page) -- DNS resolution errors treated as transient/retryable -- Millisecond timestamp handling and multiple datetime formats across endpoints -- Reserved keyword renaming (`pivot` -> `_pivot`) for destination compatibility -- Unpublished per-endpoint rate limits with daily caps diff --git a/airbyte-integrations/connectors/source-linkedin-ads/BEHAVIOR.md b/airbyte-integrations/connectors/source-linkedin-ads/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-linkedin-ads/BEHAVIOR.md rename to airbyte-integrations/connectors/source-linkedin-ads/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-mailchimp/CLAUDE.md b/airbyte-integrations/connectors/source-mailchimp/CLAUDE.md deleted file mode 100644 index ffb8b6f4ffd4..000000000000 --- a/airbyte-integrations/connectors/source-mailchimp/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -# source-mailchimp - -## Key Documentation -- See `BEHAVIOR.md` for unique connector behaviors including: - 1. Dynamic API base URL determined by data center extraction from API key or OAuth metadata diff --git a/airbyte-integrations/connectors/source-mailchimp/BEHAVIOR.md b/airbyte-integrations/connectors/source-mailchimp/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-mailchimp/BEHAVIOR.md rename to airbyte-integrations/connectors/source-mailchimp/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-monday/CLAUDE.md b/airbyte-integrations/connectors/source-monday/CLAUDE.md deleted file mode 100644 index b097f9f0db2c..000000000000 --- a/airbyte-integrations/connectors/source-monday/CLAUDE.md +++ /dev/null @@ -1,7 +0,0 @@ -# source-monday - -## Key Documentation -- See `BEHAVIOR.md` for unique connector behaviors including: - 1. GraphQL API with schema-driven query building and stream-specific query patterns - 2. Two-level nested pagination for items (boards outer, items inner) - 3. Cursor expiration after 60 minutes triggers RESET_PAGINATION (full re-read) diff --git a/airbyte-integrations/connectors/source-monday/BEHAVIOR.md b/airbyte-integrations/connectors/source-monday/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-monday/BEHAVIOR.md rename to airbyte-integrations/connectors/source-monday/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-notion/CLAUDE.md b/airbyte-integrations/connectors/source-notion/CLAUDE.md deleted file mode 100644 index 80bcea88683f..000000000000 --- a/airbyte-integrations/connectors/source-notion/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -# source-notion - -## Key Documentation -- See `BEHAVIOR.md` for unique connector behaviors including: - 1. Recursive block retrieval that depth-first traverses nested blocks up to 30 levels diff --git a/airbyte-integrations/connectors/source-notion/BEHAVIOR.md b/airbyte-integrations/connectors/source-notion/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-notion/BEHAVIOR.md rename to airbyte-integrations/connectors/source-notion/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-pinterest/CLAUDE.md b/airbyte-integrations/connectors/source-pinterest/CLAUDE.md deleted file mode 100644 index 88fd05cc987b..000000000000 --- a/airbyte-integrations/connectors/source-pinterest/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -# source-pinterest - -## Key Documentation -- See `BEHAVIOR.md` for unique connector behaviors including: - 1. Analytics retry wait time parsed from response body message text via regex diff --git a/airbyte-integrations/connectors/source-pinterest/BEHAVIOR.md b/airbyte-integrations/connectors/source-pinterest/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-pinterest/BEHAVIOR.md rename to airbyte-integrations/connectors/source-pinterest/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-sendgrid/CLAUDE.md b/airbyte-integrations/connectors/source-sendgrid/CLAUDE.md deleted file mode 100644 index e9d43da0969e..000000000000 --- a/airbyte-integrations/connectors/source-sendgrid/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -# source-sendgrid - -## Unique Behaviors -See [BEHAVIOR.md](./BEHAVIOR.md) for documented unique behaviors: -1. Async contacts export with gzipped CSV download (three-phase create/poll/download) diff --git a/airbyte-integrations/connectors/source-sendgrid/BEHAVIOR.md b/airbyte-integrations/connectors/source-sendgrid/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-sendgrid/BEHAVIOR.md rename to airbyte-integrations/connectors/source-sendgrid/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-slack/CLAUDE.md b/airbyte-integrations/connectors/source-slack/CLAUDE.md deleted file mode 100644 index 1830044aad06..000000000000 --- a/airbyte-integrations/connectors/source-slack/CLAUDE.md +++ /dev/null @@ -1,6 +0,0 @@ -# source-slack - -## Key Documentation -- See `BEHAVIOR.md` for unique connector behaviors including: - 1. Auto-joining channels during sync via POST side-effect calls - 2. Dynamic rate limit policy that switches from unlimited to 1 req/min on first 429 diff --git a/airbyte-integrations/connectors/source-slack/BEHAVIOR.md b/airbyte-integrations/connectors/source-slack/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-slack/BEHAVIOR.md rename to airbyte-integrations/connectors/source-slack/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-stripe/CLAUDE.md b/airbyte-integrations/connectors/source-stripe/CLAUDE.md deleted file mode 100644 index f2aad9fdaa5d..000000000000 --- a/airbyte-integrations/connectors/source-stripe/CLAUDE.md +++ /dev/null @@ -1,9 +0,0 @@ -# source-stripe - -## Key Documentation -- See `BEHAVIOR.md` for unique connector behaviors including: - 1. Events-based incremental sync via StateDelegatingStream with 30-day retention fallback - 2. Silent 403/400/404 error ignoring that can hide missing data - 3. Inaccessible expandable fields in Events API — incremental syncs cannot reconstruct full object state - 4. Populating sandbox data — only add records, do not modify/delete (breaks CATs) - 5. API version-dependent data discrepancies — event payloads reflect the version the object was created with diff --git a/airbyte-integrations/connectors/source-stripe/BEHAVIOR.md b/airbyte-integrations/connectors/source-stripe/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-stripe/BEHAVIOR.md rename to airbyte-integrations/connectors/source-stripe/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-tiktok-marketing/CLAUDE.md b/airbyte-integrations/connectors/source-tiktok-marketing/CLAUDE.md deleted file mode 100644 index 95c0fc6d0b57..000000000000 --- a/airbyte-integrations/connectors/source-tiktok-marketing/CLAUDE.md +++ /dev/null @@ -1,14 +0,0 @@ -# source-tiktok-marketing - -TikTok Marketing API source connector built on the declarative framework with custom Python components -for advertiser ID partitioning and metric transformation. - -## Key Behavior Documentation - -See [BEHAVIOR.md](BEHAVIOR.md) for the most important non-obvious gotchas in this connector, including: -- Dynamic sandbox vs production endpoint selection based on auth type -- Dual advertiser ID partition routers (single vs batched) for different stream types -- Empty metric values returned as "-" strings that must be transformed to null -- Rate limit detection via response body code (not HTTP 429) -- Smart+ ads filtered out when missing modify_time values -- Sandbox account rate limit (10 RPS) with credential lockout on overuse diff --git a/airbyte-integrations/connectors/source-tiktok-marketing/BEHAVIOR.md b/airbyte-integrations/connectors/source-tiktok-marketing/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-tiktok-marketing/BEHAVIOR.md rename to airbyte-integrations/connectors/source-tiktok-marketing/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-typeform/CLAUDE.md b/airbyte-integrations/connectors/source-typeform/CLAUDE.md deleted file mode 100644 index 4774f6e1dbbe..000000000000 --- a/airbyte-integrations/connectors/source-typeform/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -# source-typeform - -## Unique Behaviors -See [BEHAVIOR.md](./BEHAVIOR.md) for documented unique behaviors: -1. Single-use rotating refresh tokens diff --git a/airbyte-integrations/connectors/source-typeform/BEHAVIOR.md b/airbyte-integrations/connectors/source-typeform/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-typeform/BEHAVIOR.md rename to airbyte-integrations/connectors/source-typeform/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-zendesk-support/CLAUDE.md b/airbyte-integrations/connectors/source-zendesk-support/CLAUDE.md deleted file mode 100644 index 678c9ddfbf23..000000000000 --- a/airbyte-integrations/connectors/source-zendesk-support/CLAUDE.md +++ /dev/null @@ -1,7 +0,0 @@ -# source-zendesk-support - -## Unique Behaviors -See [BEHAVIOR.md](./BEHAVIOR.md) for documented unique behaviors: -1. Tickets incremental export uses `generated_timestamp` not `updated_at` — API can return tickets with `updated_at` before the requested `start_time` -2. StateDelegatingStream for ticket_metrics — stateless bulk path (no checkpointing, synthetic `_ab_updated_at` cursor) vs stateful per-ticket path (one API call per ticket) -3. Enterprise-only streams disabled at manifest level (CDK lacks ConditionalStreams) diff --git a/airbyte-integrations/connectors/source-zendesk-support/BEHAVIOR.md b/airbyte-integrations/connectors/source-zendesk-support/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-zendesk-support/BEHAVIOR.md rename to airbyte-integrations/connectors/source-zendesk-support/CONTRIBUTING.md diff --git a/airbyte-integrations/connectors/source-zendesk-talk/CLAUDE.md b/airbyte-integrations/connectors/source-zendesk-talk/CLAUDE.md deleted file mode 100644 index 5aea8d81173a..000000000000 --- a/airbyte-integrations/connectors/source-zendesk-talk/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -# source-zendesk-talk - -## Unique Behaviors -See [BEHAVIOR.md](./BEHAVIOR.md) for documented unique behaviors: -1. Single-use rotating refresh tokens diff --git a/airbyte-integrations/connectors/source-zendesk-talk/BEHAVIOR.md b/airbyte-integrations/connectors/source-zendesk-talk/CONTRIBUTING.md similarity index 100% rename from airbyte-integrations/connectors/source-zendesk-talk/BEHAVIOR.md rename to airbyte-integrations/connectors/source-zendesk-talk/CONTRIBUTING.md From d823c6d056a457f01d6e0ea734ecd74b1b4cd1e4 Mon Sep 17 00:00:00 2001 From: "octavia-bot[bot]" <108746235+octavia-bot[bot]@users.noreply.github.com> Date: Sat, 28 Mar 2026 03:06:09 +0000 Subject: [PATCH 026/379] docs: sync agent connector docs from airbyte-agent-connectors repo (#75550) Co-authored-by: ian-at-airbyte <187576150+ian-at-airbyte@users.noreply.github.com> --- docs/ai-agents/connectors/clickup-api/README.md | 6 +++--- docs/ai-agents/connectors/facebook-marketing/README.md | 6 +++--- docs/ai-agents/connectors/gitlab/README.md | 6 +++--- docs/ai-agents/connectors/google-search-console/README.md | 6 +++--- docs/ai-agents/connectors/hubspot/README.md | 6 +++--- docs/ai-agents/connectors/linkedin-ads/README.md | 6 +++--- docs/ai-agents/connectors/mailchimp/README.md | 6 +++--- docs/ai-agents/connectors/pinterest/README.md | 6 +++--- docs/ai-agents/connectors/pylon/README.md | 6 +++--- docs/ai-agents/connectors/sentry/README.md | 6 +++--- docs/ai-agents/connectors/shopify/README.md | 6 +++--- docs/ai-agents/connectors/snapchat-marketing/README.md | 6 +++--- docs/ai-agents/connectors/twilio/README.md | 6 +++--- docs/ai-agents/connectors/woocommerce/README.md | 6 +++--- docs/ai-agents/connectors/zendesk-support/README.md | 6 +++--- 15 files changed, 45 insertions(+), 45 deletions(-) diff --git a/docs/ai-agents/connectors/clickup-api/README.md b/docs/ai-agents/connectors/clickup-api/README.md index ccd3b02e7a79..f4a5d9c688d7 100644 --- a/docs/ai-agents/connectors/clickup-api/README.md +++ b/docs/ai-agents/connectors/clickup-api/README.md @@ -135,7 +135,7 @@ See the official [Clickup-Api API reference](https://developer.clickup.com/refer ## Version information -- **Package version:** 0.1.8 -- **Connector version:** 0.1.2 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.9 +- **Connector version:** 0.1.3 +- **Generated with Connector SDK commit SHA:** 09ed4945e89bf743be8a0f0d596ae77c99526607 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/clickup-api/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/facebook-marketing/README.md b/docs/ai-agents/connectors/facebook-marketing/README.md index 698b8282e2d1..60b979059845 100644 --- a/docs/ai-agents/connectors/facebook-marketing/README.md +++ b/docs/ai-agents/connectors/facebook-marketing/README.md @@ -135,7 +135,7 @@ See the official [Facebook-Marketing API reference](https://developers.facebook. ## Version information -- **Package version:** 0.1.61 -- **Connector version:** 1.0.21 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.62 +- **Connector version:** 1.0.22 +- **Generated with Connector SDK commit SHA:** 09ed4945e89bf743be8a0f0d596ae77c99526607 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/facebook-marketing/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/gitlab/README.md b/docs/ai-agents/connectors/gitlab/README.md index 63814df4e8e5..5469a82375bf 100644 --- a/docs/ai-agents/connectors/gitlab/README.md +++ b/docs/ai-agents/connectors/gitlab/README.md @@ -120,7 +120,7 @@ See the official [Gitlab API reference](https://docs.gitlab.com/ee/api/rest/). ## Version information -- **Package version:** 0.1.8 -- **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.9 +- **Connector version:** 1.0.2 +- **Generated with Connector SDK commit SHA:** 09ed4945e89bf743be8a0f0d596ae77c99526607 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/gitlab/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/google-search-console/README.md b/docs/ai-agents/connectors/google-search-console/README.md index a9b7ef18ca44..0018d5474d0e 100644 --- a/docs/ai-agents/connectors/google-search-console/README.md +++ b/docs/ai-agents/connectors/google-search-console/README.md @@ -117,7 +117,7 @@ See the official [Google-Search-Console API reference](https://developers.google ## Version information -- **Package version:** 0.1.7 -- **Connector version:** 1.0.0 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.8 +- **Connector version:** 1.0.1 +- **Generated with Connector SDK commit SHA:** 09ed4945e89bf743be8a0f0d596ae77c99526607 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/google-search-console/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/hubspot/README.md b/docs/ai-agents/connectors/hubspot/README.md index 41014b350e17..ca6f3d0e05e2 100644 --- a/docs/ai-agents/connectors/hubspot/README.md +++ b/docs/ai-agents/connectors/hubspot/README.md @@ -114,7 +114,7 @@ See the official [Hubspot API reference](https://developers.hubspot.com/docs/api ## Version information -- **Package version:** 0.15.125 -- **Connector version:** 0.1.15 -- **Generated with Connector SDK commit SHA:** 547c701420fd178a856f06b58309e9ac6c78f310 +- **Package version:** 0.15.126 +- **Connector version:** 0.1.16 +- **Generated with Connector SDK commit SHA:** 09ed4945e89bf743be8a0f0d596ae77c99526607 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/hubspot/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/linkedin-ads/README.md b/docs/ai-agents/connectors/linkedin-ads/README.md index e07c7c096b45..18e167e1bb09 100644 --- a/docs/ai-agents/connectors/linkedin-ads/README.md +++ b/docs/ai-agents/connectors/linkedin-ads/README.md @@ -115,7 +115,7 @@ See the official [Linkedin-Ads API reference](https://learn.microsoft.com/en-us/ ## Version information -- **Package version:** 0.1.8 -- **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.9 +- **Connector version:** 1.0.2 +- **Generated with Connector SDK commit SHA:** 09ed4945e89bf743be8a0f0d596ae77c99526607 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/linkedin-ads/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/mailchimp/README.md b/docs/ai-agents/connectors/mailchimp/README.md index 6fdf61a2f5a1..c6e9df2f4532 100644 --- a/docs/ai-agents/connectors/mailchimp/README.md +++ b/docs/ai-agents/connectors/mailchimp/README.md @@ -123,7 +123,7 @@ See the official [Mailchimp API reference](https://mailchimp.com/developer/marke ## Version information -- **Package version:** 0.1.77 -- **Connector version:** 1.0.8 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.78 +- **Connector version:** 1.0.9 +- **Generated with Connector SDK commit SHA:** 09ed4945e89bf743be8a0f0d596ae77c99526607 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/mailchimp/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/pinterest/README.md b/docs/ai-agents/connectors/pinterest/README.md index c058e976de9f..8d79ed7be32c 100644 --- a/docs/ai-agents/connectors/pinterest/README.md +++ b/docs/ai-agents/connectors/pinterest/README.md @@ -122,7 +122,7 @@ See the official [Pinterest API reference](https://developers.pinterest.com/docs ## Version information -- **Package version:** 0.1.7 -- **Connector version:** 0.1.1 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.8 +- **Connector version:** 0.1.2 +- **Generated with Connector SDK commit SHA:** 09ed4945e89bf743be8a0f0d596ae77c99526607 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/pinterest/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/pylon/README.md b/docs/ai-agents/connectors/pylon/README.md index 649004b36b5e..0240b7d3723e 100644 --- a/docs/ai-agents/connectors/pylon/README.md +++ b/docs/ai-agents/connectors/pylon/README.md @@ -132,7 +132,7 @@ See the official [Pylon API reference](https://docs.usepylon.com/pylon-docs/deve ## Version information -- **Package version:** 0.1.19 -- **Connector version:** 0.1.5 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.20 +- **Connector version:** 0.1.6 +- **Generated with Connector SDK commit SHA:** 09ed4945e89bf743be8a0f0d596ae77c99526607 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/pylon/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/sentry/README.md b/docs/ai-agents/connectors/sentry/README.md index 0aa0ca84da42..73bf8db9f766 100644 --- a/docs/ai-agents/connectors/sentry/README.md +++ b/docs/ai-agents/connectors/sentry/README.md @@ -107,7 +107,7 @@ See the official [Sentry API reference](https://docs.sentry.io/api/). ## Version information -- **Package version:** 0.1.7 -- **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.8 +- **Connector version:** 1.0.2 +- **Generated with Connector SDK commit SHA:** 09ed4945e89bf743be8a0f0d596ae77c99526607 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/sentry/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/shopify/README.md b/docs/ai-agents/connectors/shopify/README.md index fdb5bf6e9c2d..e860b08b1bbe 100644 --- a/docs/ai-agents/connectors/shopify/README.md +++ b/docs/ai-agents/connectors/shopify/README.md @@ -143,7 +143,7 @@ See the official [Shopify API reference](https://shopify.dev/docs/api/admin-rest ## Version information -- **Package version:** 0.1.73 -- **Connector version:** 0.1.9 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.74 +- **Connector version:** 0.1.10 +- **Generated with Connector SDK commit SHA:** 09ed4945e89bf743be8a0f0d596ae77c99526607 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/shopify/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/snapchat-marketing/README.md b/docs/ai-agents/connectors/snapchat-marketing/README.md index 3eded05817bc..1e99c2081dff 100644 --- a/docs/ai-agents/connectors/snapchat-marketing/README.md +++ b/docs/ai-agents/connectors/snapchat-marketing/README.md @@ -116,7 +116,7 @@ See the official [Snapchat-Marketing API reference](https://developers.snap.com/ ## Version information -- **Package version:** 0.1.7 -- **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.8 +- **Connector version:** 1.0.2 +- **Generated with Connector SDK commit SHA:** 09ed4945e89bf743be8a0f0d596ae77c99526607 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/snapchat-marketing/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/twilio/README.md b/docs/ai-agents/connectors/twilio/README.md index 920c5cbd41ad..556fbf720feb 100644 --- a/docs/ai-agents/connectors/twilio/README.md +++ b/docs/ai-agents/connectors/twilio/README.md @@ -124,7 +124,7 @@ See the official [Twilio API reference](https://www.twilio.com/docs/usage/api). ## Version information -- **Package version:** 0.1.8 -- **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.9 +- **Connector version:** 1.0.2 +- **Generated with Connector SDK commit SHA:** 09ed4945e89bf743be8a0f0d596ae77c99526607 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/twilio/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/woocommerce/README.md b/docs/ai-agents/connectors/woocommerce/README.md index ae83efb6a5ec..dafb12702f48 100644 --- a/docs/ai-agents/connectors/woocommerce/README.md +++ b/docs/ai-agents/connectors/woocommerce/README.md @@ -130,7 +130,7 @@ See the official [Woocommerce API reference](https://woocommerce.github.io/wooco ## Version information -- **Package version:** 0.1.8 -- **Connector version:** 1.0.1 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.9 +- **Connector version:** 1.0.2 +- **Generated with Connector SDK commit SHA:** 09ed4945e89bf743be8a0f0d596ae77c99526607 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/woocommerce/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/zendesk-support/README.md b/docs/ai-agents/connectors/zendesk-support/README.md index 6f2a538fc264..e67dba22778e 100644 --- a/docs/ai-agents/connectors/zendesk-support/README.md +++ b/docs/ai-agents/connectors/zendesk-support/README.md @@ -131,7 +131,7 @@ See the official [Zendesk-Support API reference](https://developer.zendesk.com/a ## Version information -- **Package version:** 0.18.126 -- **Connector version:** 0.1.17 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.18.127 +- **Connector version:** 0.1.18 +- **Generated with Connector SDK commit SHA:** 09ed4945e89bf743be8a0f0d596ae77c99526607 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/zendesk-support/CHANGELOG.md) \ No newline at end of file From 14b356a0207db6726a4ce261353a5bc0da476125 Mon Sep 17 00:00:00 2001 From: "octavia-bot[bot]" <108746235+octavia-bot[bot]@users.noreply.github.com> Date: Sat, 28 Mar 2026 06:27:10 +0000 Subject: [PATCH 027/379] chore(docs): regenerate cached Agent Engine API spec (#75561) Co-authored-by: ian-at-airbyte <187576150+ian-at-airbyte@users.noreply.github.com> --- docusaurus/src/data/agent_engine_api_spec.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docusaurus/src/data/agent_engine_api_spec.json b/docusaurus/src/data/agent_engine_api_spec.json index 93b3ba4140e2..f4408f70dc57 100644 --- a/docusaurus/src/data/agent_engine_api_spec.json +++ b/docusaurus/src/data/agent_engine_api_spec.json @@ -3511,7 +3511,14 @@ }, "CheckStatus": { "type": "string", - "enum": ["pending", "running", "cancelled", "failed", "succeeded"], + "enum": [ + "pending", + "running", + "cancelled", + "failed", + "succeeded", + "inconclusive" + ], "title": "CheckStatus" }, "ConnectionSpecification": { From 417761d868008ace22c5c937865326e37e1f2fc9 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Sun, 29 Mar 2026 19:35:18 -0700 Subject: [PATCH 028/379] ci: add `auto-ai-review` label trigger for AI review workflow (#75567) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/ai-review-command.yml | 10 +++++++++ .github/workflows/auto-ai-review-label.yml | 25 ++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 .github/workflows/auto-ai-review-label.yml diff --git a/.github/workflows/ai-review-command.yml b/.github/workflows/ai-review-command.yml index 55a87c98a7b4..8f4e560b40d7 100644 --- a/.github/workflows/ai-review-command.yml +++ b/.github/workflows/ai-review-command.yml @@ -15,6 +15,16 @@ on: comment-id: description: "Comment ID" required: false + workflow_call: + inputs: + pr: + description: "PR number" + required: true + type: string + comment-id: + description: "Comment ID" + required: false + type: string run-name: "PR AI Review for PR #${{ inputs.pr }}" diff --git a/.github/workflows/auto-ai-review-label.yml b/.github/workflows/auto-ai-review-label.yml new file mode 100644 index 000000000000..c0f8eb1d8176 --- /dev/null +++ b/.github/workflows/auto-ai-review-label.yml @@ -0,0 +1,25 @@ +# Triggers the AI Review workflow when the 'auto-ai-review' label is present. +# Two triggers: +# 1. Label added to a non-draft PR -> immediately call AI review. +# 2. PR marked ready for review -> call AI review if label is already set. +# Draft PRs are skipped on `labeled` to avoid a double-dispatch: ai-review-command.yml +# marks drafts as ready, which would re-trigger this workflow via `ready_for_review`. +name: Auto AI Review on Label + +on: + pull_request: + types: [labeled, ready_for_review] + +run-name: "Auto AI Review for PR #${{ github.event.pull_request.number }}" + +permissions: {} + +jobs: + dispatch-ai-review: + if: | + (github.event.action == 'labeled' && github.event.label.name == 'auto-ai-review' && github.event.pull_request.draft != true) || + (github.event.action == 'ready_for_review' && contains(github.event.pull_request.labels.*.name, 'auto-ai-review')) + uses: ./.github/workflows/ai-review-command.yml + with: + pr: "${{ github.event.pull_request.number }}" + secrets: inherit From 31027ce1de2b8cd7c185075f07c605b0be2b29a5 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Sun, 29 Mar 2026 20:03:02 -0700 Subject: [PATCH 029/379] ci: update stale playbook links from oncall to ai-skills (#75568) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/ai-canary-prerelease-command.yml | 2 +- .github/workflows/ai-create-docs-pr-command.yml | 4 ++-- .github/workflows/ai-prove-fix-command.yml | 2 +- .github/workflows/ai-release-watch-command.yml | 2 +- .github/workflows/ai-review-command.yml | 2 +- .github/workflows/oss-issue-triage.yml | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ai-canary-prerelease-command.yml b/.github/workflows/ai-canary-prerelease-command.yml index e816669a83c8..7a585e540d48 100644 --- a/.github/workflows/ai-canary-prerelease-command.yml +++ b/.github/workflows/ai-canary-prerelease-command.yml @@ -69,6 +69,6 @@ jobs: github-token: ${{ steps.get-app-token.outputs.token }} api-version: v3 org-id: ${{ vars.DEVIN_AI_ORG_ID }} - start-message: "🐤 **AI Canary Prerelease session starting...** Rolling out to 5-10 connections, watching results, and reporting findings. [View playbook](https://github.com/airbytehq/oncall/blob/main/prompts/playbooks/canary_prerelease.md)" + start-message: "🐤 **AI Canary Prerelease session starting...** Rolling out to 5-10 connections, watching results, and reporting findings. [View playbook](https://github.com/airbytehq/ai-skills/blob/main/devin/playbooks/canary_prerelease.md)" tags: | ai-oncall diff --git a/.github/workflows/ai-create-docs-pr-command.yml b/.github/workflows/ai-create-docs-pr-command.yml index d54e442fd4ae..eacc88e5d602 100644 --- a/.github/workflows/ai-create-docs-pr-command.yml +++ b/.github/workflows/ai-create-docs-pr-command.yml @@ -67,7 +67,7 @@ jobs: This will create a documentation PR stacked on top of PR #${PR_NUMBER}. - [View playbook](https://github.com/airbytehq/oncall/blob/main/prompts/playbooks/connectordocs.md) + [View playbook](https://github.com/airbytehq/ai-skills/blob/main/devin/playbooks/connectordocs.md) STARTMSG echo "EOF" } >> $GITHUB_OUTPUT @@ -105,7 +105,7 @@ jobs: This will create a documentation PR targeting the master branch. - [View playbook](https://github.com/airbytehq/oncall/blob/main/prompts/playbooks/connectordocs.md) + [View playbook](https://github.com/airbytehq/ai-skills/blob/main/devin/playbooks/connectordocs.md) STARTMSG echo "EOF" } >> $GITHUB_OUTPUT diff --git a/.github/workflows/ai-prove-fix-command.yml b/.github/workflows/ai-prove-fix-command.yml index 6e20a92f0fd9..f67c792cb227 100644 --- a/.github/workflows/ai-prove-fix-command.yml +++ b/.github/workflows/ai-prove-fix-command.yml @@ -69,6 +69,6 @@ jobs: github-token: ${{ steps.get-app-token.outputs.token }} api-version: v3 org-id: ${{ vars.DEVIN_AI_ORG_ID }} - start-message: "🔍 **AI Prove Fix session starting...** Running readiness checks and testing against customer connections. [View playbook](https://github.com/airbytehq/oncall/blob/main/prompts/playbooks/prove_fix.md)" + start-message: "🔍 **AI Prove Fix session starting...** Running readiness checks and testing against customer connections. [View playbook](https://github.com/airbytehq/ai-skills/blob/main/devin/playbooks/prove_fix.md)" tags: | ai-oncall diff --git a/.github/workflows/ai-release-watch-command.yml b/.github/workflows/ai-release-watch-command.yml index 186f9bc23f83..d19e88f51d6e 100644 --- a/.github/workflows/ai-release-watch-command.yml +++ b/.github/workflows/ai-release-watch-command.yml @@ -69,6 +69,6 @@ jobs: github-token: ${{ steps.get-app-token.outputs.token }} api-version: v3 org-id: ${{ vars.DEVIN_AI_ORG_ID }} - start-message: "👁️ **AI Release Watch session starting...** Monitoring rollout and tracking sync success rates. [View playbook](https://github.com/airbytehq/oncall/blob/main/prompts/playbooks/release_watch.md)" + start-message: "👁️ **AI Release Watch session starting...** Monitoring rollout and tracking sync success rates. [View playbook](https://github.com/airbytehq/ai-skills/blob/main/devin/playbooks/release_watch.md)" tags: | ai-oncall diff --git a/.github/workflows/ai-review-command.yml b/.github/workflows/ai-review-command.yml index 8f4e560b40d7..d405bb03b9a7 100644 --- a/.github/workflows/ai-review-command.yml +++ b/.github/workflows/ai-review-command.yml @@ -113,7 +113,7 @@ jobs: **AI PR Review** starting... Reviewing PR for connector safety and quality. - [View playbook](https://github.com/airbytehq/oncall/blob/main/prompts/playbooks/pr_ai_review.md) + [View playbook](https://github.com/airbytehq/ai-skills/blob/main/devin/playbooks/pr_ai_review.md) tags: | ai-oncall pr-review diff --git a/.github/workflows/oss-issue-triage.yml b/.github/workflows/oss-issue-triage.yml index 1c4b1db578ac..16aba6313ea3 100644 --- a/.github/workflows/oss-issue-triage.yml +++ b/.github/workflows/oss-issue-triage.yml @@ -105,7 +105,7 @@ jobs: - Join the [Airbyte Community Slack](https://slack.airbyte.com) to connect with other users and community members - If you're an Airbyte Cloud customer, you can [open a support ticket](https://support.airbyte.com) or contact your account representative, referencing this issue URL - [View playbook](https://github.com/airbytehq/oncall/blob/main/prompts/playbooks/oss_issue_triage.md) + [View playbook](https://github.com/airbytehq/ai-skills/blob/main/devin/playbooks/oss_issue_triage.md) tags: | oss-issue-triage community-issue From 3785eb23b22a564e3bb3a358f8569b1efa44751d Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 14:29:18 +0300 Subject: [PATCH 030/379] fix(source-gong)!: Fix schema bugs for 'context' and 'value' in extensiveCalls (AI-Triage PR) (#75248) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- .../connectors/source-gong/manifest.yaml | 115 ++++++++++-------- .../connectors/source-gong/metadata.yaml | 18 ++- docs/integrations/sources/gong-migrations.md | 49 ++++++++ docs/integrations/sources/gong.md | 1 + 4 files changed, 131 insertions(+), 52 deletions(-) create mode 100644 docs/integrations/sources/gong-migrations.md diff --git a/airbyte-integrations/connectors/source-gong/manifest.yaml b/airbyte-integrations/connectors/source-gong/manifest.yaml index b680ef0736a1..07f5bb5817d6 100644 --- a/airbyte-integrations/connectors/source-gong/manifest.yaml +++ b/airbyte-integrations/connectors/source-gong/manifest.yaml @@ -1135,57 +1135,70 @@ schemas: - string - "null" context: - description: A list of the agenda of each part of the call. - properties: - objects: - type: array - description: List of objects within the external system. - items: - type: object - properties: - fields: - type: array - description: array. - items: - type: object - properties: - name: - type: - - "null" - - string - description: >- - Field name. For Account supported fields are: Name, - Website, Industry and all the custom fields. For - Opportunity supported fields are Name, LeadSource, - Type, StageName, Probability, Amount, CloseDate and - all the custom fields. - value: - type: - - "null" - - object - description: Field value. - objectId: - type: - - "null" - - string - description: Object ID. - objectType: - type: - - "null" - - string - description: "Object Type. Allowed: Opportunity, Account" - timing: - type: - - "null" - - string - description: "Timing of object. Allowed: Now, TimeOfCall." - system: - type: - - "null" - - string - description: >- - External system name. Allowed: Salesforce, HubSpot, - MicrosoftDynamic, Generic. + type: + - array + - "null" + description: A list of links to external systems such as CRM, Dialer, Case Management, etc. + items: + type: object + properties: + objects: + type: + - array + - "null" + description: List of objects within the external system. + items: + type: object + properties: + fields: + type: + - array + - "null" + description: array. + items: + type: object + properties: + name: + type: + - "null" + - string + description: >- + Field name. For Account supported fields are: Name, + Website, Industry and all the custom fields. For + Opportunity supported fields are Name, LeadSource, + Type, StageName, Probability, Amount, CloseDate and + all the custom fields. + value: + type: + - "null" + - string + - number + - boolean + - object + - array + description: Field value. + objectId: + type: + - "null" + - string + description: Object ID. + objectType: + type: + - "null" + - string + description: "Object Type. Allowed: Opportunity, Account" + timing: + type: + - "null" + - string + description: "Timing of object. Allowed: Now, TimeOfCall." + system: + type: + - "null" + - string + description: >- + External system name. Allowed: Salesforce, HubSpot, + MicrosoftDynamic, Generic. id: type: - "null" diff --git a/airbyte-integrations/connectors/source-gong/metadata.yaml b/airbyte-integrations/connectors/source-gong/metadata.yaml index d89b7715f054..5425117a926f 100644 --- a/airbyte-integrations/connectors/source-gong/metadata.yaml +++ b/airbyte-integrations/connectors/source-gong/metadata.yaml @@ -7,7 +7,7 @@ data: connectorSubtype: api connectorType: source definitionId: 32382e40-3b49-4b99-9c5c-4076501914e7 - dockerImageTag: 0.6.3 + dockerImageTag: 1.0.0 dockerRepository: airbyte/source-gong documentationUrl: https://docs.airbyte.com/integrations/sources/gong githubIssueLabel: source-gong @@ -19,6 +19,22 @@ data: enabled: true oss: enabled: true + releases: + breakingChanges: + 1.0.0: + message: + "The `extensiveCalls` stream schema has changed: the `context` field type + changed from `object` to `array`, and the `value` field within + `context.objects.fields` now accepts `string`, `number`, `boolean`, + `object`, and `array` types instead of only `object`. Users syncing the + `extensiveCalls` stream must refresh the source schema and reset the + stream after upgrading. For more information, see the + [Gong migration guide](https://docs.airbyte.com/integrations/sources/gong-migrations)." + upgradeDeadline: "2026-04-13" + scopedImpact: + - scopeType: stream + impactedScopes: + - "extensiveCalls" releaseStage: alpha remoteRegistries: pypi: diff --git a/docs/integrations/sources/gong-migrations.md b/docs/integrations/sources/gong-migrations.md new file mode 100644 index 000000000000..7f49b3f602da --- /dev/null +++ b/docs/integrations/sources/gong-migrations.md @@ -0,0 +1,49 @@ +import MigrationGuide from '@site/static/_migration_guides_upgrade_guide.md'; + +# Gong Migration Guide + +## Upgrading to 1.0.0 + +:::note +This change is only breaking if you are syncing the `extensiveCalls` stream. +::: + +This update fixes schema bugs in the `extensiveCalls` stream to match the actual data returned by the [Gong API](https://us-66463.app.gong.io/settings/api/documentation#post-/v2/calls/extensive): + +- The `context` field type changed from `object` to `array`. The Gong API returns `context` as an array of CRM context objects, but the previous schema incorrectly defined it as a single object. +- The `value` field within `context.objects.fields` now accepts `string`, `number`, `boolean`, `object`, and `array` types instead of only `object`. The Gong API returns field values in various types depending on the CRM field. + +These schema corrections change the data types in the destination table for the `extensiveCalls` stream. Users syncing this stream must refresh the source schema and reset the stream after upgrading. + +### Migration Steps + +### Refresh affected schemas and reset data + +1. Select **Connections** in the main nav bar. + 1. Select the connection affected by the update. +1. Select the **Schema** tab. + 1. Select **Refresh source schema**. + 1. Select **OK**. + +:::note +Any detected schema changes will be listed for your review. +::: + +1. Select **Save changes** at the top right of the page. + 1. Ensure the **Reset affected streams** option is checked. + +:::note +Depending on destination type you may not be prompted to reset your data. +::: + +1. Select **Save connection**. + +:::note +This will reset the data in your destination and initiate a fresh sync. +::: + +For more information on resetting your data in Airbyte, see [this page](/platform/operator-guides/clear) + +## Connector upgrade guide + + diff --git a/docs/integrations/sources/gong.md b/docs/integrations/sources/gong.md index 85a413ae4255..d44997af31ae 100644 --- a/docs/integrations/sources/gong.md +++ b/docs/integrations/sources/gong.md @@ -78,6 +78,7 @@ The call transcripts stream fetches transcripts one call at a time as a substrea | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------ | +| 1.0.0 | 2026-03-30 | [75248](https://github.com/airbytehq/airbyte/pull/75248) | Fix schema bugs in `extensiveCalls` stream: define `context` as array type and widen `value` field to accept string, number, boolean, object, and array types. This is a breaking change for users syncing the `extensiveCalls` stream. See the [migration guide](https://docs.airbyte.com/integrations/sources/gong-migrations). | | 0.6.3 | 2026-03-27 | [75195](https://github.com/airbytehq/airbyte/pull/75195) | Migrate OAuth scope to scopes object array for granular scopes support | | 0.6.2 | 2026-03-24 | [75388](https://github.com/airbytehq/airbyte/pull/75388) | Update dependencies | | 0.6.1 | 2026-03-20 | [75253](https://github.com/airbytehq/airbyte/pull/75253) | Fix incremental sync for extensiveCalls and answeredScorecards not filtering server-side | From 06830dc1659e3ee709d6298fb0964d1933cb73db Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 10:27:14 -0500 Subject: [PATCH 031/379] fix(source-amazon-ads): Fix profile ID type mismatch in record filter (AI-Triage PR) (#74313) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk Co-authored-by: Octavia Squidington III --- .../connectors/source-amazon-ads/manifest.yaml | 8 ++++++-- .../connectors/source-amazon-ads/metadata.yaml | 2 +- docs/integrations/sources/amazon-ads.md | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/airbyte-integrations/connectors/source-amazon-ads/manifest.yaml b/airbyte-integrations/connectors/source-amazon-ads/manifest.yaml index 14ee906632ec..61284e861fb2 100644 --- a/airbyte-integrations/connectors/source-amazon-ads/manifest.yaml +++ b/airbyte-integrations/connectors/source-amazon-ads/manifest.yaml @@ -147,9 +147,13 @@ definitions: field_path: [] record_filter: condition: >- - {%- set requested_profiles = config.get("profiles", []) -%} + {%- set requested_profiles = config.get("profiles", []) | map('string') | list -%} {%- set requested_marketplace_ids = config.get("marketplace_ids", []) -%} - {{ record["profileId"] in requested_profiles or record["accountInfo"]["marketplaceStringId"] in requested_marketplace_ids if requested_profiles or requested_marketplace_ids else True }} + {%- set account_info = record.get("accountInfo", {}) -%} + {%- set has_filters = requested_profiles or requested_marketplace_ids -%} + {%- set matches_profile_id = (record["profileId"] | string) in requested_profiles -%} + {%- set matches_marketplace_id = account_info.get("marketplaceStringId", "") in requested_marketplace_ids if requested_marketplace_ids else false -%} + {{ matches_profile_id or matches_marketplace_id if has_filters else True }} paginator: type: NoPagination diff --git a/airbyte-integrations/connectors/source-amazon-ads/metadata.yaml b/airbyte-integrations/connectors/source-amazon-ads/metadata.yaml index a05f6c3162cb..af6b4cc350fb 100644 --- a/airbyte-integrations/connectors/source-amazon-ads/metadata.yaml +++ b/airbyte-integrations/connectors/source-amazon-ads/metadata.yaml @@ -13,7 +13,7 @@ data: connectorSubtype: api connectorType: source definitionId: c6b0a29e-1da9-4512-9002-7bfd0cba2246 - dockerImageTag: 7.3.15 + dockerImageTag: 7.3.16 dockerRepository: airbyte/source-amazon-ads documentationUrl: https://docs.airbyte.com/integrations/sources/amazon-ads githubIssueLabel: source-amazon-ads diff --git a/docs/integrations/sources/amazon-ads.md b/docs/integrations/sources/amazon-ads.md index 412ac4b9f780..ff822a24d73a 100644 --- a/docs/integrations/sources/amazon-ads.md +++ b/docs/integrations/sources/amazon-ads.md @@ -169,6 +169,7 @@ If you need better sync performance and are not experiencing rate limiting error | Version | Date | Pull Request | Subject | |:-----------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 7.3.16 | 2026-03-10 | [74313](https://github.com/airbytehq/airbyte/pull/74313) | fix(source-amazon-ads): Fix profile ID type mismatch in record filter (AI-Triage PR) | | 7.3.15 | 2026-03-17 | [74975](https://github.com/airbytehq/airbyte/pull/74975) | Update dependencies | | 7.3.14 | 2026-02-24 | [73761](https://github.com/airbytehq/airbyte/pull/73761) | Update dependencies | | 7.3.13 | 2026-02-10 | [73018](https://github.com/airbytehq/airbyte/pull/73018) | Update dependencies | From f4ec1dc864a997afd05bdfb0acb74a6f9249b051 Mon Sep 17 00:00:00 2001 From: "octavia-bot[bot]" <108746235+octavia-bot[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 16:26:45 +0000 Subject: [PATCH 032/379] docs: sync agent connector docs from airbyte-agent-connectors repo (#75593) Co-authored-by: ian-at-airbyte <187576150+ian-at-airbyte@users.noreply.github.com> --- docs/ai-agents/connectors/asana/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/ai-agents/connectors/asana/README.md b/docs/ai-agents/connectors/asana/README.md index f0e2feb080dc..db6c54454814 100644 --- a/docs/ai-agents/connectors/asana/README.md +++ b/docs/ai-agents/connectors/asana/README.md @@ -130,7 +130,7 @@ See the official [Asana API reference](https://developers.asana.com/reference/re ## Version information -- **Package version:** 0.19.125 -- **Connector version:** 0.1.16 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.19.126 +- **Connector version:** 0.1.17 +- **Generated with Connector SDK commit SHA:** f993df3e0254c01e2344c976d0eb5a2ec4f16c5c - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/asana/CHANGELOG.md) \ No newline at end of file From 04cbed3e3f379a76df48c531341ec9c7e9598d26 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 16:26:49 +0000 Subject: [PATCH 033/379] docs(source-amazon-ads): Fix changelog date, broken links, duplicate content, and outdated stream names (#75592) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- docs/integrations/sources/amazon-ads.md | 34 ++++++++----------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/docs/integrations/sources/amazon-ads.md b/docs/integrations/sources/amazon-ads.md index ff822a24d73a..3da9151e2ed4 100644 --- a/docs/integrations/sources/amazon-ads.md +++ b/docs/integrations/sources/amazon-ads.md @@ -62,19 +62,6 @@ To use the [Amazon Ads API](https://advertising.amazon.com/API/docs/en-us), you 8. **Profile IDs (Optional)** you want to fetch data for. The Amazon Ads source connector supports only profiles with seller and vendor type, profiles with agency type will be ignored. See [docs](https://advertising.amazon.com/API/docs/en-us/concepts/authorization/profiles) for more details. 9. **Marketplace IDs (Optional)** you want to fetch data for. _Note: If Profile IDs are also selected, profiles will be selected if they match the Profile ID **OR** the Marketplace ID._ 10. Click **Set up source**. - - - - -**For Airbyte Open Source:** - -1. **Client ID** of your Amazon Ads developer application. See [onboarding process](https://advertising.amazon.com/API/docs/en-us/setting-up/overview) for more details. -2. **Client Secret** of your Amazon Ads developer application. See [onboarding process](https://advertising.amazon.com/API/docs/en-us/setting-up/overview) for more details. -3. **Refresh Token**. See [onboarding process](https://advertising.amazon.com/API/docs/en-us/setting-up/overview) for more details. -4. Select **Region** to pull data from **North America (NA)**, **Europe (EU)**, **Far East (FE)**. See [docs](https://advertising.amazon.com/API/docs/en-us/info/api-overview#api-endpoints) for more details. -5. **Start Date (Optional)** is used for generating reports starting from the specified start date. This should be in YYYY-MM-DD format and not more than 60 days in the past. If a date is not specified, today's date is used. The date is treated in the timezone of the processed profile. -6. **Profile IDs (Optional)** you want to fetch data for. The Amazon Ads source connector supports only profiles with seller and vendor type, profiles with agency type will be ignored. See [docs](https://advertising.amazon.com/API/docs/en-us/concepts/authorization/profiles) for more details. -7. **Marketplace IDs (Optional)** you want to fetch data for. _Note: If Profile IDs are also selected, profiles will be selected if they match the Profile ID **OR** the Marketplace ID._ :::note @@ -104,7 +91,7 @@ This source is capable of syncing the following streams: - [Sponsored Display Targetings](https://advertising.amazon.com/API/docs/en-us/sponsored-display/3-0/openapi#/Targeting) - [Sponsored Display Creatives](https://advertising.amazon.com/API/docs/en-us/sponsored-display/3-0/openapi#/Creatives) - [Sponsored Display Budget Rules](https://advertising.amazon.com/API/docs/en-us/sponsored-display/3-0/openapi/prod#/BudgetRules/GetSDBudgetRulesForAdvertiser) -- [Sponsored Products Campaigns](https://advertising.amazon.com/API/docs/en-us/sponsored-display/3-0/openapi#/Campaigns) +- [Sponsored Products Campaigns](https://advertising.amazon.com/API/docs/en-us/sponsored-products/2-0/openapi#/Campaigns) - [Sponsored Products Ad groups](https://advertising.amazon.com/API/docs/en-us/sponsored-products/2-0/openapi#/Ad%20groups) - [Sponsored Products Ad Group Bid Recommendations](https://advertising.amazon.com/API/docs/en-us/sponsored-products/2-0/openapi#/Bid%20recommendations/getAdGroupBidRecommendations) - [Sponsored Products Ad Group Suggested Keywords](https://advertising.amazon.com/API/docs/en-us/sponsored-products/2-0/openapi#/Suggested%20keywords) @@ -113,11 +100,10 @@ This source is capable of syncing the following streams: - [Sponsored Products Campaign Negative keywords](https://advertising.amazon.com/API/docs/en-us/sponsored-products/2-0/openapi#/Negative%20keywords) - [Sponsored Products Ads](https://advertising.amazon.com/API/docs/en-us/sponsored-products/2-0/openapi#/Product%20ads) - [Sponsored Products Targetings](https://advertising.amazon.com/API/docs/en-us/sponsored-products/2-0/openapi#/Product%20targeting) -- [Brands Reports](https://advertising.amazon.com/API/docs/en-us/reference/sponsored-brands/2/reports) -- [Brand Video Reports](https://advertising.amazon.com/API/docs/en-us/reference/sponsored-brands/2/reports) -- [Display Reports](https://advertising.amazon.com/API/docs/en-us/guides/reporting/v3/report-types/overview) -- [Products Reports](https://advertising.amazon.com/API/docs/en-us/sponsored-products/2-0/openapi#/Reports) -- [Attribution Reports](https://advertising.amazon.com/API/docs/en-us/amazon-attribution-prod-3p/#/) +- [Sponsored Brands V3 Report](https://advertising.amazon.com/API/docs/en-us/guides/reporting/v3/report-types/overview) +- Sponsored Display Reports (Campaigns, Ad Groups, Product Ads, Targets, ASINs) +- Sponsored Products Reports (Campaigns, Ad Groups, Keywords, Targets, Product Ads, ASINs Keywords, ASINs Targets) +- [Attribution Reports](https://advertising.amazon.com/API/docs/en-us/amazon-attribution-prod-3p/#/) (Products, Performance by Ad Group, Performance by Campaign, Performance by Creative) :::note As of connector version 5.0.0, the `Sponsored Products Ad Group Bid Recommendations` stream provides bid recommendations and impact metrics for an existing automatic targeting ad group. The stream returns bid recommendations for match types `CLOSE_MATCH`, `LOOSE_MATCH`, `SUBSTITUTES`, and `COMPLEMENTS` per theme. For more detail on theme-based bid recommendations, review Amazon's [Theme-base bid suggestions - Quick-start guide](https://advertising.amazon.com/API/docs/en-us/guides/sponsored-products/bid-suggestions/theme-based-bid-suggestions-quickstart-guide). @@ -127,16 +113,16 @@ As of connector version 5.0.0, the `Sponsored Products Ad Group Bid Recommendati All the reports are generated relative to the target profile's timezone. -Campaign reports may sometimes have no data or may not be presenting in records. This can occur when there are no clicks or views associated with the campaigns on the requested day - [details](https://advertising.amazon.com/API/docs/en-us/guides/reporting/v2/faq#why-is-my-report-empty). +Campaign reports may sometimes have no data or may not appear in records. This can occur when there are no clicks or views associated with the campaigns on the requested day. For details, see [Why is my report empty?](https://advertising.amazon.com/API/docs/en-us/guides/reporting/v2/faq#why-is-my-report-empty) Report data synchronization only covers the last 60 days - [details](https://advertising.amazon.com/API/docs/en-us/reference/1/reports#parameters). :::note -The 'Reports' stream(s) by default will have `timeUnit` set to `SUMMARY`. If you would like more granularity, use the `_daily` versions of the report streams, which have - `timeUnit` set to `DAILY`. More info about this can be found [here](https://advertising.amazon.com/API/docs/en-us/guides/reporting/v3/get-started#timeunit-and-supported-columns). +Report streams use `timeUnit=SUMMARY` by default. Each report stream also has a `_daily` variant with `timeUnit=DAILY` for more granular data. For more information, see [timeUnit and supported columns](https://advertising.amazon.com/API/docs/en-us/guides/reporting/v3/get-started#timeunit-and-supported-columns). -**Important limitation**: Amazon may incorrectly detect duplicate report requests when syncing both summary and daily versions of the same report type simultaneously (e.g., `sponsored_brands_v3_report_stream` and `sponsored_brands_v3_report_stream_daily`). If you encounter this issue, create a separate source with only the needed report streams and set the "Number of concurrent workers" to 2 to ensure sequential processing. +**Important limitation**: Amazon may incorrectly detect duplicate report requests when syncing both summary and daily versions of the same report type simultaneously (e.g., `sponsored_brands_v3_report_stream` and `sponsored_brands_v3_report_stream_daily`). If you encounter this issue, create a separate source with only the needed report streams and set the **Number of concurrent workers** to 2 to ensure sequential processing. ::: + ## Performance considerations Information about expected report generation waiting time can be found [here](https://advertising.amazon.com/API/docs/en-us/get-started/developer-notes). @@ -169,7 +155,7 @@ If you need better sync performance and are not experiencing rate limiting error | Version | Date | Pull Request | Subject | |:-----------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 7.3.16 | 2026-03-10 | [74313](https://github.com/airbytehq/airbyte/pull/74313) | fix(source-amazon-ads): Fix profile ID type mismatch in record filter (AI-Triage PR) | +| 7.3.16 | 2026-03-30 | [74313](https://github.com/airbytehq/airbyte/pull/74313) | Fix profile ID type mismatch in record filter | | 7.3.15 | 2026-03-17 | [74975](https://github.com/airbytehq/airbyte/pull/74975) | Update dependencies | | 7.3.14 | 2026-02-24 | [73761](https://github.com/airbytehq/airbyte/pull/73761) | Update dependencies | | 7.3.13 | 2026-02-10 | [73018](https://github.com/airbytehq/airbyte/pull/73018) | Update dependencies | From cdd5a2b0511370536dcdab3f87114ebdcf7b3c34 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Mon, 30 Mar 2026 10:56:19 -0700 Subject: [PATCH 034/379] ci: migrate bump-version-command workflow from airbyte-ci to ops CLI (#75554) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/bump-version-command.yml | 81 ++++++++++++++++------ 1 file changed, 61 insertions(+), 20 deletions(-) diff --git a/.github/workflows/bump-version-command.yml b/.github/workflows/bump-version-command.yml index 011cbddf6080..39fc5f1720ea 100644 --- a/.github/workflows/bump-version-command.yml +++ b/.github/workflows/bump-version-command.yml @@ -47,9 +47,10 @@ jobs: id: job-vars env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.inputs.pr }} shell: bash run: | - PR_JSON=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.inputs.pr }}) + PR_JSON=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUMBER") echo "repo=$(echo "$PR_JSON" | jq -r .head.repo.full_name)" >> $GITHUB_OUTPUT echo "branch=$(echo "$PR_JSON" | jq -r .head.ref)" >> $GITHUB_OUTPUT echo "pr_title=$(echo "$PR_JSON" | jq -r .title)" >> $GITHUB_OUTPUT @@ -83,28 +84,66 @@ jobs: [1]: ${{ steps.job-vars.outputs.run-url }} - - name: Log changelog source + - name: Install uv + uses: astral-sh/setup-uv@6b9c6063abd6010835644d4c2e1bef4cf5cd0fca # v6.0.1 + + - name: Install airbyte-ops CLI + run: uv tool install airbyte-internal-ops + + - name: Detect modified connectors + id: detect-connectors + env: + PR_NUMBER: ${{ github.event.inputs.pr }} run: | - if [ -n "${{ github.event.inputs.changelog }}" ]; then - echo "Using user-provided changelog: ${{ github.event.inputs.changelog }}" + CONNECTORS=$( + airbyte-ops local connector list \ + --repo-path "$GITHUB_WORKSPACE" \ + --modified-only \ + --pr "$PR_NUMBER" \ + --output-format lines + ) + + if [ -z "$CONNECTORS" ]; then + echo "No modified connectors found in PR #$PR_NUMBER." else - echo "Using PR title as changelog: ${{ steps.job-vars.outputs.pr_title }}" + echo "Modified connectors:" + echo "$CONNECTORS" fi - - name: Run airbyte-ci connectors --modified bump-version - uses: ./.github/actions/run-airbyte-ci - continue-on-error: true - with: - context: "manual" - gcs_credentials: ${{ secrets.METADATA_SERVICE_PROD_GCS_CREDENTIALS }} - sentry_dsn: ${{ secrets.SENTRY_AIRBYTE_CI_DSN }} - github_token: ${{ secrets.GH_PAT_MAINTENANCE_OCTAVIA }} - git_repo_url: https://github.com/${{ steps.job-vars.outputs.repo }}.git - subcommand: | - connectors --modified bump-version \ - ${{ github.event.inputs.type }} \ - "${{ github.event.inputs.changelog != '' && github.event.inputs.changelog || steps.job-vars.outputs.pr_title }}" \ - --pr-number ${{ github.event.inputs.pr }} + # Pass the connector list to the next step via GITHUB_OUTPUT. + # Only set the multiline output when CONNECTORS is non-empty so that + # the downstream `if:` reliably evaluates to false for empty lists. + if [ -n "$CONNECTORS" ]; then + EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) + echo "connectors<<$EOF" >> $GITHUB_OUTPUT + echo "$CONNECTORS" >> $GITHUB_OUTPUT + echo "$EOF" >> $GITHUB_OUTPUT + fi + + - name: Bump versions for modified connectors + if: steps.detect-connectors.outputs.connectors != '' + env: + BUMP_TYPE: ${{ github.event.inputs.type }} + CHANGELOG_MSG: ${{ github.event.inputs.changelog }} + PR_TITLE: ${{ steps.job-vars.outputs.pr_title }} + PR_NUMBER: ${{ github.event.inputs.pr }} + CONNECTORS: ${{ steps.detect-connectors.outputs.connectors }} + run: | + MSG="${CHANGELOG_MSG:-$PR_TITLE}" + echo "Changelog message: $MSG" + echo "Bump type: $BUMP_TYPE" + echo "" + + echo "$CONNECTORS" | while IFS= read -r connector; do + [ -z "$connector" ] && continue + echo "--- Bumping version for $connector ---" + airbyte-ops local connector bump-version \ + --name "$connector" \ + --repo-path "$GITHUB_WORKSPACE" \ + --bump-type "$BUMP_TYPE" \ + --changelog-message "$MSG" \ + --pr-number "$PR_NUMBER" + done # This is helpful in the case that we change a previously committed generated file to be ignored by git. - name: Remove any files that have been gitignored @@ -121,11 +160,13 @@ jobs: - name: Commit changes id: commit-step if: steps.git-diff.outputs.changes == 'true' + env: + BUMP_TYPE: ${{ github.event.inputs.type }} run: | git config --global user.name "Octavia Squidington III" git config --global user.email "octavia-squidington-iii@users.noreply.github.com" git add . - git commit -m "chore: bump-version ${{ github.event.inputs.bump-type }}" + git commit -m "chore: bump-version $BUMP_TYPE" echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT - name: Push changes to '(${{ steps.job-vars.outputs.repo }})' From d57bc9badc5003724429f7a3465805b872de527f Mon Sep 17 00:00:00 2001 From: Vai Ignatavicius Date: Mon, 30 Mar 2026 18:59:59 +0100 Subject: [PATCH 035/379] docs: Clarify Datadog integration status for Airbyte Cloud (#75586) Co-authored-by: Ian Alton --- docs/platform/operator-guides/collecting-metrics.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/platform/operator-guides/collecting-metrics.md b/docs/platform/operator-guides/collecting-metrics.md index 6bf98f7ae101..14f499168d36 100644 --- a/docs/platform/operator-guides/collecting-metrics.md +++ b/docs/platform/operator-guides/collecting-metrics.md @@ -12,12 +12,11 @@ All Airbyte instances include extensive logging for each connector. These logs g ## OpenTelemetry metrics monitoring {#otel} -Self-Managed Enterprise customers can configure Airbyte to send telemetry data to an OpenTelemetry collector endpoint so you can consume these metrics in your downstream monitoring tool of choice. See [OpenTelemetry metrics monitoring](open-telemetry). +Self-Managed Enterprise customers can configure Airbyte to send telemetry data to an OpenTelemetry collector endpoint so you can consume these metrics in your downstream monitoring tool of choice. See [OpenTelemetry metrics monitoring](open-telemetry). Airbyte Cloud does not currently support a an OTEL integration. ## Datadog Integration -Airbyte uses Datadog to monitor Airbyte Cloud performance on a [number of metrics](https://docs.datadoghq.com/integrations/airbyte/#data-collected) important to your experience. This integration only works on legacy Docker deployments of Airbyte. Airbyte is working on an improved version for abctl and Kubernetes. This could become available later as an enterprise feature to help you monitor your own deployment. If you're an enterprise customer and Datadog integration is important to you, let us know. -Currently, you can send metrics to Datadog using [OpenTelemetry](open-telemetry). +Self-Managed Enterprise customers can send metrics to Datadog using [OpenTelemetry](open-telemetry). Airbyte Cloud does not currently support a Datadog integration. ![Datadog's Airbyte Integration Dashboard](assets/DatadogAirbyteIntegration_OutOfTheBox_Dashboard.png) From ba8185880c43a0afa038c2a24af4bc40970b3cba Mon Sep 17 00:00:00 2001 From: "octavia-bot[bot]" <108746235+octavia-bot[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 18:25:16 +0000 Subject: [PATCH 036/379] docs: sync agent connector docs from airbyte-agent-connectors repo (#75605) Co-authored-by: ian-at-airbyte <187576150+ian-at-airbyte@users.noreply.github.com> --- docs/ai-agents/connectors/slack/README.md | 10 +- docs/ai-agents/connectors/slack/REFERENCE.md | 184 ++++++++++++++++++- 2 files changed, 187 insertions(+), 7 deletions(-) diff --git a/docs/ai-agents/connectors/slack/README.md b/docs/ai-agents/connectors/slack/README.md index 5ada9760e2f8..9357f3a7c31b 100644 --- a/docs/ai-agents/connectors/slack/README.md +++ b/docs/ai-agents/connectors/slack/README.md @@ -114,8 +114,8 @@ This connector supports the following entities and actions. For more details, se |--------|---------| | Users | [List](./REFERENCE.md#users-list), [Get](./REFERENCE.md#users-get), [Search](./REFERENCE.md#users-search) | | Channels | [List](./REFERENCE.md#channels-list), [Get](./REFERENCE.md#channels-get), [Create](./REFERENCE.md#channels-create), [Update](./REFERENCE.md#channels-update), [Search](./REFERENCE.md#channels-search) | -| Channel Messages | [List](./REFERENCE.md#channel-messages-list) | -| Threads | [List](./REFERENCE.md#threads-list) | +| Channel Messages | [List](./REFERENCE.md#channel-messages-list), [Search](./REFERENCE.md#channel-messages-search) | +| Threads | [List](./REFERENCE.md#threads-list), [Search](./REFERENCE.md#threads-search) | | Messages | [Create](./REFERENCE.md#messages-create), [Update](./REFERENCE.md#messages-update) | | Channel Topics | [Create](./REFERENCE.md#channel-topics-create) | | Channel Purposes | [Create](./REFERENCE.md#channel-purposes-create) | @@ -132,7 +132,7 @@ See the official [Slack API reference](https://api.slack.com/methods). ## Version information -- **Package version:** 0.1.86 -- **Connector version:** 0.1.16 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.87 +- **Connector version:** 0.1.17 +- **Generated with Connector SDK commit SHA:** f07b3c8f134cf5c31405771d57ff2d95748d241b - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/slack/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/slack/REFERENCE.md b/docs/ai-agents/connectors/slack/REFERENCE.md index b8a97375321d..415414631a44 100644 --- a/docs/ai-agents/connectors/slack/REFERENCE.md +++ b/docs/ai-agents/connectors/slack/REFERENCE.md @@ -10,8 +10,8 @@ The Slack connector supports the following entities and actions. |--------|---------| | Users | [List](#users-list), [Get](#users-get), [Search](#users-search) | | Channels | [List](#channels-list), [Get](#channels-get), [Create](#channels-create), [Update](#channels-update), [Search](#channels-search) | -| Channel Messages | [List](#channel-messages-list) | -| Threads | [List](#threads-list) | +| Channel Messages | [List](#channel-messages-list), [Search](#channel-messages-search) | +| Threads | [List](#threads-list), [Search](#threads-search) | | Messages | [Create](#messages-create), [Update](#messages-update) | | Channel Topics | [Create](#channel-topics-create) | | Channel Purposes | [Create](#channel-purposes-create) | @@ -812,6 +812,98 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con
+### Channel Messages Search + +Search and filter channel messages records powered by Airbyte's data sync. This often provides additional fields and operators beyond what the API natively supports, making it easier to narrow down results before performing further operations. Only available in hosted mode. + +#### Python SDK + +```python +await slack.channel_messages.search( + query={"filter": {"eq": {"type": ""}}} +) +``` + +#### API + +```bash +curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_connector_id}/execute' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer {your_auth_token}' \ +--data '{ + "entity": "channel_messages", + "action": "search", + "params": { + "query": {"filter": {"eq": {"type": ""}}} + } +}' +``` + +#### Parameters + +| Parameter Name | Type | Required | Description | +|----------------|------|----------|-------------| +| `query` | `object` | Yes | Filter and sort conditions. Supports operators: eq, neq, gt, gte, lt, lte, in, like, fuzzy, keyword, not, and, or | +| `query.filter` | `object` | No | Filter conditions | +| `query.sort` | `array` | No | Sort conditions | +| `limit` | `integer` | No | Maximum results to return (default 1000) | +| `cursor` | `string` | No | Pagination cursor from previous response's `meta.cursor` | +| `fields` | `array` | No | Field paths to include in results | + +#### Searchable Fields + +| Field Name | Type | Description | +|------------|------|-------------| +| `type` | `string` | Message type. | +| `subtype` | `string` | Message subtype. | +| `ts` | `string` | Message timestamp (unique identifier). | +| `user` | `string` | User ID who sent the message. | +| `text` | `string` | Message text content. | +| `thread_ts` | `string` | Thread parent timestamp. | +| `reply_count` | `integer` | Number of replies in thread. | +| `reply_users_count` | `integer` | Number of unique users who replied. | +| `latest_reply` | `string` | Timestamp of latest reply. | +| `reply_users` | `array` | User IDs who replied to the thread. | +| `is_locked` | `boolean` | Whether the thread is locked. | +| `subscribed` | `boolean` | Whether the user is subscribed to the thread. | +| `reactions` | `array` | Reactions to the message. | +| `attachments` | `array` | Message attachments. | +| `blocks` | `array` | Block kit blocks. | +| `bot_id` | `string` | Bot ID if message was sent by a bot. | +| `bot_profile` | `object` | Bot profile information. | +| `team` | `string` | Team ID. | + +
+Response Schema + +| Field Name | Type | Description | +|------------|------|-------------| +| `data` | `array` | List of matching records | +| `meta` | `object` | Pagination metadata | +| `meta.has_more` | `boolean` | Whether additional pages are available | +| `meta.cursor` | `string \| null` | Cursor for next page of results | +| `meta.took_ms` | `number \| null` | Query execution time in milliseconds | +| `data[].type` | `string` | Message type. | +| `data[].subtype` | `string` | Message subtype. | +| `data[].ts` | `string` | Message timestamp (unique identifier). | +| `data[].user` | `string` | User ID who sent the message. | +| `data[].text` | `string` | Message text content. | +| `data[].thread_ts` | `string` | Thread parent timestamp. | +| `data[].reply_count` | `integer` | Number of replies in thread. | +| `data[].reply_users_count` | `integer` | Number of unique users who replied. | +| `data[].latest_reply` | `string` | Timestamp of latest reply. | +| `data[].reply_users` | `array` | User IDs who replied to the thread. | +| `data[].is_locked` | `boolean` | Whether the thread is locked. | +| `data[].subscribed` | `boolean` | Whether the user is subscribed to the thread. | +| `data[].reactions` | `array` | Reactions to the message. | +| `data[].attachments` | `array` | Message attachments. | +| `data[].blocks` | `array` | Block kit blocks. | +| `data[].bot_id` | `string` | Bot ID if message was sent by a bot. | +| `data[].bot_profile` | `object` | Bot profile information. | +| `data[].team` | `string` | Team ID. | + +
+ ## Threads ### Threads List @@ -933,6 +1025,94 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con
+### Threads Search + +Search and filter threads records powered by Airbyte's data sync. This often provides additional fields and operators beyond what the API natively supports, making it easier to narrow down results before performing further operations. Only available in hosted mode. + +#### Python SDK + +```python +await slack.threads.search( + query={"filter": {"eq": {"type": ""}}} +) +``` + +#### API + +```bash +curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_connector_id}/execute' \ +--header 'Content-Type: application/json' \ +--header 'Authorization: Bearer {your_auth_token}' \ +--data '{ + "entity": "threads", + "action": "search", + "params": { + "query": {"filter": {"eq": {"type": ""}}} + } +}' +``` + +#### Parameters + +| Parameter Name | Type | Required | Description | +|----------------|------|----------|-------------| +| `query` | `object` | Yes | Filter and sort conditions. Supports operators: eq, neq, gt, gte, lt, lte, in, like, fuzzy, keyword, not, and, or | +| `query.filter` | `object` | No | Filter conditions | +| `query.sort` | `array` | No | Sort conditions | +| `limit` | `integer` | No | Maximum results to return (default 1000) | +| `cursor` | `string` | No | Pagination cursor from previous response's `meta.cursor` | +| `fields` | `array` | No | Field paths to include in results | + +#### Searchable Fields + +| Field Name | Type | Description | +|------------|------|-------------| +| `type` | `string` | Message type. | +| `subtype` | `string` | Message subtype. | +| `ts` | `string` | Message timestamp (unique identifier). | +| `user` | `string` | User ID who sent the message. | +| `text` | `string` | Message text content. | +| `thread_ts` | `string` | Thread parent timestamp. | +| `parent_user_id` | `string` | User ID of the parent message author (present in thread replies). | +| `reply_count` | `integer` | Number of replies in thread. | +| `reply_users_count` | `integer` | Number of unique users who replied. | +| `latest_reply` | `string` | Timestamp of latest reply. | +| `reply_users` | `array` | User IDs who replied to the thread. | +| `is_locked` | `boolean` | Whether the thread is locked. | +| `subscribed` | `boolean` | Whether the user is subscribed to the thread. | +| `blocks` | `array` | Block kit blocks. | +| `bot_id` | `string` | Bot ID if message was sent by a bot. | +| `team` | `string` | Team ID. | + +
+Response Schema + +| Field Name | Type | Description | +|------------|------|-------------| +| `data` | `array` | List of matching records | +| `meta` | `object` | Pagination metadata | +| `meta.has_more` | `boolean` | Whether additional pages are available | +| `meta.cursor` | `string \| null` | Cursor for next page of results | +| `meta.took_ms` | `number \| null` | Query execution time in milliseconds | +| `data[].type` | `string` | Message type. | +| `data[].subtype` | `string` | Message subtype. | +| `data[].ts` | `string` | Message timestamp (unique identifier). | +| `data[].user` | `string` | User ID who sent the message. | +| `data[].text` | `string` | Message text content. | +| `data[].thread_ts` | `string` | Thread parent timestamp. | +| `data[].parent_user_id` | `string` | User ID of the parent message author (present in thread replies). | +| `data[].reply_count` | `integer` | Number of replies in thread. | +| `data[].reply_users_count` | `integer` | Number of unique users who replied. | +| `data[].latest_reply` | `string` | Timestamp of latest reply. | +| `data[].reply_users` | `array` | User IDs who replied to the thread. | +| `data[].is_locked` | `boolean` | Whether the thread is locked. | +| `data[].subscribed` | `boolean` | Whether the user is subscribed to the thread. | +| `data[].blocks` | `array` | Block kit blocks. | +| `data[].bot_id` | `string` | Bot ID if message was sent by a bot. | +| `data[].team` | `string` | Team ID. | + +
+ ## Messages ### Messages Create From c378ec5cb01cd0ecbeee5988501298a3642de3ca Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 11:35:23 -0700 Subject: [PATCH 037/379] fix(source-hubspot): map HTTP 429 to RATE_LIMITED instead of RETRY (#75595) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- .../connectors/source-hubspot/components.py | 2 +- .../connectors/source-hubspot/manifest.yaml | 4 +-- .../connectors/source-hubspot/metadata.yaml | 2 +- .../unit_tests/test_components.py | 36 +++++++++++++++++-- docs/integrations/sources/hubspot.md | 1 + 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/airbyte-integrations/connectors/source-hubspot/components.py b/airbyte-integrations/connectors/source-hubspot/components.py index a90461fea74c..54f314195dba 100644 --- a/airbyte-integrations/connectors/source-hubspot/components.py +++ b/airbyte-integrations/connectors/source-hubspot/components.py @@ -709,7 +709,7 @@ def build_associations_retriever( ], response_filters=[ HttpResponseFilter( - action="RETRY", + action="RATE_LIMITED", http_codes={429}, error_message="HubSpot rate limit reached (429). Backoff based on 'Retry-After' header, then exponential backoff fallback.", config=config, diff --git a/airbyte-integrations/connectors/source-hubspot/manifest.yaml b/airbyte-integrations/connectors/source-hubspot/manifest.yaml index a1c99cdd5bca..bc6505c583aa 100644 --- a/airbyte-integrations/connectors/source-hubspot/manifest.yaml +++ b/airbyte-integrations/connectors/source-hubspot/manifest.yaml @@ -49,7 +49,7 @@ definitions: - type: ExponentialBackoffStrategy response_filters: - type: HttpResponseFilter - action: RETRY + action: RATE_LIMITED http_codes: - 429 error_message: >- @@ -101,7 +101,7 @@ definitions: - type: ExponentialBackoffStrategy response_filters: - type: HttpResponseFilter - action: RETRY + action: RATE_LIMITED http_codes: - 429 error_message: >- diff --git a/airbyte-integrations/connectors/source-hubspot/metadata.yaml b/airbyte-integrations/connectors/source-hubspot/metadata.yaml index c98774bd8a90..2e66076de1f4 100644 --- a/airbyte-integrations/connectors/source-hubspot/metadata.yaml +++ b/airbyte-integrations/connectors/source-hubspot/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: api connectorType: source definitionId: 36c891d9-4bd9-43ac-bad2-10e12756272c - dockerImageTag: 6.3.3 + dockerImageTag: 6.3.4 dockerRepository: airbyte/source-hubspot documentationUrl: https://docs.airbyte.com/integrations/sources/hubspot resourceRequirements: diff --git a/airbyte-integrations/connectors/source-hubspot/unit_tests/test_components.py b/airbyte-integrations/connectors/source-hubspot/unit_tests/test_components.py index cf829625ed8d..15136ea2d358 100644 --- a/airbyte-integrations/connectors/source-hubspot/unit_tests/test_components.py +++ b/airbyte-integrations/connectors/source-hubspot/unit_tests/test_components.py @@ -10,6 +10,7 @@ from airbyte_cdk.models import FailureType from airbyte_cdk.sources.declarative.decoders import JsonDecoder +from airbyte_cdk.sources.declarative.interpolation import InterpolatedString from airbyte_cdk.sources.declarative.requesters.error_handlers.http_response_filter import HttpResponseFilter from airbyte_cdk.sources.declarative.retrievers import SimpleRetriever from airbyte_cdk.sources.streams.http.error_handlers.response_models import ResponseAction @@ -695,6 +696,35 @@ def test_crm_search_pagination_strategy( assert actual_next_page_token == expected_next_page_token +def test_build_associations_retriever_uses_rate_limited_for_429(): + """Verify that the associations retriever maps HTTP 429 to RATE_LIMITED, not RETRY.""" + components_module = __import__("components") + + config = { + "start_date": "2021-01-10T00:00:00Z", + "credentials": {"credentials_title": "Private App Credentials", "access_token": "test_access_token"}, + } + + parent_entity = InterpolatedString.create("deals", parameters={}) + + retriever = components_module.build_associations_retriever( + associations_list=["companies", "contacts"], + parent_entity=parent_entity, + config=config, + ) + + error_handler = retriever.requester.error_handler + # Find the response filter for 429 and verify it uses RATE_LIMITED + found_429_filter = False + for response_filter in error_handler.response_filters: + if 429 in response_filter.http_codes: + found_429_filter = True + assert ( + response_filter.action == ResponseAction.RATE_LIMITED + ), f"Expected RATE_LIMITED for HTTP 429 in associations retriever, got {response_filter.action}" + assert found_429_filter, "No response filter found for HTTP 429 in associations retriever" + + @pytest.mark.parametrize( "credentials_title, status_code, expected_action, expected_failure_type, expected_error_message", [ @@ -717,10 +747,10 @@ def test_crm_search_pagination_strategy( pytest.param( "Private App Credentials", 429, - ResponseAction.RETRY, + ResponseAction.RATE_LIMITED, None, None, - id="pat_429_retries_normally", + id="pat_429_rate_limited", ), pytest.param( "Private App Credentials", @@ -748,7 +778,7 @@ def test_hubspot_error_handler_401_by_auth_type( backoff_strategies=[], response_filters=[ HttpResponseFilter( - action="RETRY", + action="RATE_LIMITED", http_codes={429}, error_message="Rate limited.", config=config, diff --git a/docs/integrations/sources/hubspot.md b/docs/integrations/sources/hubspot.md index dc73843f0b89..d2e7a6034353 100644 --- a/docs/integrations/sources/hubspot.md +++ b/docs/integrations/sources/hubspot.md @@ -342,6 +342,7 @@ If you use [custom properties](https://knowledge.hubspot.com/properties/create-a | Version | Date | Pull Request | Subject | |:------------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 6.3.4 | 2026-03-30 | [75595](https://github.com/airbytehq/airbyte/pull/75595) | Fixed HTTP 429 responses mapped to RETRY instead of RATE_LIMITED, enabling correct rate-limit handling | | 6.3.3 | 2026-03-26 | [75452](https://github.com/airbytehq/airbyte/pull/75452) | Fixed HTTP 401 errors retrying indefinitely for Private App Token authentication | | 6.3.2 | 2026-03-17 | [74526](https://github.com/airbytehq/airbyte/pull/74526) | Update dependencies | | 6.3.1 | 2026-03-09 | [74410](https://github.com/airbytehq/airbyte/pull/74410) | Promoting release candidate 6.3.1-rc.1 to a main version. | From 7c77d0440c2fd163c48000de6280a132f24fa8a7 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 11:37:38 -0700 Subject: [PATCH 038/379] fix(source-notion): Fix 429 status code mapping from RETRY to RATE_LIMITED (#75603) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- .../connectors/source-notion/manifest.yaml | 2 +- .../connectors/source-notion/metadata.yaml | 2 +- .../source-notion/unit_tests/test_source.py | 46 +++++++++++++++++++ docs/integrations/sources/notion.md | 1 + 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-notion/manifest.yaml b/airbyte-integrations/connectors/source-notion/manifest.yaml index e8b64b8efd02..0bf83f673b28 100644 --- a/airbyte-integrations/connectors/source-notion/manifest.yaml +++ b/airbyte-integrations/connectors/source-notion/manifest.yaml @@ -24,7 +24,7 @@ definitions: header: retry-after response_filters: - type: HttpResponseFilter - action: RETRY + action: RATE_LIMITED http_codes: - 429 - type: DefaultErrorHandler diff --git a/airbyte-integrations/connectors/source-notion/metadata.yaml b/airbyte-integrations/connectors/source-notion/metadata.yaml index 3a9e4050def4..0f7123b3310c 100644 --- a/airbyte-integrations/connectors/source-notion/metadata.yaml +++ b/airbyte-integrations/connectors/source-notion/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: api connectorType: source definitionId: 6e00b415-b02e-4160-bf02-58176a0ae687 - dockerImageTag: 4.0.2 + dockerImageTag: 4.0.3 dockerRepository: airbyte/source-notion documentationUrl: https://docs.airbyte.com/integrations/sources/notion externalDocumentationUrls: diff --git a/airbyte-integrations/connectors/source-notion/unit_tests/test_source.py b/airbyte-integrations/connectors/source-notion/unit_tests/test_source.py index c75f064ab739..35fac7676392 100644 --- a/airbyte-integrations/connectors/source-notion/unit_tests/test_source.py +++ b/airbyte-integrations/connectors/source-notion/unit_tests/test_source.py @@ -3,9 +3,26 @@ # from unittest.mock import MagicMock +import pytest +from requests import Response + +from airbyte_cdk.sources.streams.http.error_handlers import ResponseAction from unit_tests.conftest import get_source +def _get_stream_by_name(stream_name, config): + source = get_source(config) + streams = source.streams(config) + for stream in streams: + if stream.name == stream_name: + return stream + raise ValueError(f"Stream {stream_name} not found") + + +def _get_retriever(stream): + return stream._stream_partition_generator._partition_factory._retriever + + def test_streams(): config_mock = {"start_date": "2020-01-01T00:00:00.000Z", "credentials": {"auth_type": "token", "token": "abcd"}} source = get_source(config_mock) @@ -20,3 +37,32 @@ def test_streams_no_start_date_in_config(): streams = source.streams(config_mock) expected_streams_number = 5 assert len(streams) == expected_streams_number + + +@pytest.mark.parametrize( + "status_code, expected_action", + [ + (200, ResponseAction.SUCCESS), + (429, ResponseAction.RATE_LIMITED), + (500, ResponseAction.RETRY), + ], +) +def test_error_handler_maps_429_to_rate_limited(status_code, expected_action): + """ + Verify that HTTP 429 responses are mapped to RATE_LIMITED (not RETRY). + + Using RATE_LIMITED ensures: + 1. The CDK emits a RATE_LIMITED stream status for observability. + 2. The CDK retries endlessly on rate limits (when exit_on_rate_limit is False), + preventing syncs from failing after max retries on busy workspaces. + """ + config = {"start_date": "2020-01-01T00:00:00.000Z", "credentials": {"auth_type": "token", "token": "abcd"}} + stream = _get_stream_by_name("pages", config) + retriever = _get_retriever(stream) + + mocked_response = MagicMock(spec=Response, status_code=status_code) + mocked_response.ok = status_code == 200 + mocked_response.headers = {"Content-Type": "application/json"} + + result = retriever.requester.error_handler.interpret_response(mocked_response) + assert result.response_action == expected_action diff --git a/docs/integrations/sources/notion.md b/docs/integrations/sources/notion.md index a31b9f6a2dfa..da206f399d93 100644 --- a/docs/integrations/sources/notion.md +++ b/docs/integrations/sources/notion.md @@ -121,6 +121,7 @@ The Blocks stream recursively fetches child blocks up to 30 levels deep. Pages w | Version | Date | Pull Request | Subject | |:------------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 4.0.3 | 2026-03-30 | [75603](https://github.com/airbytehq/airbyte/pull/75603) | Fix 429 status code mapping from RETRY to RATE_LIMITED for improved rate limit handling and observability | | 4.0.2 | 2026-03-23 | [75290](https://github.com/airbytehq/airbyte/pull/75290) | Update v4.0.0 upgrade deadline to 2026-04-10 | | 4.0.1 | 2026-03-10 | [74616](https://github.com/airbytehq/airbyte/pull/74616) | Update dependencies | | 4.0.0 | 2026-02-25 | [74017](https://github.com/airbytehq/airbyte/pull/74017) | Migrate to Notion API version 2025-09-03: replace `databases` stream with `data_sources`, update page parent references, and add new schema fields | From 2135a984c343c5a4782797c33a4cea7aa014739c Mon Sep 17 00:00:00 2001 From: "Ryan Br..." Date: Mon, 30 Mar 2026 12:49:09 -0700 Subject: [PATCH 039/379] fix: update sort order before columns to handle dropped columns in PK. Drop sort order when not-dedupe. (#75546) --- airbyte-cdk/bulk/core/load/changelog.md | 1 + airbyte-cdk/bulk/core/load/version.properties | 2 +- .../parquet/IcebergTableSynchronizer.kt | 109 +++++++ .../parquet/IcebergTableSynchronizerTest.kt | 281 ++++++++++++++++++ 4 files changed, 392 insertions(+), 1 deletion(-) diff --git a/airbyte-cdk/bulk/core/load/changelog.md b/airbyte-cdk/bulk/core/load/changelog.md index a3c514b8e25c..449647adefce 100644 --- a/airbyte-cdk/bulk/core/load/changelog.md +++ b/airbyte-cdk/bulk/core/load/changelog.md @@ -9,6 +9,7 @@ The Load CDK provides functionality for destination connectors including stream- | Version | Date | Pull Request | Subject | |---------|------------|--------------|-------------------------------------------------------------------------------------------------| +| 1.0.7 | 2026-03-27 | | Fix: update Iceberg sort order before schema evolution to prevent ValidationException when deleting columns referenced by the sort order. Handles Dedupe-to-Append mode switches and PK changes. | | 1.0.6 | 2026-03-12 | [#74715](https://github.com/airbytehq/airbyte/pull/74715) | Fix: drop temp table after successful upsert to prevent duplicate records across syncs. | | 1.0.5 | 2026-03-10 | [#74723](https://github.com/airbytehq/airbyte/pull/74723) | Fix schema evolution: defer identifier field update when replacing columns to avoid Iceberg conflict. | | 1.0.4 | 2026-03-05 | [#74328](https://github.com/airbytehq/airbyte/pull/74328) | Fix iceberg dedup: map PK NumberType to StringType instead of DecimalType for identifier field compatibility. | diff --git a/airbyte-cdk/bulk/core/load/version.properties b/airbyte-cdk/bulk/core/load/version.properties index 71a5aa490498..4659c1221749 100644 --- a/airbyte-cdk/bulk/core/load/version.properties +++ b/airbyte-cdk/bulk/core/load/version.properties @@ -1 +1 @@ -version=1.0.6 +version=1.0.7 diff --git a/airbyte-cdk/bulk/toolkits/load-iceberg-parquet/src/main/kotlin/io/airbyte/cdk/load/toolkits/iceberg/parquet/IcebergTableSynchronizer.kt b/airbyte-cdk/bulk/toolkits/load-iceberg-parquet/src/main/kotlin/io/airbyte/cdk/load/toolkits/iceberg/parquet/IcebergTableSynchronizer.kt index f58d56b84841..ec4a63e6a143 100644 --- a/airbyte-cdk/bulk/toolkits/load-iceberg-parquet/src/main/kotlin/io/airbyte/cdk/load/toolkits/iceberg/parquet/IcebergTableSynchronizer.kt +++ b/airbyte-cdk/bulk/toolkits/load-iceberg-parquet/src/main/kotlin/io/airbyte/cdk/load/toolkits/iceberg/parquet/IcebergTableSynchronizer.kt @@ -7,13 +7,17 @@ package io.airbyte.cdk.load.toolkits.iceberg.parquet import io.airbyte.cdk.ConfigErrorException import io.airbyte.cdk.load.toolkits.iceberg.parquet.IcebergTypesComparator.Companion.PARENT_CHILD_SEPARATOR import io.airbyte.cdk.load.toolkits.iceberg.parquet.IcebergTypesComparator.Companion.splitIntoParentAndLeaf +import io.github.oshai.kotlinlogging.KotlinLogging import jakarta.inject.Singleton import org.apache.iceberg.Schema +import org.apache.iceberg.SortDirection import org.apache.iceberg.Table import org.apache.iceberg.UpdateSchema import org.apache.iceberg.types.Type import org.apache.iceberg.types.Type.PrimitiveType +private val logger = KotlinLogging.logger {} + /** Describes how the [IcebergTableSynchronizer] handles column type changes. */ enum class ColumnTypeChangeBehavior { /** @@ -86,6 +90,27 @@ class IcebergTableSynchronizer( return SchemaUpdateResult(existingSchema, pendingUpdates = emptyList()) } + // Update the sort order before creating the UpdateSchema, because: + // 1. Deleting a column referenced by the sort order will cause + // SortOrder.checkCompatibility to throw ValidationException on commit. + // 2. UpdateSchema captures the table's metadata version at creation time. + // If we replace the sort order after creating it, the commit would fail + // with a stale metadata error. + val columnsBeingDeleted = buildList { + addAll(diff.removedColumns) + if (columnTypeChangeBehavior == ColumnTypeChangeBehavior.OVERWRITE) { + // In OVERWRITE mode, type-changed columns are deleted and re-added + // with new field IDs. The old sort field references become invalid. + addAll(diff.updatedDataTypes) + } + } + replaceSortOrderIfNeeded( + table = table, + columnsBeingDeleted = columnsBeingDeleted, + identifierFieldsChanged = diff.identifierFieldsChanged, + incomingIdentifierFieldNames = incomingSchema.identifierFieldNames(), + ) + val update: UpdateSchema = table.updateSchema().allowIncompatibleChanges() // 1) Remove columns that no longer exist in the incoming schema @@ -267,6 +292,90 @@ class IcebergTableSynchronizer( return SchemaUpdateResult(newSchema, pendingUpdates = listOf(update)) } } + + /** + * Update the table's sort order if it would conflict with pending schema changes. + * + * Sort orders are set at table creation from identifier fields (PKs) and never updated. This + * causes [org.apache.iceberg.exceptions.ValidationException] when schema evolution deletes a + * column referenced by the sort order. + * + * This method handles three cases: + * 1. Identifier fields changed → rebuild sort order from new identifiers (covers + * ``` + * Dedupe→Append, PK changes within Dedupe) + * ``` + * 2. Columns being deleted conflict with sort order → remove those fields + * 3. Neither → no-op + * + * Must be called BEFORE creating the [UpdateSchema], since this commits a metadata change and + * the subsequent UpdateSchema needs the refreshed metadata version. + */ + private fun replaceSortOrderIfNeeded( + table: Table, + columnsBeingDeleted: List, + identifierFieldsChanged: Boolean, + incomingIdentifierFieldNames: Set, + ) { + val currentSortOrder = table.sortOrder() + + // If the table has no sort order, there's nothing to conflict and nothing to update. + // (Append→Dedupe would need a sort order added, but that case requires a reset.) + if (currentSortOrder.isUnsorted) { + return + } + + if (identifierFieldsChanged) { + // Rebuild sort order from the new identifier fields. + // For Dedupe→Append: incoming identifiers are empty → unsorted. + // For PK changes within Dedupe: new identifiers → new sort order. + val builder = table.replaceSortOrder() + for (fieldName in incomingIdentifierFieldNames) { + // Only include fields that exist in the current schema. Fields being + // added in the same schema change can't be referenced yet. + if (table.schema().findField(fieldName) != null) { + builder.asc(fieldName) + } + } + logger.info { + "Replacing sort order due to identifier field change. " + + "New sort fields: ${incomingIdentifierFieldNames.ifEmpty { setOf("(unsorted)") }}" + } + builder.commit() + table.refresh() + return + } + + // No identifier change — check if any deleted columns conflict with the sort order. + if (columnsBeingDeleted.isEmpty()) { + return + } + + val schema = table.schema() + val fieldIdsBeingDeleted = + columnsBeingDeleted.mapNotNull { schema.findField(it)?.fieldId() }.toSet() + + val hasConflict = currentSortOrder.fields().any { it.sourceId() in fieldIdsBeingDeleted } + if (!hasConflict) { + return + } + + // Rebuild the sort order, keeping only fields that aren't being deleted. + val builder = table.replaceSortOrder() + for (sortField in currentSortOrder.fields()) { + if (sortField.sourceId() !in fieldIdsBeingDeleted) { + val fieldName = schema.findColumnName(sortField.sourceId()) + when (sortField.direction()) { + SortDirection.ASC -> builder.asc(fieldName, sortField.nullOrder()) + SortDirection.DESC -> builder.desc(fieldName, sortField.nullOrder()) + else -> builder.asc(fieldName, sortField.nullOrder()) + } + } + } + logger.info { "Replacing sort order to remove fields being deleted: $columnsBeingDeleted" } + builder.commit() + table.refresh() + } } data class SchemaUpdateResult(val schema: Schema, val pendingUpdates: List) diff --git a/airbyte-cdk/bulk/toolkits/load-iceberg-parquet/src/test/kotlin/io/airbyte/cdk/load/toolkits/iceberg/parquet/IcebergTableSynchronizerTest.kt b/airbyte-cdk/bulk/toolkits/load-iceberg-parquet/src/test/kotlin/io/airbyte/cdk/load/toolkits/iceberg/parquet/IcebergTableSynchronizerTest.kt index fe39cb577ee3..4d1ccecfdd84 100644 --- a/airbyte-cdk/bulk/toolkits/load-iceberg-parquet/src/test/kotlin/io/airbyte/cdk/load/toolkits/iceberg/parquet/IcebergTableSynchronizerTest.kt +++ b/airbyte-cdk/bulk/toolkits/load-iceberg-parquet/src/test/kotlin/io/airbyte/cdk/load/toolkits/iceberg/parquet/IcebergTableSynchronizerTest.kt @@ -12,9 +12,16 @@ import io.mockk.mockk import io.mockk.runs import io.mockk.spyk import io.mockk.verify +import java.nio.file.Files +import org.apache.hadoop.conf.Configuration +import org.apache.iceberg.FileFormat import org.apache.iceberg.Schema +import org.apache.iceberg.SortOrder import org.apache.iceberg.Table +import org.apache.iceberg.TableProperties.DEFAULT_FILE_FORMAT import org.apache.iceberg.UpdateSchema +import org.apache.iceberg.catalog.TableIdentifier +import org.apache.iceberg.hadoop.HadoopCatalog import org.apache.iceberg.types.Type.PrimitiveType import org.apache.iceberg.types.Types import org.assertj.core.api.Assertions.assertThat @@ -50,6 +57,9 @@ class IcebergTableSynchronizerTest { // By default, let table.schema() return an empty schema. Tests can override this as needed. every { mockTable.schema() } returns Schema(listOf()) + // By default, the table has no sort order. Tests using real tables handle this themselves. + every { mockTable.sortOrder() } returns SortOrder.unsorted() + // Table.updateSchema() should return the mock UpdateSchema every { mockTable.updateSchema().allowIncompatibleChanges() } returns mockUpdateSchema @@ -473,4 +483,275 @@ class IcebergTableSynchronizerTest { assertThat(pendingUpdates).hasSize(1) assertThat(pendingUpdates.first()).isSameAs(mockIdentifierUpdateSchema) } + + // ================================================================================== + // Sort order tests — use real HadoopCatalog tables (not mocks) because mocked tests + // never exercise Iceberg's SortOrder.checkCompatibility validation. + // ================================================================================== + + private fun createRealSynchronizer() = + IcebergTableSynchronizer( + IcebergTypesComparator(), + IcebergSuperTypeFinder(IcebergTypesComparator()), + ) + + /** Schema matching the customer's custom insight streams (Dedupe with 3 PKs). */ + private fun dedupeSchema() = + Schema( + listOf( + Types.NestedField.required(1, "_airbyte_raw_id", Types.StringType.get()), + Types.NestedField.required( + 2, + "_airbyte_extracted_at", + Types.TimestampType.withZone() + ), + Types.NestedField.required(3, "_airbyte_meta", Types.StringType.get()), + Types.NestedField.required(4, "_airbyte_generation_id", Types.LongType.get()), + Types.NestedField.required(5, "ad_id", Types.StringType.get()), + Types.NestedField.required(6, "date_start", Types.DateType.get()), + Types.NestedField.required(7, "account_id", Types.StringType.get()), + Types.NestedField.optional(8, "impressions", Types.LongType.get()), + ), + setOf(5, 6, 7), // identifier fields: ad_id, date_start, account_id + ) + + private fun dedupeSortOrder(schema: Schema): SortOrder = + SortOrder.builderFor(schema).asc("ad_id").asc("date_start").asc("account_id").build() + + private fun createTableWithSortOrder( + catalog: HadoopCatalog, + tableId: TableIdentifier, + schema: Schema, + sortOrder: SortOrder, + ): Table { + catalog.createNamespace(tableId.namespace()) + return catalog + .buildTable(tableId, schema) + .withProperty(DEFAULT_FILE_FORMAT, FileFormat.PARQUET.name.lowercase()) + .withSortOrder(sortOrder) + .create() + } + + private fun createTableWithoutSortOrder( + catalog: HadoopCatalog, + tableId: TableIdentifier, + schema: Schema, + ): Table { + catalog.createNamespace(tableId.namespace()) + return catalog + .buildTable(tableId, schema) + .withProperty(DEFAULT_FILE_FORMAT, FileFormat.PARQUET.name.lowercase()) + .create() + } + + /** + * Scenario A: Source upgrade removes a PK column (ad_id) that the sort order references. After + * fix: schema evolution should succeed and sort order should retain only the remaining PK + * columns. + */ + @Test + fun `scenario A - removing a sort-order column should update sort order and succeed`() { + val warehousePath = Files.createTempDirectory("iceberg-test-warehouse") + val catalog = HadoopCatalog(Configuration(), warehousePath.toString()) + val tableId = TableIdentifier.of("db", "scenario_a") + + val schema = dedupeSchema() + val table = createTableWithSortOrder(catalog, tableId, schema, dedupeSortOrder(schema)) + + // Incoming schema: ad_id removed, identifiers updated + val incomingSchema = + Schema( + listOf( + Types.NestedField.required(1, "_airbyte_raw_id", Types.StringType.get()), + Types.NestedField.required( + 2, + "_airbyte_extracted_at", + Types.TimestampType.withZone() + ), + Types.NestedField.required(3, "_airbyte_meta", Types.StringType.get()), + Types.NestedField.required(4, "_airbyte_generation_id", Types.LongType.get()), + // ad_id (field 5) removed + Types.NestedField.required(6, "date_start", Types.DateType.get()), + Types.NestedField.required(7, "account_id", Types.StringType.get()), + Types.NestedField.optional(8, "impressions", Types.LongType.get()), + ), + setOf(6, 7), // identifier fields: date_start, account_id + ) + + val synchronizer = createRealSynchronizer() + synchronizer.maybeApplySchemaChanges( + table, + incomingSchema, + ColumnTypeChangeBehavior.SAFE_SUPERTYPE, + ) + + // ad_id should be gone from the schema + table.refresh() + assertThat(table.schema().findField("ad_id")).isNull() + + // Sort order should have 2 remaining fields (date_start, account_id) + val updatedSortOrder = table.sortOrder() + assertThat(updatedSortOrder.fields()).hasSize(2) + assertThat(updatedSortOrder.fields().map { table.schema().findColumnName(it.sourceId()) }) + .containsExactly("date_start", "account_id") + + catalog.dropTable(tableId) + warehousePath.toFile().deleteRecursively() + } + + /** + * Scenario B: Stream switches from Dedupe to Append. Incoming schema has no identifier fields. + * The sort order should be cleared to unsorted. + */ + @Test + fun `scenario B - dedupe to append should clear sort order`() { + val warehousePath = Files.createTempDirectory("iceberg-test-warehouse") + val catalog = HadoopCatalog(Configuration(), warehousePath.toString()) + val tableId = TableIdentifier.of("db", "scenario_b") + + val schema = dedupeSchema() + val table = createTableWithSortOrder(catalog, tableId, schema, dedupeSortOrder(schema)) + + // Incoming schema: same columns but NO identifier fields (Append mode) + val incomingSchema = + Schema( + listOf( + Types.NestedField.required(1, "_airbyte_raw_id", Types.StringType.get()), + Types.NestedField.required( + 2, + "_airbyte_extracted_at", + Types.TimestampType.withZone() + ), + Types.NestedField.required(3, "_airbyte_meta", Types.StringType.get()), + Types.NestedField.required(4, "_airbyte_generation_id", Types.LongType.get()), + Types.NestedField.optional(5, "ad_id", Types.StringType.get()), + Types.NestedField.optional(6, "date_start", Types.DateType.get()), + Types.NestedField.optional(7, "account_id", Types.StringType.get()), + Types.NestedField.optional(8, "impressions", Types.LongType.get()), + ), + // No identifier fields — Append mode + ) + + val synchronizer = createRealSynchronizer() + synchronizer.maybeApplySchemaChanges( + table, + incomingSchema, + ColumnTypeChangeBehavior.SAFE_SUPERTYPE, + ) + + table.refresh() + assertThat(table.sortOrder().isUnsorted).isTrue() + + catalog.dropTable(tableId) + warehousePath.toFile().deleteRecursively() + } + + /** + * Scenario D (with column deletion): PKs change within Dedupe and the old PK column is also + * removed from the schema. Sort order should be updated to match new PKs, and the column + * deletion should succeed. + * + * This is the exact customer scenario: ad_id removed from both PKs and schema. + */ + @Test + fun `scenario D - pk change with column deletion should update sort order`() { + val warehousePath = Files.createTempDirectory("iceberg-test-warehouse") + val catalog = HadoopCatalog(Configuration(), warehousePath.toString()) + val tableId = TableIdentifier.of("db", "scenario_d_with_delete") + + val schema = dedupeSchema() + val table = createTableWithSortOrder(catalog, tableId, schema, dedupeSortOrder(schema)) + + // Incoming schema: ad_id removed from both columns and identifiers + val incomingSchema = + Schema( + listOf( + Types.NestedField.required(1, "_airbyte_raw_id", Types.StringType.get()), + Types.NestedField.required( + 2, + "_airbyte_extracted_at", + Types.TimestampType.withZone() + ), + Types.NestedField.required(3, "_airbyte_meta", Types.StringType.get()), + Types.NestedField.required(4, "_airbyte_generation_id", Types.LongType.get()), + // ad_id removed + Types.NestedField.required(6, "date_start", Types.DateType.get()), + Types.NestedField.required(7, "account_id", Types.StringType.get()), + Types.NestedField.optional(8, "impressions", Types.LongType.get()), + ), + setOf(6, 7), // identifier fields: date_start, account_id + ) + + val synchronizer = createRealSynchronizer() + synchronizer.maybeApplySchemaChanges( + table, + incomingSchema, + ColumnTypeChangeBehavior.SAFE_SUPERTYPE, + ) + + table.refresh() + assertThat(table.schema().findField("ad_id")).isNull() + + val updatedSortOrder = table.sortOrder() + assertThat(updatedSortOrder.fields()).hasSize(2) + assertThat(updatedSortOrder.fields().map { table.schema().findColumnName(it.sourceId()) }) + .containsExactly("date_start", "account_id") + + catalog.dropTable(tableId) + warehousePath.toFile().deleteRecursively() + } + + /** + * Scenario D (standalone): PKs change within Dedupe but the old PK column remains in the schema + * as a non-PK column. Sort order should be updated to match new PKs. + */ + @Test + fun `scenario D - pk change without column deletion should update sort order`() { + val warehousePath = Files.createTempDirectory("iceberg-test-warehouse") + val catalog = HadoopCatalog(Configuration(), warehousePath.toString()) + val tableId = TableIdentifier.of("db", "scenario_d_standalone") + + val schema = dedupeSchema() + val table = createTableWithSortOrder(catalog, tableId, schema, dedupeSortOrder(schema)) + + // Incoming schema: ad_id still present but no longer an identifier + val incomingSchema = + Schema( + listOf( + Types.NestedField.required(1, "_airbyte_raw_id", Types.StringType.get()), + Types.NestedField.required( + 2, + "_airbyte_extracted_at", + Types.TimestampType.withZone() + ), + Types.NestedField.required(3, "_airbyte_meta", Types.StringType.get()), + Types.NestedField.required(4, "_airbyte_generation_id", Types.LongType.get()), + Types.NestedField.optional(5, "ad_id", Types.StringType.get()), + Types.NestedField.required(6, "date_start", Types.DateType.get()), + Types.NestedField.required(7, "account_id", Types.StringType.get()), + Types.NestedField.optional(8, "impressions", Types.LongType.get()), + ), + setOf(6, 7), // identifier fields: date_start, account_id (ad_id removed from PKs) + ) + + val synchronizer = createRealSynchronizer() + synchronizer.maybeApplySchemaChanges( + table, + incomingSchema, + ColumnTypeChangeBehavior.SAFE_SUPERTYPE, + ) + + table.refresh() + // ad_id should still exist as a column + assertThat(table.schema().findField("ad_id")).isNotNull() + + // Sort order should reflect new PKs only + val updatedSortOrder = table.sortOrder() + assertThat(updatedSortOrder.fields()).hasSize(2) + assertThat(updatedSortOrder.fields().map { table.schema().findColumnName(it.sourceId()) }) + .containsExactly("date_start", "account_id") + + catalog.dropTable(tableId) + warehousePath.toFile().deleteRecursively() + } } From 649a6c964272d3852059362ce5697116f151aa02 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 13:08:59 -0700 Subject: [PATCH 040/379] fix(source-google-search-console): guard numeric fields against complex types (AI-Triage PR) (#75426) Co-authored-by: bot_apk Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: suisuixia42 --- .../components.py | 33 ++++ .../manifest.yaml | 26 +++ .../metadata.yaml | 2 +- .../unit_tests/test_components.py | 94 +++++++++++ .../sources/google-search-console.md | 156 +++++++++--------- 5 files changed, 232 insertions(+), 79 deletions(-) diff --git a/airbyte-integrations/connectors/source-google-search-console/components.py b/airbyte-integrations/connectors/source-google-search-console/components.py index d304b5f4e09e..082b64ccd227 100644 --- a/airbyte-integrations/connectors/source-google-search-console/components.py +++ b/airbyte-integrations/connectors/source-google-search-console/components.py @@ -2,6 +2,7 @@ # Copyright (c) 2025 Airbyte, Inc., all rights reserved. # +import logging from dataclasses import dataclass, field from typing import Any, Dict, List, Mapping, Optional @@ -11,6 +12,9 @@ from airbyte_cdk.sources.types import Config, StreamSlice, StreamState +logger = logging.getLogger("airbyte") + + @dataclass class NestedSubstreamStateMigration(StateMigration): """ @@ -132,6 +136,35 @@ def transform( record.pop("keys") +@dataclass +class SanitizeNumericFields(RecordTransformation): + """ + Ensures numeric metric fields are JSON-serializable by guarding against non-standard + Python numeric types (e.g., complex) that can cause serialization failures and deadlocks + in the concurrent read pipeline. + + See: https://github.com/airbytehq/airbyte/issues/74883 + """ + + NUMERIC_FIELDS = ("clicks", "impressions", "ctr", "position") + + def transform( + self, + record: Dict[str, Any], + config: Optional[Config] = None, + stream_state: Optional[StreamState] = None, + stream_slice: Optional[StreamSlice] = None, + ) -> None: + for field_name in self.NUMERIC_FIELDS: + value = record.get(field_name) + if value is not None and isinstance(value, complex): + logger.warning( + "Complex value encountered for field '%s'. Using real component only.", + field_name, + ) + record[field_name] = value.real + + @dataclass class CustomReportSchemaLoader(SchemaLoader): """ diff --git a/airbyte-integrations/connectors/source-google-search-console/manifest.yaml b/airbyte-integrations/connectors/source-google-search-console/manifest.yaml index 8ad21d294b37..673d198a3f47 100644 --- a/airbyte-integrations/connectors/source-google-search-console/manifest.yaml +++ b/airbyte-integrations/connectors/source-google-search-console/manifest.yaml @@ -486,6 +486,8 @@ definitions: value: "{{ record['query'] }}" value_type: string condition: "{{ record.get('query', False) }}" + - type: CustomTransformation + class_name: source_declarative_manifest.components.SanitizeNumericFields schema_loader: type: InlineSchemaLoader schema: @@ -536,6 +538,8 @@ definitions: - type: RemoveFields field_pointers: - - keys + - type: CustomTransformation + class_name: source_declarative_manifest.components.SanitizeNumericFields schema_loader: type: InlineSchemaLoader schema: @@ -577,6 +581,8 @@ definitions: - type: RemoveFields field_pointers: - - keys + - type: CustomTransformation + class_name: source_declarative_manifest.components.SanitizeNumericFields schema_loader: type: InlineSchemaLoader schema: @@ -625,6 +631,8 @@ definitions: - type: RemoveFields field_pointers: - - keys + - type: CustomTransformation + class_name: source_declarative_manifest.components.SanitizeNumericFields schema_loader: type: InlineSchemaLoader schema: @@ -669,6 +677,8 @@ definitions: - type: RemoveFields field_pointers: - - keys + - type: CustomTransformation + class_name: source_declarative_manifest.components.SanitizeNumericFields schema_loader: type: InlineSchemaLoader schema: @@ -727,6 +737,8 @@ definitions: value: "{{ record['query'] }}" value_type: string condition: "{{ record.get('query', False) }}" + - type: CustomTransformation + class_name: source_declarative_manifest.components.SanitizeNumericFields schema_loader: type: InlineSchemaLoader schema: @@ -778,6 +790,8 @@ definitions: - type: RemoveFields field_pointers: - - keys + - type: CustomTransformation + class_name: source_declarative_manifest.components.SanitizeNumericFields schema_loader: type: InlineSchemaLoader schema: @@ -827,6 +841,8 @@ definitions: - type: RemoveFields field_pointers: - - keys + - type: CustomTransformation + class_name: source_declarative_manifest.components.SanitizeNumericFields schema_loader: type: InlineSchemaLoader schema: @@ -876,6 +892,8 @@ definitions: - type: RemoveFields field_pointers: - - keys + - type: CustomTransformation + class_name: source_declarative_manifest.components.SanitizeNumericFields schema_loader: type: InlineSchemaLoader schema: @@ -1116,6 +1134,8 @@ definitions: - type: RemoveFields field_pointers: - - keys + - type: CustomTransformation + class_name: source_declarative_manifest.components.SanitizeNumericFields schema_loader: type: InlineSchemaLoader schema: @@ -1165,6 +1185,8 @@ definitions: - type: RemoveFields field_pointers: - - keys + - type: CustomTransformation + class_name: source_declarative_manifest.components.SanitizeNumericFields schema_loader: type: InlineSchemaLoader schema: @@ -1213,6 +1235,8 @@ definitions: - type: RemoveFields field_pointers: - - keys + - type: CustomTransformation + class_name: source_declarative_manifest.components.SanitizeNumericFields schema_loader: type: InlineSchemaLoader schema: @@ -1331,6 +1355,8 @@ dynamic_streams: dimensions: # This will be replaced by the dimensions of the custom report - date - country + - type: CustomTransformation + class_name: source_declarative_manifest.components.SanitizeNumericFields schema_loader: type: CustomSchemaLoader class_name: source_declarative_manifest.components.CustomReportSchemaLoader diff --git a/airbyte-integrations/connectors/source-google-search-console/metadata.yaml b/airbyte-integrations/connectors/source-google-search-console/metadata.yaml index 3f4a5554fc33..00bfe7142b39 100644 --- a/airbyte-integrations/connectors/source-google-search-console/metadata.yaml +++ b/airbyte-integrations/connectors/source-google-search-console/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: api connectorType: source definitionId: eb4c9e00-db83-4d63-a386-39cfa91012a8 - dockerImageTag: 1.10.26 + dockerImageTag: 1.10.27 dockerRepository: airbyte/source-google-search-console documentationUrl: https://docs.airbyte.com/integrations/sources/google-search-console externalDocumentationUrls: diff --git a/airbyte-integrations/connectors/source-google-search-console/unit_tests/test_components.py b/airbyte-integrations/connectors/source-google-search-console/unit_tests/test_components.py index 6d151b453980..62ce86d75511 100644 --- a/airbyte-integrations/connectors/source-google-search-console/unit_tests/test_components.py +++ b/airbyte-integrations/connectors/source-google-search-console/unit_tests/test_components.py @@ -1,5 +1,7 @@ # Copyright (c) 2025 Airbyte, Inc., all rights reserved. +import logging + import pytest @@ -111,3 +113,95 @@ def test_custom_report_schema_loader(components_module): actual_schema = schema_loader.get_json_schema() assert actual_schema == expected_schema + + +class TestSanitizeNumericFields: + """Tests for the SanitizeNumericFields transformation.""" + + def test_complex_values_are_sanitized(self, components_module): + """Complex values in numeric fields should be replaced with their real component.""" + component = components_module.SanitizeNumericFields() + record = { + "clicks": complex(42, 0), + "impressions": complex(100, 0), + "ctr": complex(0.0423, 0), + "position": complex(3.7, 0), + "site_url": "https://example.com", + } + component.transform(record=record) + + assert record["clicks"] == 42.0 + assert record["impressions"] == 100.0 + assert record["ctr"] == 0.0423 + assert record["position"] == 3.7 + assert isinstance(record["clicks"], float) + assert isinstance(record["ctr"], float) + # Non-numeric fields should be untouched + assert record["site_url"] == "https://example.com" + + def test_normal_values_are_not_modified(self, components_module): + """Regular int/float values should pass through unchanged.""" + component = components_module.SanitizeNumericFields() + record = { + "clicks": 10, + "impressions": 500, + "ctr": 0.02, + "position": 4.5, + } + component.transform(record=record) + + assert record["clicks"] == 10 + assert record["impressions"] == 500 + assert record["ctr"] == 0.02 + assert record["position"] == 4.5 + + def test_none_values_are_not_modified(self, components_module): + """None values in numeric fields should not be touched.""" + component = components_module.SanitizeNumericFields() + record = { + "clicks": None, + "impressions": None, + "ctr": None, + "position": None, + } + component.transform(record=record) + + assert record["clicks"] is None + assert record["impressions"] is None + assert record["ctr"] is None + assert record["position"] is None + + def test_missing_fields_are_ignored(self, components_module): + """Records without numeric metric fields should not raise errors.""" + component = components_module.SanitizeNumericFields() + record = {"site_url": "https://example.com", "search_type": "web"} + component.transform(record=record) + + assert record == {"site_url": "https://example.com", "search_type": "web"} + + def test_complex_with_nonzero_imaginary_uses_real(self, components_module): + """Even if the imaginary part is nonzero, only the real part should be extracted.""" + component = components_module.SanitizeNumericFields() + record = { + "clicks": complex(5, 3), + "impressions": 100, + "ctr": complex(0.05, 0.01), + "position": 2.0, + } + component.transform(record=record) + + assert record["clicks"] == 5.0 + assert record["ctr"] == 0.05 + # Non-complex fields remain unchanged + assert record["impressions"] == 100 + assert record["position"] == 2.0 + + def test_warning_logged_for_complex_values(self, components_module, caplog): + """A warning should be logged when a complex value is encountered.""" + component = components_module.SanitizeNumericFields() + record = {"clicks": complex(42, 0), "impressions": 100, "ctr": 0.5, "position": 1.0} + + with caplog.at_level(logging.WARNING, logger="airbyte"): + component.transform(record=record) + + assert any("Complex value encountered for field 'clicks'" in msg for msg in caplog.messages) diff --git a/docs/integrations/sources/google-search-console.md b/docs/integrations/sources/google-search-console.md index 3d9f65dba6a4..ee93f76c30e6 100644 --- a/docs/integrations/sources/google-search-console.md +++ b/docs/integrations/sources/google-search-console.md @@ -242,6 +242,7 @@ Google Search Console only retains data for websites from the last 16 months. An | Version | Date | Pull Request | Subject | |:------------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 1.10.27 | 2026-03-24 | [75426](https://github.com/airbytehq/airbyte/pull/75426) | Guard numeric metric fields against complex types to prevent serialization failures and deadlocks | | 1.10.26 | 2026-03-24 | [74935](https://github.com/airbytehq/airbyte/pull/74935) | Update dependencies | | 1.10.25 | 2026-03-10 | [74685](https://github.com/airbytehq/airbyte/pull/74685) | Update dependencies | | 1.10.24 | 2026-02-24 | [73935](https://github.com/airbytehq/airbyte/pull/73935) | Update dependencies | @@ -273,84 +274,83 @@ Google Search Console only retains data for websites from the last 16 months. An | 1.9.3 | 2025-06-18 | [61706](https://github.com/airbytehq/airbyte/pull/61706) | Fix record serialization bug | | 1.9.2 | 2025-06-14 | [60663](https://github.com/airbytehq/airbyte/pull/60663) | Update dependencies | | 1.9.1 | 2025-06-10 | [61514](https://github.com/airbytehq/airbyte/pull/61514) | Promoting release candidate 1.9.1-rc.1 to a main version. | -| 1.9.1-rc.1 | 2025-06-10 | [61508](https://github.com/airbytehq/airbyte/pull/61508) | Add API budget, reduce concurrency levels, and catch 403 rate limiting errors | -| 1.9.0 | 2025-06-06 | [61408](https://github.com/airbytehq/airbyte/pull/61408) | Migrate custom reports streams to low-code | -| 1.8.0 | 2025-06-06 | [61335](https://github.com/airbytehq/airbyte/pull/61335) | Migrate `SearchAnalyticsAllFields`, `SearchAnalyticsByDate`, `SearchAnalyticsByDevice`, `SearchAnalyticsByPage`, and `SearchAnalyticsByQuery` to low-code | -| 1.7.0 | 2025-06-05 | [61332](https://github.com/airbytehq/airbyte/pull/61332) | Migrate search_by_keyword streams to low-code | -| 1.6.0 | 2025-06-04 | [61380](https://github.com/airbytehq/airbyte/pull/61380) | Promoting release candidate 1.6.0-rc.1 to a main version. | -| 1.6.0-rc.1 | 2025-06-02 | [60928](https://github.com/airbytehq/airbyte/pull/60928) | Migrate `search_analytics_by_country`, `sites`, and `sitemaps` to low-code | -| 1.5.18 | 2025-05-28 | [58121](https://github.com/airbytehq/airbyte/pull/58121) | Prevent KeyError raise on check connetion when account does not have access to any site. Better Error message | -| 1.5.17 | 2025-05-10 | [54946](https://github.com/airbytehq/airbyte/pull/54946) | Update dependencies | -| 1.5.16 | 2025-05-09 | [59737](https://github.com/airbytehq/airbyte/pull/59737) | Promoting release candidate 1.5.16-rc.1 to a main version. | -| 1.5.16-rc.1 | 2025-05-02 | [59140](https://github.com/airbytehq/airbyte/pull/59140) | Migrate to CDK V6 | -| 1.5.15 | 2025-02-22 | [54426](https://github.com/airbytehq/airbyte/pull/54426) | Update dependencies | -| 1.5.14 | 2025-02-15 | [53781](https://github.com/airbytehq/airbyte/pull/53781) | Update dependencies | -| 1.5.13 | 2025-02-01 | [52854](https://github.com/airbytehq/airbyte/pull/52854) | Update dependencies | -| 1.5.12 | 2025-01-25 | [52303](https://github.com/airbytehq/airbyte/pull/52303) | Update dependencies | -| 1.5.11 | 2025-01-18 | [51629](https://github.com/airbytehq/airbyte/pull/51629) | Update dependencies | -| 1.5.10 | 2025-01-11 | [51129](https://github.com/airbytehq/airbyte/pull/51129) | Update dependencies | -| 1.5.9 | 2025-01-04 | [50919](https://github.com/airbytehq/airbyte/pull/50919) | Update dependencies | -| 1.5.8 | 2024-12-28 | [50579](https://github.com/airbytehq/airbyte/pull/50579) | Update dependencies | -| 1.5.7 | 2024-12-21 | [50040](https://github.com/airbytehq/airbyte/pull/50040) | Update dependencies | -| 1.5.6 | 2024-12-14 | [49173](https://github.com/airbytehq/airbyte/pull/49173) | Update dependencies | -| 1.5.5 | 2024-11-25 | [43730](https://github.com/airbytehq/airbyte/pull/43730) | Starting with this version, the Docker image is now rootless. Please note that this and future versions will not be compatible with Airbyte versions earlier than 0.64 | -| 1.5.4 | 2024-09-06 | [45196](https://github.com/airbytehq/airbyte/pull/45196) | Fix request body for report streams by keyword | -| 1.5.3 | 2024-08-03 | [43067](https://github.com/airbytehq/airbyte/pull/43067) | Update dependencies | -| 1.5.2 | 2024-07-27 | [42786](https://github.com/airbytehq/airbyte/pull/42786) | Update dependencies | -| 1.5.1 | 2024-07-20 | [42142](https://github.com/airbytehq/airbyte/pull/42142) | Update dependencies | -| 1.5.0 | 2024-07-17 | [42073](https://github.com/airbytehq/airbyte/pull/42073) | Migrate to CDK v1.8.0 | -| 1.4.13 | 2024-07-13 | [41734](https://github.com/airbytehq/airbyte/pull/41734) | Update dependencies | -| 1.4.12 | 2024-07-10 | [41440](https://github.com/airbytehq/airbyte/pull/41440) | Update dependencies | -| 1.4.11 | 2024-07-09 | [41164](https://github.com/airbytehq/airbyte/pull/41164) | Update dependencies | -| 1.4.10 | 2024-07-06 | [40981](https://github.com/airbytehq/airbyte/pull/40981) | Update dependencies | -| 1.4.9 | 2024-06-27 | [40215](https://github.com/airbytehq/airbyte/pull/40215) | Replaced deprecated AirbyteLogger with logging.Logger | -| 1.4.8 | 2024-06-26 | [40532](https://github.com/airbytehq/airbyte/pull/40532) | Update dependencies | -| 1.4.7 | 2024-06-25 | [40312](https://github.com/airbytehq/airbyte/pull/40312) | Update dependencies | -| 1.4.6 | 2024-06-22 | [40077](https://github.com/airbytehq/airbyte/pull/40077) | Update dependencies | -| 1.4.5 | 2024-06-17 | [39516](https://github.com/airbytehq/airbyte/pull/39516) | Update state handling for incremental streams | -| 1.4.4 | 2024-06-04 | [39059](https://github.com/airbytehq/airbyte/pull/39059) | [autopull] Upgrade base image to v1.2.1 | -| 1.4.3 | 2024-05-24 | [38649](https://github.com/airbytehq/airbyte/pull/38649) | Update deprecated auth package | -| 1.4.2 | 2024-04-19 | [36639](https://github.com/airbytehq/airbyte/pull/36639) | Updating to 0.80.0 CDK | -| 1.4.1 | 2024-04-12 | [36639](https://github.com/airbytehq/airbyte/pull/36639) | Schema descriptions | -| 1.4.0 | 2024-03-19 | [36267](https://github.com/airbytehq/airbyte/pull/36267) | Pin airbyte-cdk version to `^0` | -| 1.3.7 | 2024-02-12 | [35163](https://github.com/airbytehq/airbyte/pull/35163) | Manage dependencies with Poetry | -| 1.3.6 | 2023-10-26 | [31863](https://github.com/airbytehq/airbyte/pull/31863) | Base image migration: remove Dockerfile and use the python-connector-base image | -| 1.3.5 | 2023-09-28 | [30822](https://github.com/airbytehq/airbyte/pull/30822) | Fix primary key for custom reports | -| 1.3.4 | 2023-09-27 | [30785](https://github.com/airbytehq/airbyte/pull/30785) | Do not migrate config for the newly created connections | -| 1.3.3 | 2023-08-29 | [29941](https://github.com/airbytehq/airbyte/pull/29941) | Added `primary key` to each stream, added `custom_report` config migration | -| 1.3.2 | 2023-08-25 | [29829](https://github.com/airbytehq/airbyte/pull/29829) | Make `Start Date` a non-required, added the `suggested streams`, corrected public docs | -| 1.3.1 | 2023-08-24 | [29329](https://github.com/airbytehq/airbyte/pull/29329) | Update tooltip descriptions | -| 1.3.0 | 2023-08-24 | [29750](https://github.com/airbytehq/airbyte/pull/29750) | Add new `Keyword-Site-Report-By-Site` stream | -| 1.2.2 | 2023-08-23 | [29741](https://github.com/airbytehq/airbyte/pull/29741) | Handle `HTTP-401`, `HTTP-403` errors | -| 1.2.1 | 2023-07-04 | [27952](https://github.com/airbytehq/airbyte/pull/27952) | Removed deprecated `searchType`, added `discover`(Discover results) and `googleNews`(Results from news.google.com, etc.) types | -| 1.2.0 | 2023-06-29 | [27831](https://github.com/airbytehq/airbyte/pull/27831) | Add new streams | -| 1.1.0 | 2023-06-26 | [27738](https://github.com/airbytehq/airbyte/pull/27738) | License Update: Elv2 | -| 1.0.2 | 2023-06-13 | [27307](https://github.com/airbytehq/airbyte/pull/27307) | Fix `data_state` config typo | -| 1.0.1 | 2023-05-30 | [26746](https://github.com/airbytehq/airbyte/pull/26746) | Remove `authSpecification` from connector spec in favour of advancedAuth | -| 1.0.0 | 2023-05-24 | [26452](https://github.com/airbytehq/airbyte/pull/26452) | Add data_state parameter to specification | -| 0.1.22 | 2023-03-20 | [22295](https://github.com/airbytehq/airbyte/pull/22295) | Update specification examples | -| 0.1.21 | 2023-02-14 | [22984](https://github.com/airbytehq/airbyte/pull/22984) | Specified date formatting in specification | -| 0.1.20 | 2023-02-02 | [22334](https://github.com/airbytehq/airbyte/pull/22334) | Turn on default HttpAvailabilityStrategy | -| 0.1.19 | 2023-01-27 | [22007](https://github.com/airbytehq/airbyte/pull/22007) | Set `AvailabilityStrategy` for streams explicitly to `None` | -| 0.1.18 | 2022-10-27 | [18568](https://github.com/airbytehq/airbyte/pull/18568) | Improved config validation: custom_reports.dimension | -| 0.1.17 | 2022-10-08 | [17751](https://github.com/airbytehq/airbyte/pull/17751) | Improved config validation: start_date, end_date, site_urls | -| 0.1.16 | 2022-09-28 | [17304](https://github.com/airbytehq/airbyte/pull/17304) | Migrate to per-stream state. | -| 0.1.15 | 2022-09-16 | [16819](https://github.com/airbytehq/airbyte/pull/16819) | Check available site urls to avoid 403 error on sync | -| 0.1.14 | 2022-09-08 | [16433](https://github.com/airbytehq/airbyte/pull/16433) | Add custom analytics stream. | -| 0.1.13 | 2022-07-21 | [14924](https://github.com/airbytehq/airbyte/pull/14924) | Remove `additionalProperties` field from specs | -| 0.1.12 | 2022-05-04 | [12482](https://github.com/airbytehq/airbyte/pull/12482) | Update input configuration copy | -| 0.1.11 | 2022-01-05 | [9186](https://github.com/airbytehq/airbyte/pull/9186) | Fix incremental sync: keep all urls in state object | -| 0.1.10 | 2021-12-23 | [9073](https://github.com/airbytehq/airbyte/pull/9073) | Add slicing by date range | -| 0.1.9 | 2021-12-22 | [9047](https://github.com/airbytehq/airbyte/pull/9047) | Add 'order' to spec.json props | -| 0.1.8 | 2021-12-21 | [8248](https://github.com/airbytehq/airbyte/pull/8248) | Enable Sentry for performance and errors tracking | -| 0.1.7 | 2021-11-26 | [7431](https://github.com/airbytehq/airbyte/pull/7431) | Add default `end_date` param value | -| 0.1.6 | 2021-09-27 | [6460](https://github.com/airbytehq/airbyte/pull/6460) | Update OAuth Spec File | -| 0.1.4 | 2021-09-23 | [6394](https://github.com/airbytehq/airbyte/pull/6394) | Update Doc link Spec File | -| 0.1.3 | 2021-09-23 | [6405](https://github.com/airbytehq/airbyte/pull/6405) | Correct Spec File | -| 0.1.2 | 2021-09-17 | [6222](https://github.com/airbytehq/airbyte/pull/6222) | Correct Spec File | -| 0.1.1 | 2021-09-22 | [6315](https://github.com/airbytehq/airbyte/pull/6315) | Verify access to all sites when performing connection check | -| 0.1.0 | 2021-09-03 | [5350](https://github.com/airbytehq/airbyte/pull/5350) | Initial Release | ->>>>>>> master +| 1.9.1-rc.1 | 2025-06-10 | [61508](https://github.com/airbytehq/airbyte/pull/61508) | Add API budget, reduce concurrency levels, and catch 403 rate limiting errors | +| 1.9.0 | 2025-06-06 | [61408](https://github.com/airbytehq/airbyte/pull/61408) | Migrate custom reports streams to low-code | +| 1.8.0 | 2025-06-06 | [61335](https://github.com/airbytehq/airbyte/pull/61335) | Migrate `SearchAnalyticsAllFields`, `SearchAnalyticsByDate`, `SearchAnalyticsByDevice`, `SearchAnalyticsByPage`, and `SearchAnalyticsByQuery` to low-code | +| 1.7.0 | 2025-06-05 | [61332](https://github.com/airbytehq/airbyte/pull/61332) | Migrate search_by_keyword streams to low-code | +| 1.6.0 | 2025-06-04 | [61380](https://github.com/airbytehq/airbyte/pull/61380) | Promoting release candidate 1.6.0-rc.1 to a main version. | +| 1.6.0-rc.1 | 2025-06-02 | [60928](https://github.com/airbytehq/airbyte/pull/60928) | Migrate `search_analytics_by_country`, `sites`, and `sitemaps` to low-code | +| 1.5.18 | 2025-05-28 | [58121](https://github.com/airbytehq/airbyte/pull/58121) | Prevent KeyError raise on check connetion when account does not have access to any site. Better Error message | +| 1.5.17 | 2025-05-10 | [54946](https://github.com/airbytehq/airbyte/pull/54946) | Update dependencies | +| 1.5.16 | 2025-05-09 | [59737](https://github.com/airbytehq/airbyte/pull/59737) | Promoting release candidate 1.5.16-rc.1 to a main version. | +| 1.5.16-rc.1 | 2025-05-02 | [59140](https://github.com/airbytehq/airbyte/pull/59140) | Migrate to CDK V6 | +| 1.5.15 | 2025-02-22 | [54426](https://github.com/airbytehq/airbyte/pull/54426) | Update dependencies | +| 1.5.14 | 2025-02-15 | [53781](https://github.com/airbytehq/airbyte/pull/53781) | Update dependencies | +| 1.5.13 | 2025-02-01 | [52854](https://github.com/airbytehq/airbyte/pull/52854) | Update dependencies | +| 1.5.12 | 2025-01-25 | [52303](https://github.com/airbytehq/airbyte/pull/52303) | Update dependencies | +| 1.5.11 | 2025-01-18 | [51629](https://github.com/airbytehq/airbyte/pull/51629) | Update dependencies | +| 1.5.10 | 2025-01-11 | [51129](https://github.com/airbytehq/airbyte/pull/51129) | Update dependencies | +| 1.5.9 | 2025-01-04 | [50919](https://github.com/airbytehq/airbyte/pull/50919) | Update dependencies | +| 1.5.8 | 2024-12-28 | [50579](https://github.com/airbytehq/airbyte/pull/50579) | Update dependencies | +| 1.5.7 | 2024-12-21 | [50040](https://github.com/airbytehq/airbyte/pull/50040) | Update dependencies | +| 1.5.6 | 2024-12-14 | [49173](https://github.com/airbytehq/airbyte/pull/49173) | Update dependencies | +| 1.5.5 | 2024-11-25 | [43730](https://github.com/airbytehq/airbyte/pull/43730) | Starting with this version, the Docker image is now rootless. Please note that this and future versions will not be compatible with Airbyte versions earlier than 0.64 | +| 1.5.4 | 2024-09-06 | [45196](https://github.com/airbytehq/airbyte/pull/45196) | Fix request body for report streams by keyword | +| 1.5.3 | 2024-08-03 | [43067](https://github.com/airbytehq/airbyte/pull/43067) | Update dependencies | +| 1.5.2 | 2024-07-27 | [42786](https://github.com/airbytehq/airbyte/pull/42786) | Update dependencies | +| 1.5.1 | 2024-07-20 | [42142](https://github.com/airbytehq/airbyte/pull/42142) | Update dependencies | +| 1.5.0 | 2024-07-17 | [42073](https://github.com/airbytehq/airbyte/pull/42073) | Migrate to CDK v1.8.0 | +| 1.4.13 | 2024-07-13 | [41734](https://github.com/airbytehq/airbyte/pull/41734) | Update dependencies | +| 1.4.12 | 2024-07-10 | [41440](https://github.com/airbytehq/airbyte/pull/41440) | Update dependencies | +| 1.4.11 | 2024-07-09 | [41164](https://github.com/airbytehq/airbyte/pull/41164) | Update dependencies | +| 1.4.10 | 2024-07-06 | [40981](https://github.com/airbytehq/airbyte/pull/40981) | Update dependencies | +| 1.4.9 | 2024-06-27 | [40215](https://github.com/airbytehq/airbyte/pull/40215) | Replaced deprecated AirbyteLogger with logging.Logger | +| 1.4.8 | 2024-06-26 | [40532](https://github.com/airbytehq/airbyte/pull/40532) | Update dependencies | +| 1.4.7 | 2024-06-25 | [40312](https://github.com/airbytehq/airbyte/pull/40312) | Update dependencies | +| 1.4.6 | 2024-06-22 | [40077](https://github.com/airbytehq/airbyte/pull/40077) | Update dependencies | +| 1.4.5 | 2024-06-17 | [39516](https://github.com/airbytehq/airbyte/pull/39516) | Update state handling for incremental streams | +| 1.4.4 | 2024-06-04 | [39059](https://github.com/airbytehq/airbyte/pull/39059) | [autopull] Upgrade base image to v1.2.1 | +| 1.4.3 | 2024-05-24 | [38649](https://github.com/airbytehq/airbyte/pull/38649) | Update deprecated auth package | +| 1.4.2 | 2024-04-19 | [36639](https://github.com/airbytehq/airbyte/pull/36639) | Updating to 0.80.0 CDK | +| 1.4.1 | 2024-04-12 | [36639](https://github.com/airbytehq/airbyte/pull/36639) | Schema descriptions | +| 1.4.0 | 2024-03-19 | [36267](https://github.com/airbytehq/airbyte/pull/36267) | Pin airbyte-cdk version to `^0` | +| 1.3.7 | 2024-02-12 | [35163](https://github.com/airbytehq/airbyte/pull/35163) | Manage dependencies with Poetry | +| 1.3.6 | 2023-10-26 | [31863](https://github.com/airbytehq/airbyte/pull/31863) | Base image migration: remove Dockerfile and use the python-connector-base image | +| 1.3.5 | 2023-09-28 | [30822](https://github.com/airbytehq/airbyte/pull/30822) | Fix primary key for custom reports | +| 1.3.4 | 2023-09-27 | [30785](https://github.com/airbytehq/airbyte/pull/30785) | Do not migrate config for the newly created connections | +| 1.3.3 | 2023-08-29 | [29941](https://github.com/airbytehq/airbyte/pull/29941) | Added `primary key` to each stream, added `custom_report` config migration | +| 1.3.2 | 2023-08-25 | [29829](https://github.com/airbytehq/airbyte/pull/29829) | Make `Start Date` a non-required, added the `suggested streams`, corrected public docs | +| 1.3.1 | 2023-08-24 | [29329](https://github.com/airbytehq/airbyte/pull/29329) | Update tooltip descriptions | +| 1.3.0 | 2023-08-24 | [29750](https://github.com/airbytehq/airbyte/pull/29750) | Add new `Keyword-Site-Report-By-Site` stream | +| 1.2.2 | 2023-08-23 | [29741](https://github.com/airbytehq/airbyte/pull/29741) | Handle `HTTP-401`, `HTTP-403` errors | +| 1.2.1 | 2023-07-04 | [27952](https://github.com/airbytehq/airbyte/pull/27952) | Removed deprecated `searchType`, added `discover`(Discover results) and `googleNews`(Results from news.google.com, etc.) types | +| 1.2.0 | 2023-06-29 | [27831](https://github.com/airbytehq/airbyte/pull/27831) | Add new streams | +| 1.1.0 | 2023-06-26 | [27738](https://github.com/airbytehq/airbyte/pull/27738) | License Update: Elv2 | +| 1.0.2 | 2023-06-13 | [27307](https://github.com/airbytehq/airbyte/pull/27307) | Fix `data_state` config typo | +| 1.0.1 | 2023-05-30 | [26746](https://github.com/airbytehq/airbyte/pull/26746) | Remove `authSpecification` from connector spec in favour of advancedAuth | +| 1.0.0 | 2023-05-24 | [26452](https://github.com/airbytehq/airbyte/pull/26452) | Add data_state parameter to specification | +| 0.1.22 | 2023-03-20 | [22295](https://github.com/airbytehq/airbyte/pull/22295) | Update specification examples | +| 0.1.21 | 2023-02-14 | [22984](https://github.com/airbytehq/airbyte/pull/22984) | Specified date formatting in specification | +| 0.1.20 | 2023-02-02 | [22334](https://github.com/airbytehq/airbyte/pull/22334) | Turn on default HttpAvailabilityStrategy | +| 0.1.19 | 2023-01-27 | [22007](https://github.com/airbytehq/airbyte/pull/22007) | Set `AvailabilityStrategy` for streams explicitly to `None` | +| 0.1.18 | 2022-10-27 | [18568](https://github.com/airbytehq/airbyte/pull/18568) | Improved config validation: custom_reports.dimension | +| 0.1.17 | 2022-10-08 | [17751](https://github.com/airbytehq/airbyte/pull/17751) | Improved config validation: start_date, end_date, site_urls | +| 0.1.16 | 2022-09-28 | [17304](https://github.com/airbytehq/airbyte/pull/17304) | Migrate to per-stream state. | +| 0.1.15 | 2022-09-16 | [16819](https://github.com/airbytehq/airbyte/pull/16819) | Check available site urls to avoid 403 error on sync | +| 0.1.14 | 2022-09-08 | [16433](https://github.com/airbytehq/airbyte/pull/16433) | Add custom analytics stream. | +| 0.1.13 | 2022-07-21 | [14924](https://github.com/airbytehq/airbyte/pull/14924) | Remove `additionalProperties` field from specs | +| 0.1.12 | 2022-05-04 | [12482](https://github.com/airbytehq/airbyte/pull/12482) | Update input configuration copy | +| 0.1.11 | 2022-01-05 | [9186](https://github.com/airbytehq/airbyte/pull/9186) | Fix incremental sync: keep all urls in state object | +| 0.1.10 | 2021-12-23 | [9073](https://github.com/airbytehq/airbyte/pull/9073) | Add slicing by date range | +| 0.1.9 | 2021-12-22 | [9047](https://github.com/airbytehq/airbyte/pull/9047) | Add 'order' to spec.json props | +| 0.1.8 | 2021-12-21 | [8248](https://github.com/airbytehq/airbyte/pull/8248) | Enable Sentry for performance and errors tracking | +| 0.1.7 | 2021-11-26 | [7431](https://github.com/airbytehq/airbyte/pull/7431) | Add default `end_date` param value | +| 0.1.6 | 2021-09-27 | [6460](https://github.com/airbytehq/airbyte/pull/6460) | Update OAuth Spec File | +| 0.1.4 | 2021-09-23 | [6394](https://github.com/airbytehq/airbyte/pull/6394) | Update Doc link Spec File | +| 0.1.3 | 2021-09-23 | [6405](https://github.com/airbytehq/airbyte/pull/6405) | Correct Spec File | +| 0.1.2 | 2021-09-17 | [6222](https://github.com/airbytehq/airbyte/pull/6222) | Correct Spec File | +| 0.1.1 | 2021-09-22 | [6315](https://github.com/airbytehq/airbyte/pull/6315) | Verify access to all sites when performing connection check | +| 0.1.0 | 2021-09-03 | [5350](https://github.com/airbytehq/airbyte/pull/5350) | Initial Release | From ef3682b392ea9705d713ffc6c6b546aa18ff44d3 Mon Sep 17 00:00:00 2001 From: "Ryan Br..." Date: Mon, 30 Mar 2026 13:09:07 -0700 Subject: [PATCH 041/379] fix: bump s3-data-lake to 1.0.7 to get sort order fix. (#75628) --- .../destination-s3-data-lake/gradle.properties | 2 +- .../connectors/destination-s3-data-lake/metadata.yaml | 2 +- .../s3_data_lake/write/S3DataLakeStreamLoaderTest.kt | 11 +++++++++-- docs/integrations/destinations/s3-data-lake.md | 1 + 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/airbyte-integrations/connectors/destination-s3-data-lake/gradle.properties b/airbyte-integrations/connectors/destination-s3-data-lake/gradle.properties index ddc90fbbaf36..c28a577e6ca1 100644 --- a/airbyte-integrations/connectors/destination-s3-data-lake/gradle.properties +++ b/airbyte-integrations/connectors/destination-s3-data-lake/gradle.properties @@ -1,3 +1,3 @@ testExecutionConcurrency=-1 -cdkVersion=1.0.5 +cdkVersion=1.0.7 JunitMethodExecutionTimeout=10m diff --git a/airbyte-integrations/connectors/destination-s3-data-lake/metadata.yaml b/airbyte-integrations/connectors/destination-s3-data-lake/metadata.yaml index f463264f6c16..2b57522bebd2 100644 --- a/airbyte-integrations/connectors/destination-s3-data-lake/metadata.yaml +++ b/airbyte-integrations/connectors/destination-s3-data-lake/metadata.yaml @@ -37,7 +37,7 @@ data: alias: airbyte-connector-testing-secret-store connectorType: destination definitionId: 716ca874-520b-4902-9f80-9fad66754b89 - dockerImageTag: 0.3.45 + dockerImageTag: 0.3.46 dockerRepository: airbyte/destination-s3-data-lake documentationUrl: https://docs.airbyte.com/integrations/destinations/s3-data-lake githubIssueLabel: destination-s3-data-lake diff --git a/airbyte-integrations/connectors/destination-s3-data-lake/src/test/kotlin/io/airbyte/integrations/destination/s3_data_lake/write/S3DataLakeStreamLoaderTest.kt b/airbyte-integrations/connectors/destination-s3-data-lake/src/test/kotlin/io/airbyte/integrations/destination/s3_data_lake/write/S3DataLakeStreamLoaderTest.kt index 1f4e3ad4f498..4d9c95d97d6f 100644 --- a/airbyte-integrations/connectors/destination-s3-data-lake/src/test/kotlin/io/airbyte/integrations/destination/s3_data_lake/write/S3DataLakeStreamLoaderTest.kt +++ b/airbyte-integrations/connectors/destination-s3-data-lake/src/test/kotlin/io/airbyte/integrations/destination/s3_data_lake/write/S3DataLakeStreamLoaderTest.kt @@ -44,6 +44,7 @@ import io.mockk.verify import kotlin.test.assertEquals import kotlinx.coroutines.runBlocking import org.apache.iceberg.Schema +import org.apache.iceberg.SortOrder import org.apache.iceberg.Table import org.apache.iceberg.UpdateSchema import org.apache.iceberg.catalog.Catalog @@ -261,7 +262,10 @@ internal class S3DataLakeStreamLoaderTest { every { s3BucketConfiguration } returns bucketConfiguration } val catalog: Catalog = mockk() - val table: Table = mockk { every { schema() } returns icebergSchema } + val table: Table = mockk { + every { schema() } returns icebergSchema + every { sortOrder() } returns SortOrder.unsorted() + } val updateSchema: UpdateSchema = mockk() every { table.updateSchema().allowIncompatibleChanges() } returns updateSchema every { @@ -433,7 +437,10 @@ internal class S3DataLakeStreamLoaderTest { every { s3BucketConfiguration } returns bucketConfiguration } val catalog: Catalog = mockk() - val table: Table = mockk { every { schema() } returns icebergSchema } + val table: Table = mockk { + every { schema() } returns icebergSchema + every { sortOrder() } returns SortOrder.unsorted() + } val updateSchema: UpdateSchema = mockk() every { table.updateSchema().allowIncompatibleChanges() } returns updateSchema every { diff --git a/docs/integrations/destinations/s3-data-lake.md b/docs/integrations/destinations/s3-data-lake.md index 5c5a433bbbd0..c4e9760dcf32 100644 --- a/docs/integrations/destinations/s3-data-lake.md +++ b/docs/integrations/destinations/s3-data-lake.md @@ -392,6 +392,7 @@ This destination supports [namespaces](https://docs.airbyte.com/platform/using-a | Version | Date | Pull Request | Subject | |:------------|:-----------|:-----------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------| +| 0.3.46 | 2026-03-30 | | Upgrade CDK to 1.0.7: fix sort order handling during schema evolution. | | 0.3.45 | 2026-03-12 | [74326](https://github.com/airbytehq/airbyte/pull/74326) | Upgrade CDK to 1.0.5: Number-type primary keys are now stored as String (enabling dedup on numeric PKs); fix schema evolution when replacing identifier columns | | 0.3.44 | 2026-02-04 | [72848](https://github.com/airbytehq/airbyte/pull/72848) | Enable Speed. | | 0.3.43 | 2026-01-29 | [72482](https://github.com/airbytehq/airbyte/pull/72482) | Release on dataflow. | From f3f5324b850978ff10454c4bfb835c1f1e1abab1 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Mon, 30 Mar 2026 13:13:18 -0700 Subject: [PATCH 042/379] ci: use GitHub API for modified-connector detection in bump-version workflow (#75604) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/bump-version-command.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/bump-version-command.yml b/.github/workflows/bump-version-command.yml index 39fc5f1720ea..6a049e01f973 100644 --- a/.github/workflows/bump-version-command.yml +++ b/.github/workflows/bump-version-command.yml @@ -94,12 +94,14 @@ jobs: id: detect-connectors env: PR_NUMBER: ${{ github.event.inputs.pr }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | CONNECTORS=$( airbyte-ops local connector list \ --repo-path "$GITHUB_WORKSPACE" \ --modified-only \ --pr "$PR_NUMBER" \ + --gh-token "$GH_TOKEN" \ --output-format lines ) From 28b00519a1266768b83db2939defa6fd0df2a67a Mon Sep 17 00:00:00 2001 From: "octavia-bot[bot]" <108746235+octavia-bot[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 20:18:05 +0000 Subject: [PATCH 043/379] docs: sync agent connector docs from airbyte-agent-connectors repo (#75629) Co-authored-by: ian-at-airbyte <187576150+ian-at-airbyte@users.noreply.github.com> --- docs/ai-agents/connectors/notion/AUTH.md | 155 +++++++++++++++++- docs/ai-agents/connectors/notion/README.md | 10 +- docs/ai-agents/connectors/notion/REFERENCE.md | 4 + 3 files changed, 159 insertions(+), 10 deletions(-) diff --git a/docs/ai-agents/connectors/notion/AUTH.md b/docs/ai-agents/connectors/notion/AUTH.md index 0d63e075ae83..0380ccc87c23 100644 --- a/docs/ai-agents/connectors/notion/AUTH.md +++ b/docs/ai-agents/connectors/notion/AUTH.md @@ -9,7 +9,30 @@ This page documents the authentication and configuration options for the Notion In open source mode, you provide API credentials directly to the connector. #### OAuth -This authentication method isn't available for this connector. + +`credentials` fields you need: + + +| Field Name | Type | Required | Description | +|------------|------|----------|-------------| +| `client_id` | `str` | Yes | Your Notion OAuth integration's client ID | +| `client_secret` | `str` | Yes | Your Notion OAuth integration's client secret | +| `access_token` | `str` | Yes | OAuth access token obtained through the Notion authorization flow | + +Example request: + +```python +from airbyte_agent_notion import NotionConnector +from airbyte_agent_notion.models import NotionOauth20AuthConfig + +connector = NotionConnector( + auth_config=NotionOauth20AuthConfig( + client_id="", + client_secret="", + access_token="" + ) +) +``` #### Token @@ -23,10 +46,10 @@ Example request: ```python from airbyte_agent_notion import NotionConnector -from airbyte_agent_notion.models import NotionAuthConfig +from airbyte_agent_notion.models import NotionAccessTokenAuthConfig connector = NotionConnector( - auth_config=NotionAuthConfig( + auth_config=NotionAccessTokenAuthConfig( token="" ) ) @@ -37,10 +60,132 @@ connector = NotionConnector( In hosted mode, you first create a connector via the Airbyte API (providing your OAuth or Token credentials), then execute operations using either the Python SDK or API. If you need a step-by-step guide, see the [hosted execution tutorial](https://docs.airbyte.com/ai-agents/quickstarts/tutorial-hosted). #### OAuth -This authentication method isn't available for this connector. +Create a connector with OAuth credentials. + +`credentials` fields you need: + + +| Field Name | Type | Required | Description | +|------------|------|----------|-------------| +| `client_id` | `str` | Yes | Your Notion OAuth integration's client ID | +| `client_secret` | `str` | Yes | Your Notion OAuth integration's client secret | +| `access_token` | `str` | Yes | OAuth access token obtained through the Notion authorization flow | + +Example request: + +```bash +curl -X POST "https://api.airbyte.ai/api/v1/integrations/connectors" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "customer_name": "", + "connector_type": "Notion", + "name": "My Notion Connector", + "credentials": { + "client_id": "", + "client_secret": "", + "access_token": "" + } + }' +``` + + #### Bring your own OAuth flow -This authentication method isn't available for this connector. +To implement your own OAuth flow, use Airbyte's server-side OAuth API endpoints. For a complete guide, see [Build your own OAuth flow](https://docs.airbyte.com/ai-agents/platform/authenticate/build-auth/build-your-own). + +##### Configure your own OAuth app credentials (optional) + +By default, Airbyte uses its own OAuth app credentials. You can override these with your own so that OAuth consent screens show your company's branding. If you skip this step, the consent screen shows "Airbyte" as the requesting application. + +**Python SDK** + +```python +from airbyte_agent_notion import NotionConnector, AirbyteAuthConfig +from airbyte_agent_notion.models import NotionOAuthCredentials + +await NotionConnector.configure_oauth_app_parameters( + airbyte_config=AirbyteAuthConfig( + airbyte_client_id="", + airbyte_client_secret="", + ), + credentials=NotionOAuthCredentials( + client_id="", + client_secret="", + ), +) +``` + +**API** + +```bash +curl -X PUT "https://api.airbyte.ai/api/v1/oauth/credentials" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "connector_type": "notion", + "configuration": { + "client_id": "", + "client_secret": "" + } + }' +``` + +**To revert to Airbyte-managed defaults**: + +**Python SDK** + +```python +await NotionConnector.configure_oauth_app_parameters( + airbyte_config=AirbyteAuthConfig( + airbyte_client_id="", + airbyte_client_secret="", + ), + credentials=None, +) +``` + +**API** + +```bash +curl -X DELETE "https://api.airbyte.ai/api/v1/oauth/credentials/connector_type/notion" \ + -H "Authorization: Bearer " +``` + +##### Step 1: Initiate the OAuth flow + +Request a consent URL for your user. + +| Field Name | Type | Required | Description | +|------------|------|----------|-------------| +| `customer_name` | `string` | Yes | Your unique identifier for the customer | +| `connector_type` | `string` | Yes | The connector type (e.g., "Notion") | +| `redirect_url` | `string` | Yes | URL to redirect to after OAuth authorization | + +Example request: + +```bash +curl -X POST "https://api.airbyte.ai/api/v1/integrations/connectors/oauth/initiate" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "customer_name": "", + "connector_type": "Notion", + "redirect_url": "https://yourapp.com/oauth/callback" + }' +``` + +Redirect your user to the `consent_url` from the response. + +##### Step 2: Handle the callback + +After the user authorizes access, Airbyte automatically creates the connector and redirects them to your `redirect_url` with a `connector_id` query parameter. You don't need to make a separate API call to create the connector. + +```text +https://yourapp.com/oauth/callback?connector_id= +``` + +Extract the `connector_id` from the callback URL and store it for future operations. For error handling and a complete implementation example, see [Build your own OAuth flow](https://docs.airbyte.com/ai-agents/platform/authenticate/build-auth/build-your-own#part-3-handle-the-callback). #### Token Create a connector with Token credentials. diff --git a/docs/ai-agents/connectors/notion/README.md b/docs/ai-agents/connectors/notion/README.md index d5cdab78ea38..b4db919490de 100644 --- a/docs/ai-agents/connectors/notion/README.md +++ b/docs/ai-agents/connectors/notion/README.md @@ -50,10 +50,10 @@ In open source mode, you provide API credentials directly to the connector. ```python from airbyte_agent_notion import NotionConnector -from airbyte_agent_notion.models import NotionAuthConfig +from airbyte_agent_notion.models import NotionAccessTokenAuthConfig connector = NotionConnector( - auth_config=NotionAuthConfig( + auth_config=NotionAccessTokenAuthConfig( token="" ) ) @@ -114,7 +114,7 @@ See the official [Notion API reference](https://developers.notion.com/reference/ ## Version information -- **Package version:** 0.1.22 -- **Connector version:** 0.1.5 -- **Generated with Connector SDK commit SHA:** 75f388847745be753ab20224c66697e1d4a84347 +- **Package version:** 0.1.23 +- **Connector version:** 0.1.6 +- **Generated with Connector SDK commit SHA:** dd2ed97fb6ead6bc3014adf1eaddb9b8b9fb4001 - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/notion/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/notion/REFERENCE.md b/docs/ai-agents/connectors/notion/REFERENCE.md index 819f3698c3d4..230de56a25bb 100644 --- a/docs/ai-agents/connectors/notion/REFERENCE.md +++ b/docs/ai-agents/connectors/notion/REFERENCE.md @@ -254,6 +254,7 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | `parent` | `object \| any` | | | `archived` | `boolean \| null` | | | `in_trash` | `boolean \| null` | | +| `is_archived` | `boolean \| null` | | | `is_locked` | `boolean \| null` | | | `properties` | `object \| null` | | | `url` | `string \| null` | | @@ -323,6 +324,7 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | `parent` | `object \| any` | | | `archived` | `boolean \| null` | | | `in_trash` | `boolean \| null` | | +| `is_archived` | `boolean \| null` | | | `is_locked` | `boolean \| null` | | | `properties` | `object \| null` | | | `url` | `string \| null` | | @@ -489,6 +491,7 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | `public_url` | `string \| null` | | | `archived` | `boolean \| null` | | | `in_trash` | `boolean \| null` | | +| `is_archived` | `boolean \| null` | | | `is_inline` | `boolean \| null` | | | `is_locked` | `boolean \| null` | | | `request_id` | `string \| null` | | @@ -572,6 +575,7 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | `public_url` | `string \| null` | | | `archived` | `boolean \| null` | | | `in_trash` | `boolean \| null` | | +| `is_archived` | `boolean \| null` | | | `is_inline` | `boolean \| null` | | | `is_locked` | `boolean \| null` | | | `request_id` | `string \| null` | | From d1543d40e56d9ad5762adab77abc4869461c9f3f Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 20:18:11 +0000 Subject: [PATCH 044/379] docs(source-notion): Improve rate limiting docs, prerequisites, and stream descriptions (#75607) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- docs/integrations/sources/notion.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/integrations/sources/notion.md b/docs/integrations/sources/notion.md index da206f399d93..6ee7a53e14b9 100644 --- a/docs/integrations/sources/notion.md +++ b/docs/integrations/sources/notion.md @@ -5,6 +5,7 @@ This page contains the setup guide and reference information for the Notion sour ## Prerequisites - Access to a [Notion](https://notion.so/login) workspace +- You must be a workspace owner to create a Notion integration ## Setup guide @@ -35,8 +36,8 @@ You must be the owner of the Notion workspace to create a new integration associ 3. In the navbar, select [**Capabilities**](https://developers.notion.com/reference/capabilities). Check the following capabilities based on your use case: - [**Read content**](https://developers.notion.com/reference/capabilities#content-capabilities): required for all connections. -- [**Read comments**](https://developers.notion.com/reference/capabilities#comment-capabilities): required if you wish to sync the `Comments` stream -- [**Read user information**](https://developers.notion.com/reference/capabilities#user-capabilities) (either with or without emails): required if you wish to sync the `Users` stream +- [**Read comments**](https://developers.notion.com/reference/capabilities#comment-capabilities): required if you want to sync the Comments stream. +- [**Read user information**](https://developers.notion.com/reference/capabilities#user-capabilities) (with or without emails): required if you want to sync the Users stream. ### Step 2: Share pages and acquire authorization credentials @@ -98,19 +99,19 @@ The Notion source connector supports the following [sync modes](https://docs.air | Pages | ✓ | ✓ | | Users | ✓ | | -## Supported Streams +## Supported streams The Notion source connector supports the following streams: - [Blocks](https://developers.notion.com/reference/retrieve-a-block): Retrieves content blocks for all synced pages, including recursively nested child blocks up to 30 levels deep. Block types `child_page`, `child_database`, and `ai_block` are excluded. -- [Comments](https://developers.notion.com/reference/list-comments): Retrieves comments on all synced pages. -- [Data Sources](https://developers.notion.com/reference/data-source): Retrieves data source objects, which represent the structured tables that contain pages and properties. This stream replaces the former `Databases` stream as of v4.0.0. For details on migrating, see the [Notion migration guide](notion-migrations.md). +- [Comments](https://developers.notion.com/reference/list-comments): Retrieves comments on all synced pages. Requires the **Read comments** integration capability. +- [Data Sources](https://developers.notion.com/reference/data-source): Retrieves data source objects. In the Notion API `2025-09-03`, a data source represents a structured table that contains pages and properties — previously called a "database." This stream replaces the former `Databases` stream as of v4.0.0. For details on migrating, see the [Notion migration guide](notion-migrations.md). - [Pages](https://developers.notion.com/reference/retrieve-a-page): Retrieves page objects from all shared pages. -- [Users](https://developers.notion.com/reference/get-users): Retrieves user objects from the workspace. +- [Users](https://developers.notion.com/reference/get-users): Retrieves user objects from the workspace. Requires the **Read user information** integration capability. ## Performance considerations -The connector is restricted by Notion [request limits](https://developers.notion.com/reference/request-limits). The Notion connector should not run into Notion API limitations under normal usage. [Create an issue](https://github.com/airbytehq/airbyte/issues) if you encounter any rate limit issues that are not automatically retried successfully. +The Notion API enforces a rate limit of approximately three requests per second per integration. When the connector receives an HTTP 429 response, it respects the `Retry-After` header and retries the request automatically. Rate-limited requests do not count toward the maximum retry limit, so syncs continue indefinitely until the rate limit clears. For more details, see Notion's [request limits](https://developers.notion.com/reference/request-limits) documentation. The Blocks stream recursively fetches child blocks up to 30 levels deep. Pages with deeply nested content can generate a large number of API requests, which may slow down syncs for workspaces with complex page structures. From a24a64302df793ba04382cd63795616a8e972888 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 20:18:18 +0000 Subject: [PATCH 045/379] docs(source-hubspot): update deprecated API links and correct rate limits table (#75606) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- docs/integrations/sources/hubspot.md | 44 ++++++++++++++-------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/integrations/sources/hubspot.md b/docs/integrations/sources/hubspot.md index d2e7a6034353..bd5b70583eed 100644 --- a/docs/integrations/sources/hubspot.md +++ b/docs/integrations/sources/hubspot.md @@ -49,7 +49,7 @@ More information on HubSpot authentication methods can be found These instructions are only relevant if you are using a **Private App** for authentication. You can ignore this if you are authenticating via OAuth. -To set up a Private App, you must manually configure scopes to ensure Airbyte can sync all available data. Each scope relates to a specific stream or streams. Please refer to [Hubspot's page on scopes](https://legacydocs.hubspot.com/docs/methods/oauth2/initiate-oauth-integration#scopes) for instructions. +To set up a Private App, you must manually configure scopes to ensure Airbyte can sync all available data. Each scope relates to a specific stream or streams. Refer to [HubSpot's documentation on scopes](https://developers.hubspot.com/docs/api/working-with-oauth#scopes) for instructions.
Expand to review scopes @@ -158,40 +158,40 @@ There are two types of incremental sync: The HubSpot source connector supports the following streams: -- [Campaigns](https://developers.hubspot.com/docs/methods/email/get_campaign_data) \(Client-Side Incremental\) +- [Campaigns](https://developers.hubspot.com/docs/api/marketing/campaigns) \(Client-Side Incremental\) - [Companies](https://developers.hubspot.com/docs/api/crm/companies) \(Incremental\) - [Contact Lists](https://developers.hubspot.com/docs/reference/api/crm/lists#post-%2Fcrm%2Fv3%2Flists%2Fsearch) \(Incremental\) -- [Contacts](https://developers.hubspot.com/docs/methods/contacts/get_contacts) \(Incremental\) -- [Deal Pipelines](https://developers.hubspot.com/docs/methods/pipelines/get_pipelines_for_object_type) \(Client-Side Incremental\) +- [Contacts](https://developers.hubspot.com/docs/api/crm/contacts) \(Incremental\) +- [Deal Pipelines](https://developers.hubspot.com/docs/api/crm/pipelines) \(Client-Side Incremental\) - [Deal Splits](https://developers.hubspot.com/docs/api/crm/deals) \(Incremental\) - [Deals](https://developers.hubspot.com/docs/api/crm/deals) \(including Contact associations\) \(Incremental\) - Records that have been deleted (archived) and stored in HubSpot's recycle bin will only be kept for 90 days, see [response from HubSpot Team](https://community.hubspot.com/t5/APIs-Integrations/Archived-deals-deleted-or-different/m-p/714157) - [Deals Archived](https://developers.hubspot.com/docs/api/crm/deals) \(including Contact associations\) \(Incremental\) -- [Email Events](https://developers.hubspot.com/docs/methods/email/get_events) \(Incremental\) -- [Email Subscriptions](https://developers.hubspot.com/docs/methods/email/get_subscriptions) -- [Engagements](https://legacydocs.hubspot.com/docs/methods/engagements/get-all-engagements) \(Incremental\) +- [Email Events](https://developers.hubspot.com/docs/api/marketing/email-events) \(Incremental\) +- [Email Subscriptions](https://developers.hubspot.com/docs/api/marketing/subscriptions) +- [Engagements](https://developers.hubspot.com/docs/api/crm/engagements) \(Incremental\) - [Engagements Calls](https://developers.hubspot.com/docs/api/crm/calls) \(Incremental\) - [Engagements Emails](https://developers.hubspot.com/docs/api/crm/email) \(Incremental\) - [Engagements Meetings](https://developers.hubspot.com/docs/api/crm/meetings) \(Incremental\) - [Engagements Notes](https://developers.hubspot.com/docs/api/crm/notes) \(Incremental\) - [Engagements Tasks](https://developers.hubspot.com/docs/api/crm/tasks) \(Incremental\) - [Forms](https://developers.hubspot.com/docs/api/marketing/forms) \(Client-Side Incremental\) -- [Form Submissions](https://legacydocs.hubspot.com/docs/methods/forms/get-submissions-for-a-form) \(Client-Side Incremental\) +- [Form Submissions](https://developers.hubspot.com/docs/api/marketing/forms) \(Client-Side Incremental\) - [Goals](https://developers.hubspot.com/docs/api/crm/goals) \(Incremental\) - [Leads](https://developers.hubspot.com/docs/api/crm/leads) \(Incremental\) - [Line Items](https://developers.hubspot.com/docs/api/crm/line-items) \(Incremental\) - [Marketing Emails](https://developers.hubspot.com/docs/api-reference/marketing-marketing-emails-v3-v3/marketing-emails/get-marketing-v3-emails-) \(Incremental\) -- [Owners](https://developers.hubspot.com/docs/methods/owners/get_owners) \(Client-Side Incremental\) -- [Owners Archived](https://legacydocs.hubspot.com/docs/methods/owners/get_owners) \(Client-Side Incremental) +- [Owners](https://developers.hubspot.com/docs/api/crm/owners) \(Client-Side Incremental\) +- [Owners Archived](https://developers.hubspot.com/docs/api/crm/owners) \(Client-Side Incremental) - [Products](https://developers.hubspot.com/docs/api/crm/products) \(Incremental\) - [Properties](https://developers.hubspot.com/docs/api/crm/properties) \(Full Refresh\) -- [Contacts Property History](https://legacydocs.hubspot.com/docs/methods/contacts/get_contacts) \(Client-Side Incremental\) -- [Companies Property History](https://legacydocs.hubspot.com/docs/methods/companies/get-all-companies) \(Client-Side Incremental\) -- [Deals Property History](https://legacydocs.hubspot.com/docs/methods/deals/get-all-deals) \(Client-Side Incremental\) -- [Subscription Changes](https://developers.hubspot.com/docs/methods/email/get_subscriptions_timeline) \(Incremental\) +- [Contacts Property History](https://developers.hubspot.com/docs/api/crm/contacts) \(Client-Side Incremental\) +- [Companies Property History](https://developers.hubspot.com/docs/api/crm/companies) \(Client-Side Incremental\) +- [Deals Property History](https://developers.hubspot.com/docs/api/crm/deals) \(Client-Side Incremental\) +- [Subscription Changes](https://developers.hubspot.com/docs/api/marketing/subscriptions) \(Incremental\) - [Tickets](https://developers.hubspot.com/docs/api/crm/tickets) \(Incremental\) - [Ticket Pipelines](https://developers.hubspot.com/docs/api/crm/pipelines) \(Client-Side Incremental\) -- [Workflows](https://legacydocs.hubspot.com/docs/methods/workflows/v3/get_workflows) \(Client-Side Incremental\) +- [Workflows](https://developers.hubspot.com/docs/api/automation/workflows) \(Client-Side Incremental\) - [ContactsWebAnalytics](https://developers.hubspot.com/docs/api/events/web-analytics) \(Incremental\) - [CompaniesWebAnalytics](https://developers.hubspot.com/docs/api/events/web-analytics) \(Incremental\) - [DealsWebAnalytics](https://developers.hubspot.com/docs/api/events/web-analytics) \(Incremental\) @@ -259,14 +259,14 @@ Expand to see details about Hubspot connector limitations and troubleshooting. ### Rate limiting -The connector is restricted by normal HubSpot [rate limitations](https://legacydocs.hubspot.com/apps/api_guidelines). +The connector is restricted by normal HubSpot [rate limits](https://developers.hubspot.com/docs/developer-tooling/platform/usage-guidelines). The burst limit applies per app, and the daily limit is shared across all apps within the same HubSpot account. -| Product tier | Limits | -| :--------------- | :---------------------------------------- | -| `Free & Starter` | Burst: 100/10 seconds, Daily: 250,000 | -| `Professional` | Burst: 190/10 seconds, Daily: 650,000 | -| `Enterprise` | Burst: 190/10 seconds, Daily: 1,000,000 | -| `API add-on` | Adds 1,000,000 daily requests to the tier limit | +| Product tier | Burst (per 10 seconds) | Daily (per account) | +| :------------------------- | :--------------------- | :---------------------------- | +| Free & Starter | 100 | 250,000 | +| Professional | 190 | 625,000 | +| Enterprise | 190 | 1,000,000 | +| API Limit Increase add-on | 250 | +1,000,000 per add-on (max 2) | ### Custom properties sync slowly From 7ead32b04ef135b2ea9f24f36c50bc315e70708d Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 20:18:23 +0000 Subject: [PATCH 046/379] fix(source-linkedin-ads): map HTTP 429 to RATE_LIMITED instead of RETRY (#75597) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- .../source-linkedin-ads/manifest.yaml | 12 +- .../source-linkedin-ads/metadata.yaml | 2 +- .../unit_tests/test_source.py | 31 +++ docs/integrations/sources/linkedin-ads.md | 185 +++++++++--------- 4 files changed, 127 insertions(+), 103 deletions(-) diff --git a/airbyte-integrations/connectors/source-linkedin-ads/manifest.yaml b/airbyte-integrations/connectors/source-linkedin-ads/manifest.yaml index 0d9f76c45e0c..0d0123a34790 100644 --- a/airbyte-integrations/connectors/source-linkedin-ads/manifest.yaml +++ b/airbyte-integrations/connectors/source-linkedin-ads/manifest.yaml @@ -286,18 +286,10 @@ definitions: - type: DefaultErrorHandler response_filters: - type: HttpResponseFilter - action: RETRY + action: RATE_LIMITED http_codes: - 429 - error_message: >- - Stream {{self.name}}: LinkedIn API requests are rate - limited. Rate limits specify the maximum number of API - calls that can be made in a 24 hour period. These limits - reset at midnight UTC every day. You can find more - information here - https://docs.airbyte.com/integrations/sources/linkedin-ads. - Also quotas and usage are here: - https://www.linkedin.com/developers/apps. + error_message: Rate limit exceeded for LinkedIn API. - type: HttpResponseFilter action: RETRY http_codes: diff --git a/airbyte-integrations/connectors/source-linkedin-ads/metadata.yaml b/airbyte-integrations/connectors/source-linkedin-ads/metadata.yaml index bbbd937b909f..547b1aa9edb8 100644 --- a/airbyte-integrations/connectors/source-linkedin-ads/metadata.yaml +++ b/airbyte-integrations/connectors/source-linkedin-ads/metadata.yaml @@ -11,7 +11,7 @@ data: connectorSubtype: api connectorType: source definitionId: 137ece28-5434-455c-8f34-69dc3782f451 - dockerImageTag: 5.6.4 + dockerImageTag: 5.6.5 dockerRepository: airbyte/source-linkedin-ads documentationUrl: https://docs.airbyte.com/integrations/sources/linkedin-ads externalDocumentationUrls: diff --git a/airbyte-integrations/connectors/source-linkedin-ads/unit_tests/test_source.py b/airbyte-integrations/connectors/source-linkedin-ads/unit_tests/test_source.py index 21cf9a05bcc2..84cda4cec4ff 100644 --- a/airbyte-integrations/connectors/source-linkedin-ads/unit_tests/test_source.py +++ b/airbyte-integrations/connectors/source-linkedin-ads/unit_tests/test_source.py @@ -1,10 +1,12 @@ # Copyright (c) 2025 Airbyte, Inc., all rights reserved. import logging +from pathlib import Path from typing import Any, Dict, List import pytest import requests +import yaml from airbyte_protocol_dataclasses.models import AirbyteStream, ConfiguredAirbyteCatalog, ConfiguredAirbyteStream, DestinationSyncMode from airbyte_protocol_dataclasses.models import Status as ConnectionStatus @@ -107,6 +109,35 @@ def test_should_retry_on_error(self, error_code, requests_mock, mocker): with pytest.raises(MessageRepresentationAirbyteTracedErrors): list(run_read(stream)) + def test_manifest_maps_429_to_rate_limited(self): + """ + Verify the manifest configures HTTP 429 responses with RATE_LIMITED action + (not RETRY), so that rate-limited requests retry indefinitely with backoff + instead of failing after a limited number of retries. + + HTTP 500/503 should remain mapped to RETRY. + """ + manifest_path = Path(__file__).parent.parent / "manifest.yaml" + manifest = yaml.safe_load(manifest_path.read_text()) + + # The CompositeErrorHandler with the 429 filter is on the creatives stream + creatives = manifest["definitions"]["streams"]["creatives"] + error_handlers = creatives["retriever"]["requester"]["error_handlers"] + + assert error_handlers["type"] == "CompositeErrorHandler" + + inner_handlers = error_handlers["error_handlers"] + default_handler = next(h for h in inner_handlers if h.get("type") == "DefaultErrorHandler") + response_filters = default_handler["response_filters"] + + filter_429 = next(f for f in response_filters if 429 in f.get("http_codes", [])) + filter_5xx = next(f for f in response_filters if 500 in f.get("http_codes", [])) + + assert ( + filter_429["action"] == "RATE_LIMITED" + ), f"HTTP 429 must use RATE_LIMITED action for indefinite retry, got {filter_429['action']}" + assert filter_5xx["action"] == "RETRY", f"HTTP 500/503 should use RETRY action, got {filter_5xx['action']}" + def test_custom_streams(self, requests_mock): config = {"ad_analytics_reports": [{"name": "ShareAdByMonth", "pivot_by": "COMPANY", "time_granularity": "MONTHLY"}], **TEST_CONFIG} streams = get_source(config).streams(config=config) diff --git a/docs/integrations/sources/linkedin-ads.md b/docs/integrations/sources/linkedin-ads.md index d6ce0dfba25f..34426dee6ce1 100644 --- a/docs/integrations/sources/linkedin-ads.md +++ b/docs/integrations/sources/linkedin-ads.md @@ -212,102 +212,103 @@ No workaround has been identified to manage this issue as of 2025, February. | Version | Date | Pull Request | Subject | |:-----------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 5.6.5 | 2026-03-30 | [75597](https://github.com/airbytehq/airbyte/pull/75597) | Map HTTP 429 responses to RATE_LIMITED instead of RETRY for proper indefinite backoff on rate-limited requests | | 5.6.4 | 2026-02-10 | [72831](https://github.com/airbytehq/airbyte/pull/72831) | Upgrade LinkedIn API version from 202502 to 202601 | | 5.6.3 | 2026-02-10 | [72768](https://github.com/airbytehq/airbyte/pull/72768) | Update dependencies | | 5.6.2 | 2026-01-20 | [72028](https://github.com/airbytehq/airbyte/pull/72028) | Update dependencies | | 5.6.1 | 2026-01-14 | [68982](https://github.com/airbytehq/airbyte/pull/68982) | Update dependencies | | 5.6.0 | 2025-11-04 | [69180](https://github.com/airbytehq/airbyte/pull/69180) | Promoting release candidate 5.6.0-rc.1 to a main version. | -| 5.6.0-rc.1 | 2025-10-29 | [68614](https://github.com/airbytehq/airbyte/pull/68614) | Upgrade to latest CDK to only include the selected columns of the schema in API requests for ad analytics streams | -| 5.5.5 | 2025-10-28 | [68626](https://github.com/airbytehq/airbyte/pull/68626) | Increase concurrency and introduce initial attempt at API budget | -| 5.5.4 | 2025-10-21 | [64967](https://github.com/airbytehq/airbyte/pull/64967) | Update dependencies | -| 5.5.3 | 2025-10-14 | [67564](https://github.com/airbytehq/airbyte/pull/67564) | Upgrade to CDK v7. | -| 5.5.2 | 2025-07-16 | [63336](https://github.com/airbytehq/airbyte/pull/63336) | Promoting release candidate 5.5.2-rc.1 to a main version. | -| 5.5.2-rc.1 | 2025-06-23 | [60996](https://github.com/airbytehq/airbyte/pull/60996) | Fix to properly manage pagination for `Lead forms` and `Lead form responses` streams | -| 5.5.1 | 2025-06-18 | [61639](https://github.com/airbytehq/airbyte/pull/61639) | Reduce default concurrency level to 3 and enable configurability via `num_workers` config property | -| 5.5.0 | 2025-04-28 | [59116](https://github.com/airbytehq/airbyte/pull/59116) | Promoting release candidate 5.5.0-rc.1 to a main version. | -| 5.5.0-rc.1 | 2025-04-25 | [58628](https://github.com/airbytehq/airbyte/pull/58628) | Convert to manifest-only format | -| 5.4.1 | 2025-04-23 | [58134](https://github.com/airbytehq/airbyte/pull/58134) | Fix to properly retrieve `approximateMemberReach` for `adAnalytics` streams following `v5.3.3`. | -| 5.4.0 | 2025-04-22 | [58593](https://github.com/airbytehq/airbyte/pull/58593) | Promoting release candidate 5.4.0-rc.1 to a main version. | -| 5.4.0-rc.1 | 2025-04-18 | [58114](https://github.com/airbytehq/airbyte/pull/58114) | Removes custom retrievers and cursors from analytics streams so that they can take up concurrency. | -| 5.3.3 | 2025-03-12 | [55724](https://github.com/airbytehq/airbyte/pull/55724) | Update outdated schema `approximateUniqueImpressions` to new `approximateMemberReach` for `adAnalytics` streams. | -| 5.3.2 | 2025-03-08 | [55447](https://github.com/airbytehq/airbyte/pull/55447) | Update dependencies | -| 5.3.1 | 2025-03-05 | [55211](https://github.com/airbytehq/airbyte/pull/55211) | Update dependencies | -| 5.3.0 | 2025-03-02 | [55171](https://github.com/airbytehq/airbyte/pull/55171) | Migrate API to v202502 | -| 5.2.3 | 2025-03-01 | [54813](https://github.com/airbytehq/airbyte/pull/54813) | Update dependencies | -| 5.2.2 | 2025-02-22 | [53308](https://github.com/airbytehq/airbyte/pull/53308) | Update dependencies | -| 5.2.1 | 2025-02-10 | [53611](https://github.com/airbytehq/airbyte/pull/53611) | Add schema precisions for `Lead forms` and `Lead form responses` streams | -| 5.2.0 | 2025-02-04 | [52047](https://github.com/airbytehq/airbyte/pull/52047) | Add `Lead forms` and `Lead form responses` new streams - See Limits & considerations | -| 5.1.6 | 2025-02-02 | [49458](https://github.com/airbytehq/airbyte/pull/49458) | Update Linkedin Ads API version to 202410 for creatives stream | -| 5.1.5 | 2025-02-01 | [52791](https://github.com/airbytehq/airbyte/pull/52791) | Update dependencies | -| 5.1.4 | 2025-01-30 | [52604](https://github.com/airbytehq/airbyte/pull/52604) | Fix state error | -| 5.1.3 | 2025-01-22 | [52604](https://github.com/airbytehq/airbyte/pull/52604) | Update CDK to production ^6 | -| 5.1.2 | 2025-01-25 | [52253](https://github.com/airbytehq/airbyte/pull/52253) | Update dependencies | -| 5.1.1 | 2025-01-15 | [47092](https://github.com/airbytehq/airbyte/pull/47092) | Starting with this version, the Docker image is now rootless. Please note that this and future versions will not be compatible with Airbyte versions earlier than 0.64 | -| 5.1.0 | 2025-01-14 | [48863](https://github.com/airbytehq/airbyte/pull/48863) | Custom streams moved to manifest implementation & URL Error Handling | -| 5.0.0 | 2024-11-26 | [48451](https://github.com/airbytehq/airbyte/pull/48451) | Update primary keys for streams ad_campaign_analytics, Custom Ad Analytics Reports and account_users | -| 4.1.4 | 2024-10-12 | [46862](https://github.com/airbytehq/airbyte/pull/46862) | Update dependencies | -| 4.1.3 | 2024-10-05 | [46433](https://github.com/airbytehq/airbyte/pull/46433) | Update dependencies | -| 4.1.2 | 2024-09-28 | [46171](https://github.com/airbytehq/airbyte/pull/46171) | Update dependencies | -| 4.1.1 | 2024-09-21 | [45774](https://github.com/airbytehq/airbyte/pull/45774) | Update dependencies | -| 4.1.0 | 2024-09-20 | [44370](https://github.com/airbytehq/airbyte/pull/44370) | Migrate to low-code | -| 4.0.6 | 2024-09-14 | [45532](https://github.com/airbytehq/airbyte/pull/45532) | Update dependencies | -| 4.0.5 | 2024-09-07 | [45209](https://github.com/airbytehq/airbyte/pull/45209) | Update dependencies | -| 4.0.4 | 2024-08-31 | [44950](https://github.com/airbytehq/airbyte/pull/44950) | Update dependencies | -| 4.0.3 | 2024-08-24 | [44682](https://github.com/airbytehq/airbyte/pull/44682) | Update dependencies | -| 4.0.2 | 2024-08-17 | [44220](https://github.com/airbytehq/airbyte/pull/44220) | Update dependencies | -| 4.0.1 | 2024-08-10 | [43629](https://github.com/airbytehq/airbyte/pull/43629) | Update dependencies | -| 4.0.0 | 2024-08-07 | [43359](https://github.com/airbytehq/airbyte/pull/43359) | Revert low code migration | -| 3.0.1 | 2024-08-03 | [43087](https://github.com/airbytehq/airbyte/pull/43087) | Update dependencies | -| 3.0.0 | 2024-06-18 | [38314](https://github.com/airbytehq/airbyte/pull/38314) | Migrate to low-code | -| 2.1.12 | 2024-07-27 | [42728](https://github.com/airbytehq/airbyte/pull/42728) | Update dependencies | -| 2.1.11 | 2024-07-20 | [42291](https://github.com/airbytehq/airbyte/pull/42291) | Update dependencies | -| 2.1.10 | 2024-07-13 | [41710](https://github.com/airbytehq/airbyte/pull/41710) | Update dependencies | -| 2.1.9 | 2024-07-10 | [41517](https://github.com/airbytehq/airbyte/pull/41517) | Update dependencies | -| 2.1.8 | 2024-07-09 | [41315](https://github.com/airbytehq/airbyte/pull/41315) | Update dependencies | -| 2.1.7 | 2024-07-06 | [40868](https://github.com/airbytehq/airbyte/pull/40868) | Update dependencies | -| 2.1.6 | 2024-06-25 | [40331](https://github.com/airbytehq/airbyte/pull/40331) | Update dependencies | -| 2.1.5 | 2024-06-22 | [39998](https://github.com/airbytehq/airbyte/pull/39998) | Update dependencies | -| 2.1.4 | 2024-06-16 | [39442](https://github.com/airbytehq/airbyte/pull/39442) | Fix README commands, change spec from json to yaml, fix schema states to object | -| 2.1.3 | 2024-06-06 | [39240](https://github.com/airbytehq/airbyte/pull/39240) | [autopull] Upgrade base image to v1.2.2 | -| 2.1.2 | 2024-05-07 | [36648](https://github.com/airbytehq/airbyte/pull/36648) | Schema descriptions | -| 2.1.1 | 2024-05-07 | [38013](https://github.com/airbytehq/airbyte/pull/38013) | Fix an issue where the `Accounts` stream did not correctly handle provided account IDs | -| 2.1.0 | 2024-04-30 | [37573](https://github.com/airbytehq/airbyte/pull/37573) | Update API version to `202404`; add cursor-based pagination | -| 2.0.0 | 2024-04-24 | [37531](https://github.com/airbytehq/airbyte/pull/37531) | Change primary key for Analytics Streams | -| 1.0.1 | 2024-03-28 | [34152](https://github.com/airbytehq/airbyte/pull/34152) | Proceed pagination if return less than expected | -| 1.0.0 | 2024-04-10 | [36927](https://github.com/airbytehq/airbyte/pull/36927) | Update primary key for Analytics Streams | -| 0.8.0 | 2024-03-19 | [36267](https://github.com/airbytehq/airbyte/pull/36267) | Pin airbyte-cdk version to `^0` | -| 0.7.0 | 2024-02-20 | [35465](https://github.com/airbytehq/airbyte/pull/35465) | Per-error reporting and continue sync on stream failures | -| 0.6.8 | 2024-02-09 | [35086](https://github.com/airbytehq/airbyte/pull/35086) | Manage dependencies with Poetry | -| 0.6.7 | 2024-01-11 | [34152](https://github.com/airbytehq/airbyte/pull/34152) | Prepare for airbyte-lib | -| 0.6.6 | 2024-01-15 | [34222](https://github.com/airbytehq/airbyte/pull/34222) | Use stream slices for Analytics streams | -| 0.6.5 | 2023-12-15 | [33530](https://github.com/airbytehq/airbyte/pull/33530) | Fix typo in `Pivot Category` list | -| 0.6.4 | 2023-10-19 | [31599](https://github.com/airbytehq/airbyte/pull/31599) | Base image migration: remove Dockerfile and use the python-connector-base image | -| 0.6.3 | 2023-10-13 | [31396](https://github.com/airbytehq/airbyte/pull/31396) | Fix pagination for reporting | -| 0.6.2 | 2023-08-23 | [31221](https://github.com/airbytehq/airbyte/pull/31221) | Increase max time between messages to 24 hours | -| 0.6.1 | 2023-08-23 | [29600](https://github.com/airbytehq/airbyte/pull/29600) | Update field descriptions | -| 0.6.0 | 2023-08-22 | [29721](https://github.com/airbytehq/airbyte/pull/29721) | Add `Conversions` stream | -| 0.5.0 | 2023-08-14 | [29175](https://github.com/airbytehq/airbyte/pull/29175) | Add Custom report Constructor | -| 0.4.0 | 2023-08-08 | [29175](https://github.com/airbytehq/airbyte/pull/29175) | Add analytics streams | -| 0.3.1 | 2023-08-08 | [29189](https://github.com/airbytehq/airbyte/pull/29189) | Fix empty accounts field | -| 0.3.0 | 2023-08-07 | [29045](https://github.com/airbytehq/airbyte/pull/29045) | Add new fields to schemas; convert datetime fields to `rfc3339` | -| 0.2.1 | 2023-05-30 | [26780](https://github.com/airbytehq/airbyte/pull/26780) | Reduce records limit for Creatives Stream | -| 0.2.0 | 2023-05-23 | [26372](https://github.com/airbytehq/airbyte/pull/26372) | Migrate to LinkedIn API version: May 2023 | -| 0.1.16 | 2023-05-24 | [26512](https://github.com/airbytehq/airbyte/pull/26512) | Removed authSpecification from spec.json in favour of advancedAuth | -| 0.1.15 | 2023-02-13 | [22940](https://github.com/airbytehq/airbyte/pull/22940) | Specified date formatting in specification | -| 0.1.14 | 2023-02-03 | [22361](https://github.com/airbytehq/airbyte/pull/22361) | Turn on default HttpAvailabilityStrategy | -| 0.1.13 | 2023-01-27 | [22013](https://github.com/airbytehq/airbyte/pull/22013) | For adDirectSponsoredContents stream skip accounts which are part of organization | -| 0.1.12 | 2022-10-18 | [18111](https://github.com/airbytehq/airbyte/pull/18111) | For adDirectSponsoredContents stream skip accounts which are part of organization | -| 0.1.11 | 2022-10-07 | [17724](https://github.com/airbytehq/airbyte/pull/17724) | Retry 429/5xx errors when refreshing access token | -| 0.1.10 | 2022-09-28 | [17326](https://github.com/airbytehq/airbyte/pull/17326) | Migrate to per-stream states. | -| 0.1.9 | 2022-07-21 | [14924](https://github.com/airbytehq/airbyte/pull/14924) | Remove `additionalProperties` field from schemas | -| 0.1.8 | 2022-06-07 | [13495](https://github.com/airbytehq/airbyte/pull/13495) | Fixed `base-normalization` issue on `Destination Redshift` caused by wrong casting of `pivot` column | -| 0.1.7 | 2022-05-04 | [12482](https://github.com/airbytehq/airbyte/pull/12482) | Update input configuration copy | -| 0.1.6 | 2022-04-04 | [11690](https://github.com/airbytehq/airbyte/pull/11690) | Small documentation corrections | -| 0.1.5 | 2021-12-21 | [8984](https://github.com/airbytehq/airbyte/pull/8984) | Update connector fields title/description | -| 0.1.4 | 2021-12-02 | [8382](https://github.com/airbytehq/airbyte/pull/8382) | Modify log message in rate-limit cases | -| 0.1.3 | 2021-11-11 | [7839](https://github.com/airbytehq/airbyte/pull/7839) | Added OAuth support | -| 0.1.2 | 2021-11-08 | [7499](https://github.com/airbytehq/airbyte/pull/7499) | Remove base-python dependencies | -| 0.1.1 | 2021-10-02 | [6610](https://github.com/airbytehq/airbyte/pull/6610) | Fix for `Campaigns/targetingCriteria` transformation, coerced `Creatives/variables/values` to string by default | -| 0.1.0 | 2021-09-05 | [5285](https://github.com/airbytehq/airbyte/pull/5285) | Initial release of Native LinkedIn Ads connector for Airbyte | +| 5.6.0-rc.1 | 2025-10-29 | [68614](https://github.com/airbytehq/airbyte/pull/68614) | Upgrade to latest CDK to only include the selected columns of the schema in API requests for ad analytics streams | +| 5.5.5 | 2025-10-28 | [68626](https://github.com/airbytehq/airbyte/pull/68626) | Increase concurrency and introduce initial attempt at API budget | +| 5.5.4 | 2025-10-21 | [64967](https://github.com/airbytehq/airbyte/pull/64967) | Update dependencies | +| 5.5.3 | 2025-10-14 | [67564](https://github.com/airbytehq/airbyte/pull/67564) | Upgrade to CDK v7. | +| 5.5.2 | 2025-07-16 | [63336](https://github.com/airbytehq/airbyte/pull/63336) | Promoting release candidate 5.5.2-rc.1 to a main version. | +| 5.5.2-rc.1 | 2025-06-23 | [60996](https://github.com/airbytehq/airbyte/pull/60996) | Fix to properly manage pagination for `Lead forms` and `Lead form responses` streams | +| 5.5.1 | 2025-06-18 | [61639](https://github.com/airbytehq/airbyte/pull/61639) | Reduce default concurrency level to 3 and enable configurability via `num_workers` config property | +| 5.5.0 | 2025-04-28 | [59116](https://github.com/airbytehq/airbyte/pull/59116) | Promoting release candidate 5.5.0-rc.1 to a main version. | +| 5.5.0-rc.1 | 2025-04-25 | [58628](https://github.com/airbytehq/airbyte/pull/58628) | Convert to manifest-only format | +| 5.4.1 | 2025-04-23 | [58134](https://github.com/airbytehq/airbyte/pull/58134) | Fix to properly retrieve `approximateMemberReach` for `adAnalytics` streams following `v5.3.3`. | +| 5.4.0 | 2025-04-22 | [58593](https://github.com/airbytehq/airbyte/pull/58593) | Promoting release candidate 5.4.0-rc.1 to a main version. | +| 5.4.0-rc.1 | 2025-04-18 | [58114](https://github.com/airbytehq/airbyte/pull/58114) | Removes custom retrievers and cursors from analytics streams so that they can take up concurrency. | +| 5.3.3 | 2025-03-12 | [55724](https://github.com/airbytehq/airbyte/pull/55724) | Update outdated schema `approximateUniqueImpressions` to new `approximateMemberReach` for `adAnalytics` streams. | +| 5.3.2 | 2025-03-08 | [55447](https://github.com/airbytehq/airbyte/pull/55447) | Update dependencies | +| 5.3.1 | 2025-03-05 | [55211](https://github.com/airbytehq/airbyte/pull/55211) | Update dependencies | +| 5.3.0 | 2025-03-02 | [55171](https://github.com/airbytehq/airbyte/pull/55171) | Migrate API to v202502 | +| 5.2.3 | 2025-03-01 | [54813](https://github.com/airbytehq/airbyte/pull/54813) | Update dependencies | +| 5.2.2 | 2025-02-22 | [53308](https://github.com/airbytehq/airbyte/pull/53308) | Update dependencies | +| 5.2.1 | 2025-02-10 | [53611](https://github.com/airbytehq/airbyte/pull/53611) | Add schema precisions for `Lead forms` and `Lead form responses` streams | +| 5.2.0 | 2025-02-04 | [52047](https://github.com/airbytehq/airbyte/pull/52047) | Add `Lead forms` and `Lead form responses` new streams - See Limits & considerations | +| 5.1.6 | 2025-02-02 | [49458](https://github.com/airbytehq/airbyte/pull/49458) | Update Linkedin Ads API version to 202410 for creatives stream | +| 5.1.5 | 2025-02-01 | [52791](https://github.com/airbytehq/airbyte/pull/52791) | Update dependencies | +| 5.1.4 | 2025-01-30 | [52604](https://github.com/airbytehq/airbyte/pull/52604) | Fix state error | +| 5.1.3 | 2025-01-22 | [52604](https://github.com/airbytehq/airbyte/pull/52604) | Update CDK to production ^6 | +| 5.1.2 | 2025-01-25 | [52253](https://github.com/airbytehq/airbyte/pull/52253) | Update dependencies | +| 5.1.1 | 2025-01-15 | [47092](https://github.com/airbytehq/airbyte/pull/47092) | Starting with this version, the Docker image is now rootless. Please note that this and future versions will not be compatible with Airbyte versions earlier than 0.64 | +| 5.1.0 | 2025-01-14 | [48863](https://github.com/airbytehq/airbyte/pull/48863) | Custom streams moved to manifest implementation & URL Error Handling | +| 5.0.0 | 2024-11-26 | [48451](https://github.com/airbytehq/airbyte/pull/48451) | Update primary keys for streams ad_campaign_analytics, Custom Ad Analytics Reports and account_users | +| 4.1.4 | 2024-10-12 | [46862](https://github.com/airbytehq/airbyte/pull/46862) | Update dependencies | +| 4.1.3 | 2024-10-05 | [46433](https://github.com/airbytehq/airbyte/pull/46433) | Update dependencies | +| 4.1.2 | 2024-09-28 | [46171](https://github.com/airbytehq/airbyte/pull/46171) | Update dependencies | +| 4.1.1 | 2024-09-21 | [45774](https://github.com/airbytehq/airbyte/pull/45774) | Update dependencies | +| 4.1.0 | 2024-09-20 | [44370](https://github.com/airbytehq/airbyte/pull/44370) | Migrate to low-code | +| 4.0.6 | 2024-09-14 | [45532](https://github.com/airbytehq/airbyte/pull/45532) | Update dependencies | +| 4.0.5 | 2024-09-07 | [45209](https://github.com/airbytehq/airbyte/pull/45209) | Update dependencies | +| 4.0.4 | 2024-08-31 | [44950](https://github.com/airbytehq/airbyte/pull/44950) | Update dependencies | +| 4.0.3 | 2024-08-24 | [44682](https://github.com/airbytehq/airbyte/pull/44682) | Update dependencies | +| 4.0.2 | 2024-08-17 | [44220](https://github.com/airbytehq/airbyte/pull/44220) | Update dependencies | +| 4.0.1 | 2024-08-10 | [43629](https://github.com/airbytehq/airbyte/pull/43629) | Update dependencies | +| 4.0.0 | 2024-08-07 | [43359](https://github.com/airbytehq/airbyte/pull/43359) | Revert low code migration | +| 3.0.1 | 2024-08-03 | [43087](https://github.com/airbytehq/airbyte/pull/43087) | Update dependencies | +| 3.0.0 | 2024-06-18 | [38314](https://github.com/airbytehq/airbyte/pull/38314) | Migrate to low-code | +| 2.1.12 | 2024-07-27 | [42728](https://github.com/airbytehq/airbyte/pull/42728) | Update dependencies | +| 2.1.11 | 2024-07-20 | [42291](https://github.com/airbytehq/airbyte/pull/42291) | Update dependencies | +| 2.1.10 | 2024-07-13 | [41710](https://github.com/airbytehq/airbyte/pull/41710) | Update dependencies | +| 2.1.9 | 2024-07-10 | [41517](https://github.com/airbytehq/airbyte/pull/41517) | Update dependencies | +| 2.1.8 | 2024-07-09 | [41315](https://github.com/airbytehq/airbyte/pull/41315) | Update dependencies | +| 2.1.7 | 2024-07-06 | [40868](https://github.com/airbytehq/airbyte/pull/40868) | Update dependencies | +| 2.1.6 | 2024-06-25 | [40331](https://github.com/airbytehq/airbyte/pull/40331) | Update dependencies | +| 2.1.5 | 2024-06-22 | [39998](https://github.com/airbytehq/airbyte/pull/39998) | Update dependencies | +| 2.1.4 | 2024-06-16 | [39442](https://github.com/airbytehq/airbyte/pull/39442) | Fix README commands, change spec from json to yaml, fix schema states to object | +| 2.1.3 | 2024-06-06 | [39240](https://github.com/airbytehq/airbyte/pull/39240) | [autopull] Upgrade base image to v1.2.2 | +| 2.1.2 | 2024-05-07 | [36648](https://github.com/airbytehq/airbyte/pull/36648) | Schema descriptions | +| 2.1.1 | 2024-05-07 | [38013](https://github.com/airbytehq/airbyte/pull/38013) | Fix an issue where the `Accounts` stream did not correctly handle provided account IDs | +| 2.1.0 | 2024-04-30 | [37573](https://github.com/airbytehq/airbyte/pull/37573) | Update API version to `202404`; add cursor-based pagination | +| 2.0.0 | 2024-04-24 | [37531](https://github.com/airbytehq/airbyte/pull/37531) | Change primary key for Analytics Streams | +| 1.0.1 | 2024-03-28 | [34152](https://github.com/airbytehq/airbyte/pull/34152) | Proceed pagination if return less than expected | +| 1.0.0 | 2024-04-10 | [36927](https://github.com/airbytehq/airbyte/pull/36927) | Update primary key for Analytics Streams | +| 0.8.0 | 2024-03-19 | [36267](https://github.com/airbytehq/airbyte/pull/36267) | Pin airbyte-cdk version to `^0` | +| 0.7.0 | 2024-02-20 | [35465](https://github.com/airbytehq/airbyte/pull/35465) | Per-error reporting and continue sync on stream failures | +| 0.6.8 | 2024-02-09 | [35086](https://github.com/airbytehq/airbyte/pull/35086) | Manage dependencies with Poetry | +| 0.6.7 | 2024-01-11 | [34152](https://github.com/airbytehq/airbyte/pull/34152) | Prepare for airbyte-lib | +| 0.6.6 | 2024-01-15 | [34222](https://github.com/airbytehq/airbyte/pull/34222) | Use stream slices for Analytics streams | +| 0.6.5 | 2023-12-15 | [33530](https://github.com/airbytehq/airbyte/pull/33530) | Fix typo in `Pivot Category` list | +| 0.6.4 | 2023-10-19 | [31599](https://github.com/airbytehq/airbyte/pull/31599) | Base image migration: remove Dockerfile and use the python-connector-base image | +| 0.6.3 | 2023-10-13 | [31396](https://github.com/airbytehq/airbyte/pull/31396) | Fix pagination for reporting | +| 0.6.2 | 2023-08-23 | [31221](https://github.com/airbytehq/airbyte/pull/31221) | Increase max time between messages to 24 hours | +| 0.6.1 | 2023-08-23 | [29600](https://github.com/airbytehq/airbyte/pull/29600) | Update field descriptions | +| 0.6.0 | 2023-08-22 | [29721](https://github.com/airbytehq/airbyte/pull/29721) | Add `Conversions` stream | +| 0.5.0 | 2023-08-14 | [29175](https://github.com/airbytehq/airbyte/pull/29175) | Add Custom report Constructor | +| 0.4.0 | 2023-08-08 | [29175](https://github.com/airbytehq/airbyte/pull/29175) | Add analytics streams | +| 0.3.1 | 2023-08-08 | [29189](https://github.com/airbytehq/airbyte/pull/29189) | Fix empty accounts field | +| 0.3.0 | 2023-08-07 | [29045](https://github.com/airbytehq/airbyte/pull/29045) | Add new fields to schemas; convert datetime fields to `rfc3339` | +| 0.2.1 | 2023-05-30 | [26780](https://github.com/airbytehq/airbyte/pull/26780) | Reduce records limit for Creatives Stream | +| 0.2.0 | 2023-05-23 | [26372](https://github.com/airbytehq/airbyte/pull/26372) | Migrate to LinkedIn API version: May 2023 | +| 0.1.16 | 2023-05-24 | [26512](https://github.com/airbytehq/airbyte/pull/26512) | Removed authSpecification from spec.json in favour of advancedAuth | +| 0.1.15 | 2023-02-13 | [22940](https://github.com/airbytehq/airbyte/pull/22940) | Specified date formatting in specification | +| 0.1.14 | 2023-02-03 | [22361](https://github.com/airbytehq/airbyte/pull/22361) | Turn on default HttpAvailabilityStrategy | +| 0.1.13 | 2023-01-27 | [22013](https://github.com/airbytehq/airbyte/pull/22013) | For adDirectSponsoredContents stream skip accounts which are part of organization | +| 0.1.12 | 2022-10-18 | [18111](https://github.com/airbytehq/airbyte/pull/18111) | For adDirectSponsoredContents stream skip accounts which are part of organization | +| 0.1.11 | 2022-10-07 | [17724](https://github.com/airbytehq/airbyte/pull/17724) | Retry 429/5xx errors when refreshing access token | +| 0.1.10 | 2022-09-28 | [17326](https://github.com/airbytehq/airbyte/pull/17326) | Migrate to per-stream states. | +| 0.1.9 | 2022-07-21 | [14924](https://github.com/airbytehq/airbyte/pull/14924) | Remove `additionalProperties` field from schemas | +| 0.1.8 | 2022-06-07 | [13495](https://github.com/airbytehq/airbyte/pull/13495) | Fixed `base-normalization` issue on `Destination Redshift` caused by wrong casting of `pivot` column | +| 0.1.7 | 2022-05-04 | [12482](https://github.com/airbytehq/airbyte/pull/12482) | Update input configuration copy | +| 0.1.6 | 2022-04-04 | [11690](https://github.com/airbytehq/airbyte/pull/11690) | Small documentation corrections | +| 0.1.5 | 2021-12-21 | [8984](https://github.com/airbytehq/airbyte/pull/8984) | Update connector fields title/description | +| 0.1.4 | 2021-12-02 | [8382](https://github.com/airbytehq/airbyte/pull/8382) | Modify log message in rate-limit cases | +| 0.1.3 | 2021-11-11 | [7839](https://github.com/airbytehq/airbyte/pull/7839) | Added OAuth support | +| 0.1.2 | 2021-11-08 | [7499](https://github.com/airbytehq/airbyte/pull/7499) | Remove base-python dependencies | +| 0.1.1 | 2021-10-02 | [6610](https://github.com/airbytehq/airbyte/pull/6610) | Fix for `Campaigns/targetingCriteria` transformation, coerced `Creatives/variables/values` to string by default | +| 0.1.0 | 2021-09-05 | [5285](https://github.com/airbytehq/airbyte/pull/5285) | Initial release of Native LinkedIn Ads connector for Airbyte |
From b1ea76d2a773903a8a55f2ae48e5c35586b666b4 Mon Sep 17 00:00:00 2001 From: "Ryan Br..." Date: Mon, 30 Mar 2026 13:29:37 -0700 Subject: [PATCH 047/379] =?UTF-8?q?Bump=20cdk=20in=20gcs=20data=20lake=20t?= =?UTF-8?q?o=201.0.7.=20Fixes=20sort=20order=20handling=20during=20?= =?UTF-8?q?=E2=80=A6=20(#75630)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../connectors/destination-gcs-data-lake/gradle.properties | 2 +- .../connectors/destination-gcs-data-lake/metadata.yaml | 2 +- docs/integrations/destinations/gcs-data-lake.md | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/destination-gcs-data-lake/gradle.properties b/airbyte-integrations/connectors/destination-gcs-data-lake/gradle.properties index c710a039ec85..9aedf74c38ba 100644 --- a/airbyte-integrations/connectors/destination-gcs-data-lake/gradle.properties +++ b/airbyte-integrations/connectors/destination-gcs-data-lake/gradle.properties @@ -1,3 +1,3 @@ testExecutionConcurrency=1 -cdkVersion=0.2.8 +cdkVersion=1.0.7 JunitMethodExecutionTimeout=10m diff --git a/airbyte-integrations/connectors/destination-gcs-data-lake/metadata.yaml b/airbyte-integrations/connectors/destination-gcs-data-lake/metadata.yaml index 4801b7b6192b..e5f0cdd32a07 100644 --- a/airbyte-integrations/connectors/destination-gcs-data-lake/metadata.yaml +++ b/airbyte-integrations/connectors/destination-gcs-data-lake/metadata.yaml @@ -21,7 +21,7 @@ data: alias: airbyte-connector-testing-secret-store connectorType: destination definitionId: 8c8a2d3e-1b4f-4a9c-9e7d-6f5a4b3c2d1e - dockerImageTag: 1.0.7 + dockerImageTag: 1.0.8 dockerRepository: airbyte/destination-gcs-data-lake documentationUrl: https://docs.airbyte.com/integrations/destinations/gcs-data-lake githubIssueLabel: destination-gcs-data-lake diff --git a/docs/integrations/destinations/gcs-data-lake.md b/docs/integrations/destinations/gcs-data-lake.md index 7f745aab3c97..a5e1d06234cd 100644 --- a/docs/integrations/destinations/gcs-data-lake.md +++ b/docs/integrations/destinations/gcs-data-lake.md @@ -218,6 +218,7 @@ This destination supports [namespaces](https://docs.airbyte.com/platform/using-a | Version | Date | Pull Request | Subject | |:--------|:-----------|:-------------------------------------------------------------|:--------------------------------------------------------------------------------------| +| 1.0.8 | 2026-03-30 | [75630](https://github.com/airbytehq/airbyte/pull/75630) | Upgrade CDK to 1.0.7: fix sort order handling during schema evolution. | | 1.0.7 | 2026-02-04 | [72855](https://github.com/airbytehq/airbyte/pull/72855) | Upgrade CDK to 0.2.8 | | 1.0.6 | 2026-01-23 | [72300](https://github.com/airbytehq/airbyte/pull/72300) | Upgrade CDK to 0.2.0 | | 1.0.5 | 2026-01-14 | [71760](https://github.com/airbytehq/airbyte/pull/71760) | Restore integration tests in CI. Workaround DI error. | From 498f500ad3543d576772e257e0a3a6ff1f5d9fd6 Mon Sep 17 00:00:00 2001 From: Sunil Kuruba Date: Mon, 30 Mar 2026 13:35:03 -0700 Subject: [PATCH 048/379] deps(destination-bigquery): Upgrade BQ cloud deps + CDK version (progressive rollout) (#75541) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../destination-bigquery/build.gradle | 2 +- .../destination-bigquery/gradle.properties | 2 +- .../destination-bigquery/metadata.yaml | 4 +- docs/integrations/destinations/bigquery.md | 167 +++++++++--------- 4 files changed, 88 insertions(+), 87 deletions(-) diff --git a/airbyte-integrations/connectors/destination-bigquery/build.gradle b/airbyte-integrations/connectors/destination-bigquery/build.gradle index 1393cf69e83a..a9ffdb980e98 100644 --- a/airbyte-integrations/connectors/destination-bigquery/build.gradle +++ b/airbyte-integrations/connectors/destination-bigquery/build.gradle @@ -39,7 +39,7 @@ dependencies { // but we're still waiting for google to cut another release. // so for now, use a specific bigquery version. // https://github.com/airbytehq/airbyte-internal-issues/issues/13662 - implementation 'com.google.cloud:google-cloud-bigquery:2.53.0' + implementation 'com.google.cloud:google-cloud-bigquery:2.62.0' integrationTestImplementation 'com.google.cloud:google-cloud-bigquery' testImplementation "io.mockk:mockk:1.13.13" diff --git a/airbyte-integrations/connectors/destination-bigquery/gradle.properties b/airbyte-integrations/connectors/destination-bigquery/gradle.properties index b3a770fa0b0e..74fc0e4ac134 100644 --- a/airbyte-integrations/connectors/destination-bigquery/gradle.properties +++ b/airbyte-integrations/connectors/destination-bigquery/gradle.properties @@ -1,3 +1,3 @@ testExecutionConcurrency=-1 JunitMethodExecutionTimeout=10m -cdkVersion=0.2.0 +cdkVersion=1.0.6 diff --git a/airbyte-integrations/connectors/destination-bigquery/metadata.yaml b/airbyte-integrations/connectors/destination-bigquery/metadata.yaml index b4743b946b57..9761220975da 100644 --- a/airbyte-integrations/connectors/destination-bigquery/metadata.yaml +++ b/airbyte-integrations/connectors/destination-bigquery/metadata.yaml @@ -6,7 +6,7 @@ data: connectorSubtype: database connectorType: destination definitionId: 22f6c74f-5699-40ff-833c-4a879ea40133 - dockerImageTag: 3.0.17 + dockerImageTag: 3.0.18-rc.1 dockerRepository: airbyte/destination-bigquery documentationUrl: https://docs.airbyte.com/integrations/destinations/bigquery githubIssueLabel: destination-bigquery @@ -39,7 +39,7 @@ data: message: "If you never interact with the raw tables, you can upgrade without taking any action. Otherwise, make sure to read the migration guide for more details." upgradeDeadline: "2026-07-31" rolloutConfiguration: - enableProgressiveRollout: false + enableProgressiveRollout: true resourceRequirements: jobSpecific: - jobType: sync diff --git a/docs/integrations/destinations/bigquery.md b/docs/integrations/destinations/bigquery.md index 2a33506c375a..a682ac47ac8e 100644 --- a/docs/integrations/destinations/bigquery.md +++ b/docs/integrations/destinations/bigquery.md @@ -250,94 +250,95 @@ This destination supports [namespaces](https://docs.airbyte.com/platform/using-a | Version | Date | Pull Request | Subject | |:------------|:-----------|:-----------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 3.0.17 | 2026-01-28 | [72427](https://github.com/airbytehq/airbyte/pull/72427) | Finalize upgrade CDK to 0.2.0 | +| 3.0.18-rc.1 | 2026-03-27 | [75541](https://github.com/airbytehq/airbyte/pull/75541) | Upgrade BigQuery Cloud dependencies and CDK version | +| 3.0.17 | 2026-01-28 | [72427](https://github.com/airbytehq/airbyte/pull/72427) | Finalize upgrade CDK to 0.2.0 | | 3.0.17-rc.1 | 2026-01-26 | [72296](https://github.com/airbytehq/airbyte/pull/72296) | Upgrade CDK to 0.2.0 | | 3.0.16 | 2025-11-25 | [67401](https://github.com/airbytehq/airbyte/pull/67401) | Add backticks to column names in SQL generation to prevent syntax errors. | | 3.0.15 | 2025-11-13 | [69307](https://github.com/airbytehq/airbyte/pull/69307) | Handle out-of-range timestamps/times. | | 3.0.14 | 2025-11-11 | [69231](https://github.com/airbytehq/airbyte/pull/69231) | Upgrade to Bulk CDK 0.1.74. | | 3.0.13 | 2025-11-05 | [69126](https://github.com/airbytehq/airbyte/pull/69126) | Upgrade to Bulk CDK 0.1.61. | -| 3.0.12 | 2025-10-31 | [69083](https://github.com/airbytehq/airbyte/pull/69083) | Fail loudly if Bigquery detects bad records. | -| 3.0.11 | 2025-10-28 | [68671](https://github.com/airbytehq/airbyte/pull/68671) | Log record count per load job. | -| 3.0.10 | 2025-10-21 | [67153](https://github.com/airbytehq/airbyte/pull/67153) | Implement new proto schema implementation | -| 3.0.9 | 2025-10-17 | [68152](https://github.com/airbytehq/airbyte/pull/68152) | Update to new TableOperationsClient interface. | -| 3.0.8 | 2025-10-06 | [67078](https://github.com/airbytehq/airbyte/pull/67078) | Remove memory limit for sync jobs to improve performance and resource utilization. | -| 3.0.7 | 2025-09-03 | [65905](https://github.com/airbytehq/airbyte/pull/65905) | Promoting release candidate 3.0.7-rc.1 to a main version. | -| 3.0.7-rc.1 | 2025-08-27 | [65114](https://github.com/airbytehq/airbyte/pull/65114) | Implement SOCKET+PROTO mode support. | -| 3.0.6 | 2025-07-24 | [63700](https://github.com/airbytehq/airbyte/pull/63700) | Improve error reporting for Billing errors. | -| 3.0.5 | 2025-07-15 | [63312](https://github.com/airbytehq/airbyte/pull/63312) | Pull in upstream fix to support null chars in GCS staging mode. | -| 3.0.4 | 2025-07-15 | [63327](https://github.com/airbytehq/airbyte/pull/63327) | Improve error reporting for Billing errors. | -| 3.0.3 | 2025-07-02 | [62495](https://github.com/airbytehq/airbyte/pull/62495) | Improve error reporting for misconfigured connections; improve support for complex types. | -| 3.0.2 | 2025-06-26 | [62106](https://github.com/airbytehq/airbyte/pull/62106) | Improve error reporting during schema evolution. | -| 3.0.1 | 2025-06-26 | [62085](https://github.com/airbytehq/airbyte/pull/62085) | Correctly handle stream names/namespaces and column names which start with a digit. | -| 3.0.0 | 2025-06-25 | [59752](https://github.com/airbytehq/airbyte/pull/59752) | Upgrade to direct-load tables; add option for soft CDC deletes. | -| 2.12.4 | 2025-06-24 | [62045](https://github.com/airbytehq/airbyte/pull/62045) | Promoting release candidate 2.12.4-rc.6 to a main version. | -| 2.12.4-rc.6 | 2025-06-24 | [62041](https://github.com/airbytehq/airbyte/pull/62041) | 2.12.4 RC 6 More retries is better retries | -| 2.12.4-rc.5 | 2025-06-23 | [62016](https://github.com/airbytehq/airbyte/pull/62016) | 2.12.4 RC 5 Handle records up to 20MiB | -| 2.12.4-rc.4 | 2025-06-23 | [62014](https://github.com/airbytehq/airbyte/pull/62014) | 2.12.4 RC 4 Improve JSON schema parser's behavior on invalid source schemas | -| 2.12.4-rc.3 | 2025-06-18 | [61702](https://github.com/airbytehq/airbyte/pull/61702) | 2.12.4 RC 3 Fix an issue with streams with special chars on bulk loader | -| 2.12.4-rc.2 | 2025-06-18 | [61700](https://github.com/airbytehq/airbyte/pull/61700) | 2.12.4 RC 2 (throw more informative error on invalid catalog) | -| 2.12.4-rc.1 | 2025-06-16 | [61637](https://github.com/airbytehq/airbyte/pull/61637) | 2.12.4 RC 1 (theoretically equivalent to 2.12.0, but with fixed global state handling in CDK) | -| 2.12.3 | 2025-06-16 | [61648](https://github.com/airbytehq/airbyte/pull/61648) | This is not the release you are looking for. identical to 2.10.2 | -| 2.12.1 | 2025-06-13 | [61588](https://github.com/airbytehq/airbyte/pull/61588) | ~~Publish version to account for possible duplicate publishing in pipeline. Noop change.~~ WARNING: THIS HAS A BUG. DO NOT USE. | -| 2.12.0 | 2025-06-06 | [61432](https://github.com/airbytehq/airbyte/pull/61432) | Improve performance in GCS staging mode by writing GZIP-compressed files. | -| 2.11.4 | 2025-05-30 | [61018](https://github.com/airbytehq/airbyte/pull/61018) | Always emit a useful error message when erroring during sync startup. | -| 2.11.3 | 2025-06-02 | [61321](https://github.com/airbytehq/airbyte/pull/61321) | CHECK operation doesn't need to drop the dataset anymore. | -| 2.11.2 | 2025-05-29 | [60986](https://github.com/airbytehq/airbyte/pull/60986) | CHECK operation uses configured default dataset instead of `airbyte_internal_test`. | -| 2.11.1 | 2025-05-29 | [60973](https://github.com/airbytehq/airbyte/pull/60973) | Improve error recovery when a stream's sync mode and schema are both changed and the previous sync exited uncleanly. | -| 2.11.0 | 2025-05-27 | [60922](https://github.com/airbytehq/airbyte/pull/60922) | Promoting release candidate 2.11.0-rc.7 to a main version. | -| 2.11.0-rc.7 | 2025-05-22 | [60865](https://github.com/airbytehq/airbyte/pull/60865) | Add a random element to the check sync namespace | -| 2.11.0-rc.6 | 2025-05-22 | [60859](https://github.com/airbytehq/airbyte/pull/60859) | Improve bigquery quota usage in standard inserts for streams with heavy load | -| 2.11.0-rc.5 | 2025-05-21 | [60841](https://github.com/airbytehq/airbyte/pull/60841) | Improve behavior in syncs with many state messages | -| 2.11.0-rc.4 | 2025-05-19 | [60791](https://github.com/airbytehq/airbyte/pull/60791) | Fix bug in detecting schema change when stream has no columns | -| 2.11.0-rc.3 | 2025-05-16 | [60324](https://github.com/airbytehq/airbyte/pull/60324) | Fix bug in syncs with many state message | -| 2.11.0-rc.2 | 2025-05-15 | [60302](https://github.com/airbytehq/airbyte/pull/60302) | Fix bugs in handling special characters / uppercase characters in column names | -| 2.11.0-rc.1 | 2025-05-08 | [59729](https://github.com/airbytehq/airbyte/pull/59729) | Version 2.11.0 RC 1 | -| 2.10.2 | 2025-04-29 | [59142](https://github.com/airbytehq/airbyte/pull/59142) | Add `europe-north2` region. | -| 2.10.1 | 2025-04-14 | [57569](https://github.com/airbytehq/airbyte/pull/57569) | Remove StringSubstitutor usage | -| 2.10.0 | 2025-04-02 | [56982](https://github.com/airbytehq/airbyte/pull/56982) | Change default raw table partitioning scheme to be on `_airbyte_extracted_at`; upgrade CDK | -| 2.9.3 | 2025-03-24 | [56355](https://github.com/airbytehq/airbyte/pull/56355) | Upgrade to airbyte/java-connector-base:2.0.1 to be M4 compatible. | -| 2.9.2 | 2025-01-10 | [51482](https://github.com/airbytehq/airbyte/pull/51482) | Use a non root base image | -| 2.9.1 | 2024-12-18 | [49902](https://github.com/airbytehq/airbyte/pull/49902) | Use a base image: airbyte/java-connector-base:1.0.0 | -| 2.9.0 | 2024-09-18 | [45433](https://github.com/airbytehq/airbyte/pull/45433) | upgrade all dependencies | -| 2.8.9 | 2024-08-20 | [44476](https://github.com/airbytehq/airbyte/pull/44476) | Increase message parsing limit to 100mb | -| 2.8.8 | 2024-08-22 | [44526](https://github.com/airbytehq/airbyte/pull/44526) | Revert protocol compliance fix | -| 2.8.7 | 2024-08-15 | [42504](https://github.com/airbytehq/airbyte/pull/42504) | Fix bug in refreshes logic (already mitigated in platform, just fixing protocol compliance) | -| 2.8.6 | 2024-07-30 | [42511](https://github.com/airbytehq/airbyte/pull/42511) | Added a copy operation to validate copy permissions in the check function | -| 2.8.5 | 2024-07-22 | [42407](https://github.com/airbytehq/airbyte/pull/42407) | Batched Standard Inserts is default loading mode | -| 2.8.4 | 2024-07-15 | [41968](https://github.com/airbytehq/airbyte/pull/41968) | Don't hang forever on empty stream list; shorten error message on INCOMPLETE stream status | -| 2.8.3 | 2024-07-12 | [41674](https://github.com/airbytehq/airbyte/pull/41674) | Upgrade to latest CDK | -| 2.8.2 | 2024-07-08 | [41041](https://github.com/airbytehq/airbyte/pull/41041) | Fix resume logic in truncate refreshes to prevent data loss | -| 2.8.1 | 2024-06-25 | [39379](https://github.com/airbytehq/airbyte/pull/39379) | Removing requirement of a redundant permission bigquery.datasets.create permission | -| 2.8.0 | 2024-06-21 | [39904](https://github.com/airbytehq/airbyte/pull/39904) | Convert all production code to kotlin | -| 2.7.1 | 2024-06-17 | [39526](https://github.com/airbytehq/airbyte/pull/39526) | Internal code change for improved error reporting in case of source/platform failure (`INCOMPLETE` stream status / empty ConfiguredCatalog). | -| 2.7.0 | 2024-06-17 | [38713](https://github.com/airbytehq/airbyte/pull/38713) | Support for [refreshes](/platform/operator-guides/refreshes) and resumable full refresh. WARNING: You must upgrade to platform 0.63.7 before upgrading to this connector version. | -| 2.6.3 | 2024-06-10 | [38331](https://github.com/airbytehq/airbyte/pull/38331) | Internal code changes in preparation for future feature release | -| 2.6.2 | 2024-06-07 | [38764](https://github.com/airbytehq/airbyte/pull/38764) | Increase message length limit to 50MiB | -| 2.6.1 | 2024-05-29 | [38770](https://github.com/airbytehq/airbyte/pull/38770) | Internal code change (switch to CDK artifact) | -| 2.6.0 | 2024-05-28 | [38359](https://github.com/airbytehq/airbyte/pull/38359) | Propagate airbyte_meta from sources; add generation_id column | -| 2.5.1 | 2024-05-22 | [38591](https://github.com/airbytehq/airbyte/pull/38591) | Bugfix to include forward-slash when cleaning up stage | -| 2.5.0 | 2024-05-22 | [38132](https://github.com/airbytehq/airbyte/pull/38132) | Major rewrite of existing code, Adapting to CDK changes introduced in [38107](https://github.com/airbytehq/airbyte/pull/38107) | -| 2.4.20 | 2024-05-13 | [38131](https://github.com/airbytehq/airbyte/pull/38131) | Cleanup `BigQueryWriteConfig` and reuse `StreamConfig`; Adapt to `StreamConfig` signature changes | -| 2.4.19 | 2024-05-10 | [38125](https://github.com/airbytehq/airbyte/pull/38125) | adopt latest CDK code | -| 2.4.18 | 2024-05-10 | [38111](https://github.com/airbytehq/airbyte/pull/38111) | No functional changes, deleting unused code | -| 2.4.17 | 2024-05-09 | [38098](https://github.com/airbytehq/airbyte/pull/38098) | Internal build structure change | -| 2.4.16 | 2024-05-08 | [37714](https://github.com/airbytehq/airbyte/pull/37714) | Adopt CDK 0.34.0 | -| 2.4.15 | 2024-05-07 | [34611](https://github.com/airbytehq/airbyte/pull/34611) | Adopt CDK 0.33.2 | -| 2.4.14 | 2024-02-25 | [37584](https://github.com/airbytehq/airbyte/pull/37584) | Remove unused insecure dependencies from CDK | -| 2.4.13 | 2024-02-25 | [36899](https://github.com/airbytehq/airbyte/pull/36899) | adopt latest CDK | -| 2.4.12 | 2024-03-04 | [35315](https://github.com/airbytehq/airbyte/pull/35315) | Adopt CDK 0.23.11 | -| 2.4.11 | 2024-02-22 | [35569](https://github.com/airbytehq/airbyte/pull/35569) | Fix logging bug. | -| 2.4.10 | 2024-02-15 | [35240](https://github.com/airbytehq/airbyte/pull/35240) | Adopt CDK 0.20.9 | -| 2.4.9 | 2024-02-15 | [35285](https://github.com/airbytehq/airbyte/pull/35285) | Adopt CDK 0.20.8 | -| 2.4.8 | 2024-02-12 | [35144](https://github.com/airbytehq/airbyte/pull/35144) | Adopt CDK 0.20.2 | -| 2.4.7 | 2024-02-12 | [35111](https://github.com/airbytehq/airbyte/pull/35111) | Adopt CDK 0.20.1 | -| 2.4.6 | 2024-02-09 | [34575](https://github.com/airbytehq/airbyte/pull/34575) | Adopt CDK 0.20.0 | -| 2.4.5 | 2024-02-08 | [34745](https://github.com/airbytehq/airbyte/pull/34745) | Adopt CDK 0.19.0 | -| 2.4.4 | 2024-02-08 | [35027](https://github.com/airbytehq/airbyte/pull/35027) | Upgrade CDK to 0.17.1 | -| 2.4.3 | 2024-02-01 | [34728](https://github.com/airbytehq/airbyte/pull/34728) | Upgrade CDK to 0.16.4; Notable changes from 0.14.2, 0.15.1 and 0.16.3 | -| 2.4.2 | 2024-01-24 | [34451](https://github.com/airbytehq/airbyte/pull/34451) | Improve logging for unparseable input | -| 2.4.1 | 2024-01-24 | [34458](https://github.com/airbytehq/airbyte/pull/34458) | Improve error reporting | -| 2.4.0 | 2024-01-24 | [34468](https://github.com/airbytehq/airbyte/pull/34468) | Upgrade CDK to 0.14.0 | +| 3.0.12 | 2025-10-31 | [69083](https://github.com/airbytehq/airbyte/pull/69083) | Fail loudly if Bigquery detects bad records. | +| 3.0.11 | 2025-10-28 | [68671](https://github.com/airbytehq/airbyte/pull/68671) | Log record count per load job. | +| 3.0.10 | 2025-10-21 | [67153](https://github.com/airbytehq/airbyte/pull/67153) | Implement new proto schema implementation | +| 3.0.9 | 2025-10-17 | [68152](https://github.com/airbytehq/airbyte/pull/68152) | Update to new TableOperationsClient interface. | +| 3.0.8 | 2025-10-06 | [67078](https://github.com/airbytehq/airbyte/pull/67078) | Remove memory limit for sync jobs to improve performance and resource utilization. | +| 3.0.7 | 2025-09-03 | [65905](https://github.com/airbytehq/airbyte/pull/65905) | Promoting release candidate 3.0.7-rc.1 to a main version. | +| 3.0.7-rc.1 | 2025-08-27 | [65114](https://github.com/airbytehq/airbyte/pull/65114) | Implement SOCKET+PROTO mode support. | +| 3.0.6 | 2025-07-24 | [63700](https://github.com/airbytehq/airbyte/pull/63700) | Improve error reporting for Billing errors. | +| 3.0.5 | 2025-07-15 | [63312](https://github.com/airbytehq/airbyte/pull/63312) | Pull in upstream fix to support null chars in GCS staging mode. | +| 3.0.4 | 2025-07-15 | [63327](https://github.com/airbytehq/airbyte/pull/63327) | Improve error reporting for Billing errors. | +| 3.0.3 | 2025-07-02 | [62495](https://github.com/airbytehq/airbyte/pull/62495) | Improve error reporting for misconfigured connections; improve support for complex types. | +| 3.0.2 | 2025-06-26 | [62106](https://github.com/airbytehq/airbyte/pull/62106) | Improve error reporting during schema evolution. | +| 3.0.1 | 2025-06-26 | [62085](https://github.com/airbytehq/airbyte/pull/62085) | Correctly handle stream names/namespaces and column names which start with a digit. | +| 3.0.0 | 2025-06-25 | [59752](https://github.com/airbytehq/airbyte/pull/59752) | Upgrade to direct-load tables; add option for soft CDC deletes. | +| 2.12.4 | 2025-06-24 | [62045](https://github.com/airbytehq/airbyte/pull/62045) | Promoting release candidate 2.12.4-rc.6 to a main version. | +| 2.12.4-rc.6 | 2025-06-24 | [62041](https://github.com/airbytehq/airbyte/pull/62041) | 2.12.4 RC 6 More retries is better retries | +| 2.12.4-rc.5 | 2025-06-23 | [62016](https://github.com/airbytehq/airbyte/pull/62016) | 2.12.4 RC 5 Handle records up to 20MiB | +| 2.12.4-rc.4 | 2025-06-23 | [62014](https://github.com/airbytehq/airbyte/pull/62014) | 2.12.4 RC 4 Improve JSON schema parser's behavior on invalid source schemas | +| 2.12.4-rc.3 | 2025-06-18 | [61702](https://github.com/airbytehq/airbyte/pull/61702) | 2.12.4 RC 3 Fix an issue with streams with special chars on bulk loader | +| 2.12.4-rc.2 | 2025-06-18 | [61700](https://github.com/airbytehq/airbyte/pull/61700) | 2.12.4 RC 2 (throw more informative error on invalid catalog) | +| 2.12.4-rc.1 | 2025-06-16 | [61637](https://github.com/airbytehq/airbyte/pull/61637) | 2.12.4 RC 1 (theoretically equivalent to 2.12.0, but with fixed global state handling in CDK) | +| 2.12.3 | 2025-06-16 | [61648](https://github.com/airbytehq/airbyte/pull/61648) | This is not the release you are looking for. identical to 2.10.2 | +| 2.12.1 | 2025-06-13 | [61588](https://github.com/airbytehq/airbyte/pull/61588) | ~~Publish version to account for possible duplicate publishing in pipeline. Noop change.~~ WARNING: THIS HAS A BUG. DO NOT USE. | +| 2.12.0 | 2025-06-06 | [61432](https://github.com/airbytehq/airbyte/pull/61432) | Improve performance in GCS staging mode by writing GZIP-compressed files. | +| 2.11.4 | 2025-05-30 | [61018](https://github.com/airbytehq/airbyte/pull/61018) | Always emit a useful error message when erroring during sync startup. | +| 2.11.3 | 2025-06-02 | [61321](https://github.com/airbytehq/airbyte/pull/61321) | CHECK operation doesn't need to drop the dataset anymore. | +| 2.11.2 | 2025-05-29 | [60986](https://github.com/airbytehq/airbyte/pull/60986) | CHECK operation uses configured default dataset instead of `airbyte_internal_test`. | +| 2.11.1 | 2025-05-29 | [60973](https://github.com/airbytehq/airbyte/pull/60973) | Improve error recovery when a stream's sync mode and schema are both changed and the previous sync exited uncleanly. | +| 2.11.0 | 2025-05-27 | [60922](https://github.com/airbytehq/airbyte/pull/60922) | Promoting release candidate 2.11.0-rc.7 to a main version. | +| 2.11.0-rc.7 | 2025-05-22 | [60865](https://github.com/airbytehq/airbyte/pull/60865) | Add a random element to the check sync namespace | +| 2.11.0-rc.6 | 2025-05-22 | [60859](https://github.com/airbytehq/airbyte/pull/60859) | Improve bigquery quota usage in standard inserts for streams with heavy load | +| 2.11.0-rc.5 | 2025-05-21 | [60841](https://github.com/airbytehq/airbyte/pull/60841) | Improve behavior in syncs with many state messages | +| 2.11.0-rc.4 | 2025-05-19 | [60791](https://github.com/airbytehq/airbyte/pull/60791) | Fix bug in detecting schema change when stream has no columns | +| 2.11.0-rc.3 | 2025-05-16 | [60324](https://github.com/airbytehq/airbyte/pull/60324) | Fix bug in syncs with many state message | +| 2.11.0-rc.2 | 2025-05-15 | [60302](https://github.com/airbytehq/airbyte/pull/60302) | Fix bugs in handling special characters / uppercase characters in column names | +| 2.11.0-rc.1 | 2025-05-08 | [59729](https://github.com/airbytehq/airbyte/pull/59729) | Version 2.11.0 RC 1 | +| 2.10.2 | 2025-04-29 | [59142](https://github.com/airbytehq/airbyte/pull/59142) | Add `europe-north2` region. | +| 2.10.1 | 2025-04-14 | [57569](https://github.com/airbytehq/airbyte/pull/57569) | Remove StringSubstitutor usage | +| 2.10.0 | 2025-04-02 | [56982](https://github.com/airbytehq/airbyte/pull/56982) | Change default raw table partitioning scheme to be on `_airbyte_extracted_at`; upgrade CDK | +| 2.9.3 | 2025-03-24 | [56355](https://github.com/airbytehq/airbyte/pull/56355) | Upgrade to airbyte/java-connector-base:2.0.1 to be M4 compatible. | +| 2.9.2 | 2025-01-10 | [51482](https://github.com/airbytehq/airbyte/pull/51482) | Use a non root base image | +| 2.9.1 | 2024-12-18 | [49902](https://github.com/airbytehq/airbyte/pull/49902) | Use a base image: airbyte/java-connector-base:1.0.0 | +| 2.9.0 | 2024-09-18 | [45433](https://github.com/airbytehq/airbyte/pull/45433) | upgrade all dependencies | +| 2.8.9 | 2024-08-20 | [44476](https://github.com/airbytehq/airbyte/pull/44476) | Increase message parsing limit to 100mb | +| 2.8.8 | 2024-08-22 | [44526](https://github.com/airbytehq/airbyte/pull/44526) | Revert protocol compliance fix | +| 2.8.7 | 2024-08-15 | [42504](https://github.com/airbytehq/airbyte/pull/42504) | Fix bug in refreshes logic (already mitigated in platform, just fixing protocol compliance) | +| 2.8.6 | 2024-07-30 | [42511](https://github.com/airbytehq/airbyte/pull/42511) | Added a copy operation to validate copy permissions in the check function | +| 2.8.5 | 2024-07-22 | [42407](https://github.com/airbytehq/airbyte/pull/42407) | Batched Standard Inserts is default loading mode | +| 2.8.4 | 2024-07-15 | [41968](https://github.com/airbytehq/airbyte/pull/41968) | Don't hang forever on empty stream list; shorten error message on INCOMPLETE stream status | +| 2.8.3 | 2024-07-12 | [41674](https://github.com/airbytehq/airbyte/pull/41674) | Upgrade to latest CDK | +| 2.8.2 | 2024-07-08 | [41041](https://github.com/airbytehq/airbyte/pull/41041) | Fix resume logic in truncate refreshes to prevent data loss | +| 2.8.1 | 2024-06-25 | [39379](https://github.com/airbytehq/airbyte/pull/39379) | Removing requirement of a redundant permission bigquery.datasets.create permission | +| 2.8.0 | 2024-06-21 | [39904](https://github.com/airbytehq/airbyte/pull/39904) | Convert all production code to kotlin | +| 2.7.1 | 2024-06-17 | [39526](https://github.com/airbytehq/airbyte/pull/39526) | Internal code change for improved error reporting in case of source/platform failure (`INCOMPLETE` stream status / empty ConfiguredCatalog). | +| 2.7.0 | 2024-06-17 | [38713](https://github.com/airbytehq/airbyte/pull/38713) | Support for [refreshes](/platform/operator-guides/refreshes) and resumable full refresh. WARNING: You must upgrade to platform 0.63.7 before upgrading to this connector version. | +| 2.6.3 | 2024-06-10 | [38331](https://github.com/airbytehq/airbyte/pull/38331) | Internal code changes in preparation for future feature release | +| 2.6.2 | 2024-06-07 | [38764](https://github.com/airbytehq/airbyte/pull/38764) | Increase message length limit to 50MiB | +| 2.6.1 | 2024-05-29 | [38770](https://github.com/airbytehq/airbyte/pull/38770) | Internal code change (switch to CDK artifact) | +| 2.6.0 | 2024-05-28 | [38359](https://github.com/airbytehq/airbyte/pull/38359) | Propagate airbyte_meta from sources; add generation_id column | +| 2.5.1 | 2024-05-22 | [38591](https://github.com/airbytehq/airbyte/pull/38591) | Bugfix to include forward-slash when cleaning up stage | +| 2.5.0 | 2024-05-22 | [38132](https://github.com/airbytehq/airbyte/pull/38132) | Major rewrite of existing code, Adapting to CDK changes introduced in [38107](https://github.com/airbytehq/airbyte/pull/38107) | +| 2.4.20 | 2024-05-13 | [38131](https://github.com/airbytehq/airbyte/pull/38131) | Cleanup `BigQueryWriteConfig` and reuse `StreamConfig`; Adapt to `StreamConfig` signature changes | +| 2.4.19 | 2024-05-10 | [38125](https://github.com/airbytehq/airbyte/pull/38125) | adopt latest CDK code | +| 2.4.18 | 2024-05-10 | [38111](https://github.com/airbytehq/airbyte/pull/38111) | No functional changes, deleting unused code | +| 2.4.17 | 2024-05-09 | [38098](https://github.com/airbytehq/airbyte/pull/38098) | Internal build structure change | +| 2.4.16 | 2024-05-08 | [37714](https://github.com/airbytehq/airbyte/pull/37714) | Adopt CDK 0.34.0 | +| 2.4.15 | 2024-05-07 | [34611](https://github.com/airbytehq/airbyte/pull/34611) | Adopt CDK 0.33.2 | +| 2.4.14 | 2024-02-25 | [37584](https://github.com/airbytehq/airbyte/pull/37584) | Remove unused insecure dependencies from CDK | +| 2.4.13 | 2024-02-25 | [36899](https://github.com/airbytehq/airbyte/pull/36899) | adopt latest CDK | +| 2.4.12 | 2024-03-04 | [35315](https://github.com/airbytehq/airbyte/pull/35315) | Adopt CDK 0.23.11 | +| 2.4.11 | 2024-02-22 | [35569](https://github.com/airbytehq/airbyte/pull/35569) | Fix logging bug. | +| 2.4.10 | 2024-02-15 | [35240](https://github.com/airbytehq/airbyte/pull/35240) | Adopt CDK 0.20.9 | +| 2.4.9 | 2024-02-15 | [35285](https://github.com/airbytehq/airbyte/pull/35285) | Adopt CDK 0.20.8 | +| 2.4.8 | 2024-02-12 | [35144](https://github.com/airbytehq/airbyte/pull/35144) | Adopt CDK 0.20.2 | +| 2.4.7 | 2024-02-12 | [35111](https://github.com/airbytehq/airbyte/pull/35111) | Adopt CDK 0.20.1 | +| 2.4.6 | 2024-02-09 | [34575](https://github.com/airbytehq/airbyte/pull/34575) | Adopt CDK 0.20.0 | +| 2.4.5 | 2024-02-08 | [34745](https://github.com/airbytehq/airbyte/pull/34745) | Adopt CDK 0.19.0 | +| 2.4.4 | 2024-02-08 | [35027](https://github.com/airbytehq/airbyte/pull/35027) | Upgrade CDK to 0.17.1 | +| 2.4.3 | 2024-02-01 | [34728](https://github.com/airbytehq/airbyte/pull/34728) | Upgrade CDK to 0.16.4; Notable changes from 0.14.2, 0.15.1 and 0.16.3 | +| 2.4.2 | 2024-01-24 | [34451](https://github.com/airbytehq/airbyte/pull/34451) | Improve logging for unparseable input | +| 2.4.1 | 2024-01-24 | [34458](https://github.com/airbytehq/airbyte/pull/34458) | Improve error reporting | +| 2.4.0 | 2024-01-24 | [34468](https://github.com/airbytehq/airbyte/pull/34468) | Upgrade CDK to 0.14.0 | | 2.3.31 | 2024-01-22 | [\#34023](https://github.com/airbytehq/airbyte/pull/34023) | Combine DDL operations into a single execution | | 2.3.30 | 2024-01-12 | [\#34226](https://github.com/airbytehq/airbyte/pull/34226) | Upgrade CDK to 0.12.0; Cleanup dependencies | | 2.3.29 | 2024-01-09 | [\#34003](https://github.com/airbytehq/airbyte/pull/34003) | Fix loading credentials from GCP Env | From a66f651efa581ae8a3625e057633bba79dc26213 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 16:36:37 -0500 Subject: [PATCH 049/379] fix(source-bing-ads): fix OOM on large report downloads with streaming ZIP decoder (#74885) Co-authored-by: bot_apk Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Alfredo Garcia Co-authored-by: alfredo.garcia@airbyte.io Co-authored-by: Aaron ("AJ") Steers --- .../connectors/source-bing-ads/components.py | 55 +++++++++++++++++++ .../connectors/source-bing-ads/manifest.yaml | 17 +++--- .../connectors/source-bing-ads/metadata.yaml | 2 +- docs/integrations/sources/bing-ads.md | 1 + 4 files changed, 65 insertions(+), 10 deletions(-) diff --git a/airbyte-integrations/connectors/source-bing-ads/components.py b/airbyte-integrations/connectors/source-bing-ads/components.py index 19a7fcda3fb6..7a0d499cd855 100644 --- a/airbyte-integrations/connectors/source-bing-ads/components.py +++ b/airbyte-integrations/connectors/source-bing-ads/components.py @@ -3,6 +3,8 @@ import gzip import io import logging +import tempfile +import zipfile from copy import deepcopy from dataclasses import dataclass from datetime import datetime, timezone @@ -467,6 +469,59 @@ def read(self, size: int = -1) -> bytes: return self._stream.read(size) or b"" +@dataclass +class BingAdsReportZipCsvDecoder(Decoder): + """ + Streaming decoder for Bing Ads report ZIP downloads. + + The CDK's built-in ZipfileDecoder loads the entire HTTP response into memory + via `response.content`, creating multiple in-memory copies of the data. + With high concurrency, this causes OOM when processing large reports. + + This decoder streams the response to a temporary SpooledTemporaryFile + (spilling to disk beyond 5 MB), then extracts and parses the CSV content + row-by-row, keeping memory usage bounded regardless of report size. + """ + + encoding: str = "utf-8-sig" + set_values_to_none: Optional[List[str]] = None + + def is_stream_response(self) -> bool: + return True + + def decode(self, response: Any) -> Generator[MutableMapping[str, Any], None, None]: + spool = tempfile.SpooledTemporaryFile(max_size=5 * 1024 * 1024) + raw = response.raw + try: + while True: + chunk = raw.read(64 * 1024) + if not chunk: + break + spool.write(chunk) + spool.seek(0) + + try: + with zipfile.ZipFile(spool) as zf: + for name in zf.namelist(): + with zf.open(name) as member: + text_stream = io.TextIOWrapper(member, encoding=self.encoding) + reader = csv.DictReader(text_stream) + none_values = set(self.set_values_to_none) if self.set_values_to_none else set() + for row in reader: + row.pop(None, None) # Remove extra columns not in header + if none_values: + for key, value in row.items(): + if value in none_values: + row[key] = None + yield row + except zipfile.BadZipFile as exc: + logger.error("Received an invalid zip file in response: %s", exc) + raise + finally: + spool.close() + raw.close() + + @dataclass class BingAdsGzipCsvDecoder(Decoder): """ diff --git a/airbyte-integrations/connectors/source-bing-ads/manifest.yaml b/airbyte-integrations/connectors/source-bing-ads/manifest.yaml index 6efefd23237a..7cc5f1252100 100644 --- a/airbyte-integrations/connectors/source-bing-ads/manifest.yaml +++ b/airbyte-integrations/connectors/source-bing-ads/manifest.yaml @@ -2535,13 +2535,12 @@ definitions: url_base: "{{download_target}}" http_method: GET download_decoder: - type: ZipfileDecoder - decoder: - type: CsvDecoder - encoding: "utf-8-sig" - set_values_to_none: - - "" - - "--" + type: CustomDecoder + class_name: source_declarative_manifest.components.BingAdsReportZipCsvDecoder + encoding: "utf-8-sig" + set_values_to_none: + - "" + - "--" creation_requester: type: HttpRequester url_base: https://reporting.api.bingads.microsoft.com/ @@ -17473,8 +17472,8 @@ schemas: concurrency_level: type: ConcurrencyLevel - default_concurrency: 40 - max_concurrency: 40 + default_concurrency: 10 + max_concurrency: 20 spec: type: Spec diff --git a/airbyte-integrations/connectors/source-bing-ads/metadata.yaml b/airbyte-integrations/connectors/source-bing-ads/metadata.yaml index e2ca076c8860..eaffc112ca5b 100644 --- a/airbyte-integrations/connectors/source-bing-ads/metadata.yaml +++ b/airbyte-integrations/connectors/source-bing-ads/metadata.yaml @@ -16,7 +16,7 @@ data: connectorSubtype: api connectorType: source definitionId: 47f25999-dd5e-4636-8c39-e7cea2453331 - dockerImageTag: 2.23.15-rc.1 + dockerImageTag: 2.23.15-rc.2 dockerRepository: airbyte/source-bing-ads documentationUrl: https://docs.airbyte.com/integrations/sources/bing-ads externalDocumentationUrls: diff --git a/docs/integrations/sources/bing-ads.md b/docs/integrations/sources/bing-ads.md index e304cbb6bd1a..95708c973b24 100644 --- a/docs/integrations/sources/bing-ads.md +++ b/docs/integrations/sources/bing-ads.md @@ -319,6 +319,7 @@ The Bing Ads API limits the number of requests for all Microsoft Advertising cli | Version | Date | Pull Request | Subject | |:------------|:-----------|:---------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 2.23.15-rc.2 | 2026-03-15 | [TBD](https://github.com/airbytehq/airbyte/pull/TBD) | Fix OOM on large report downloads by using streaming ZIP decoder and reducing concurrency | | 2.23.15-rc.1 | 2026-03-12 | [74745](https://github.com/airbytehq/airbyte/pull/74745) | Increase default concurrency from 2 to 40 to test rate limit behavior | | 2.23.14 | 2026-03-10 | [74483](https://github.com/airbytehq/airbyte/pull/74483) | Update dependencies | | 2.23.13 | 2026-03-03 | [73654](https://github.com/airbytehq/airbyte/pull/73654) | Use streaming decompression in BingAdsGzipCsvDecoder to prevent OOM on large accounts | From 8b2e332d1b8089b7d4eb8e4446ed2a337b353a90 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 22:15:24 +0000 Subject: [PATCH 050/379] docs(source-bing-ads): fix changelog date and PR link for v2.23.15-rc.2 (#75635) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- docs/integrations/sources/bing-ads.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/sources/bing-ads.md b/docs/integrations/sources/bing-ads.md index 95708c973b24..233847e0f135 100644 --- a/docs/integrations/sources/bing-ads.md +++ b/docs/integrations/sources/bing-ads.md @@ -319,7 +319,7 @@ The Bing Ads API limits the number of requests for all Microsoft Advertising cli | Version | Date | Pull Request | Subject | |:------------|:-----------|:---------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 2.23.15-rc.2 | 2026-03-15 | [TBD](https://github.com/airbytehq/airbyte/pull/TBD) | Fix OOM on large report downloads by using streaming ZIP decoder and reducing concurrency | +| 2.23.15-rc.2 | 2026-03-30 | [74885](https://github.com/airbytehq/airbyte/pull/74885) | Fix OOM on large report downloads by using streaming ZIP decoder and reducing concurrency | | 2.23.15-rc.1 | 2026-03-12 | [74745](https://github.com/airbytehq/airbyte/pull/74745) | Increase default concurrency from 2 to 40 to test rate limit behavior | | 2.23.14 | 2026-03-10 | [74483](https://github.com/airbytehq/airbyte/pull/74483) | Update dependencies | | 2.23.13 | 2026-03-03 | [73654](https://github.com/airbytehq/airbyte/pull/73654) | Use streaming decompression in BingAdsGzipCsvDecoder to prevent OOM on large accounts | From 6f38c017afa0f9e66a2956a5e38a021dbba90f96 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 22:15:29 +0000 Subject: [PATCH 051/379] docs(source-google-search-console): fix changelog date, typos, and document missing config options (#75631) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- .../sources/google-search-console.md | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/integrations/sources/google-search-console.md b/docs/integrations/sources/google-search-console.md index ee93f76c30e6..331126661b25 100644 --- a/docs/integrations/sources/google-search-console.md +++ b/docs/integrations/sources/google-search-console.md @@ -2,7 +2,7 @@ -This page contains the setup guide and reference information for the [Google Search Console](https://developers.google.com) source connector. +This page contains the setup guide and reference information for the [Google Search Console](https://search.google.com/search-console/about) source connector. @@ -87,7 +87,7 @@ For more information on this topic, please refer to [this Google article](https: 2. Click Sources and then click + New source. 3. On the Set up the source page, select Google Search Console from the Source type dropdown. 4. Enter a name for the Google Search Console connector. -5. For **Website URL Property**, enter the specific website property in Google Seach Console with data you want to replicate. +5. For **Website URL Property**, enter the website properties in Google Search Console that contain the data you want to replicate. You can add multiple site URLs. 6. For **Start Date**, by default the `2021-01-01` is set, use the provided datepicker or enter a date in the format `YYYY-MM-DD`. Any data created on or after this date will be replicated. 7. To authenticate the connection: @@ -106,15 +106,17 @@ For more information on this topic, please refer to [this Google article](https: - **For Airbyte Open Source:** - - (Recommended) Select **Service Account Key Authorization** from the Authentication dropdown, then enter the **Admin Email** and **Service Account JSON Key**. For the key, copy and paste the JSON key you obtained during the service account setup. It should begin with `{"type": "service account", "project_id": YOUR_PROJECT_ID, "private_key_id": YOUR_PRIVATE_KEY, ...}` + - (Recommended) Select **Service Account Key Authorization** from the Authentication dropdown, then enter the **Admin Email** and **Service Account JSON Key**. For the key, copy and paste the JSON key you obtained during the service account setup. It should begin with `{"type": "service_account", "project_id": YOUR_PROJECT_ID, "private_key_id": YOUR_PRIVATE_KEY, ...}` - Select **Oauth** from the Authentication dropdown, then enter your **Client ID**, **Client Secret**, **Access Token** and **Refresh Token**. 8. (Optional) For **End Date**, you may optionally provide a date in the format `YYYY-MM-DD`. Any data created between the defined Start Date and End Date will be replicated. Leaving this field blank will replicate all data created on or after the Start Date to the present. 9. (Optional) For **Custom Reports**, you may optionally provide an array of JSON objects representing any custom reports you wish to query the API with. Refer to the [Custom reports](#custom-reports) section below for more information on formulating these reports. 10. (Optional) For **Data Freshness**, you may choose whether to include "fresh" data that has not been finalized by Google, and may be subject to change. Please note that if you are using Incremental sync mode, we highly recommend leaving this option to its default value of `final`. Refer to the [Data Freshness](#data-freshness) section below for more information on this parameter. -11. (Optional) For **Search Analytics API Requests Per Minute**, you may configure the maximum number of requests per minute for Search Analytics API calls. The default value (1200) matches Google's documented maximum quota. If you are experiencing rate limit errors, you may need to lower this value. Most new Google Cloud projects start with a quota of 60 requests per minute. Check your Google Cloud Console quotas to see your actual limit. Refer to the [Rate Limiting](#rate-limiting) section below for more information. -12. Click **Set up source** and wait for the tests to complete. +11. (Optional) For **Number of Concurrent Workers**, you may configure the number of worker threads used during sync. The default is 40. If you are syncing a large number of site URLs or experiencing rate limit errors, you may want to reduce this value. +12. (Optional) For **Always Use Aggregation Type Auto**, enable this setting if your search analytics streams fail with a 400 error related to an unsupported `aggregationType`. This overrides the default aggregation type with `auto`, which resolves the error for certain site configurations. +13. (Optional) For **Search Analytics API Requests Per Minute**, you may configure the maximum number of requests per minute for Search Analytics API calls. The default value of 1200 matches Google's documented maximum quota. If you are experiencing rate limit errors, you may need to lower this value. Most new Google Cloud projects start with a quota of 60 requests per minute. Check your Google Cloud Console quotas to see your actual limit. Refer to the [Rate Limiting](#rate-limiting) section below for more information. +14. Click **Set up source** and wait for the tests to complete. @@ -135,7 +137,7 @@ The granularity for the cursor is 1 day, so Incremental Sync in Append mode may - [Sites](https://developers.google.com/webmaster-tools/search-console-api-original/v3/sites/get) - [Sitemaps](https://developers.google.com/webmaster-tools/search-console-api-original/v3/sitemaps/list) -- [Full Analytics report](https://developers.google.com/webmaster-tools/search-console-api-original/v3/searchanalytics/query) \(this stream has a long sync time because it is very detailed, use with care\) +- [Full Analytics report](https://developers.google.com/webmaster-tools/search-console-api-original/v3/searchanalytics/query) — this stream has a long sync time because it is very detailed; use with care - [Analytics report by country](https://developers.google.com/webmaster-tools/search-console-api-original/v3/searchanalytics/query) - [Analytics report by date](https://developers.google.com/webmaster-tools/search-console-api-original/v3/searchanalytics/query) - [Analytics report by device](https://developers.google.com/webmaster-tools/search-console-api-original/v3/searchanalytics/query) @@ -177,7 +179,7 @@ For example, to query the API for a report that groups results by country, then Please note, that for technical reasons `date` is the default dimension which will be included in your query whether you specify it or not. By specifying it you can change the order the results are grouped in. Primary key will consist of your custom dimensions and the default dimension along with `site_url` and `search_type`. -The information you provide via UI Custom report builder will then be transformed into the custom stream by it's `Name` +The information you provide via the UI Custom report builder will then be transformed into a custom stream using its `Name`. You can use the [Google APIS Explorer](https://developers.google.com/webmaster-tools/v1/searchanalytics/query) to build and test the reports you want to use. @@ -227,7 +229,7 @@ If you need higher limits, you can enable billing on your Google Cloud project o #### Data retention -Google Search Console only retains data for websites from the last 16 months. Any data prior to this cutoff point will not be accessible. [Please see this article for more information](https://seotesting.com/google-search-console/how-long-does-gsc-keep-my-data/#:~:text=Google%20Search%20Console%20holds%20relevant,October%2C%202022%2C%20until%20today.). +Google Search Console only retains data for websites from the last 16 months. Any data prior to this cutoff point will not be accessible. For more information, see [Google's documentation on data freshness and availability](https://support.google.com/webmasters/answer/7576553). ### Troubleshooting @@ -242,7 +244,7 @@ Google Search Console only retains data for websites from the last 16 months. An | Version | Date | Pull Request | Subject | |:------------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 1.10.27 | 2026-03-24 | [75426](https://github.com/airbytehq/airbyte/pull/75426) | Guard numeric metric fields against complex types to prevent serialization failures and deadlocks | +| 1.10.27 | 2026-03-30 | [75426](https://github.com/airbytehq/airbyte/pull/75426) | Guard numeric metric fields against complex types to prevent serialization failures and deadlocks | | 1.10.26 | 2026-03-24 | [74935](https://github.com/airbytehq/airbyte/pull/74935) | Update dependencies | | 1.10.25 | 2026-03-10 | [74685](https://github.com/airbytehq/airbyte/pull/74685) | Update dependencies | | 1.10.24 | 2026-02-24 | [73935](https://github.com/airbytehq/airbyte/pull/73935) | Update dependencies | From de0a0db367cb4d53801a6834030d70f580055321 Mon Sep 17 00:00:00 2001 From: Serhii Lazebnyi Date: Tue, 31 Mar 2026 00:40:03 +0100 Subject: [PATCH 052/379] feat(source-intercom): add oauth_connector_input_specification for declarative OAuth (#75575) --- .../connectors/source-intercom/manifest.yaml | 22 +++++++++---------- .../connectors/source-intercom/metadata.yaml | 2 +- docs/integrations/sources/intercom.md | 1 + 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/airbyte-integrations/connectors/source-intercom/manifest.yaml b/airbyte-integrations/connectors/source-intercom/manifest.yaml index 99f51bdac2ee..f616720a0f2c 100644 --- a/airbyte-integrations/connectors/source-intercom/manifest.yaml +++ b/airbyte-integrations/connectors/source-intercom/manifest.yaml @@ -879,17 +879,17 @@ spec: advanced_auth: auth_flow_type: "oauth2.0" oauth_config_specification: - oauth_authorization_url: "https://app.intercom.com/oauth" - oauth_token_url: "https://api.intercom.io/auth/eagle/token" - oauth_user_input_from_connector_config_specification: - type: object - properties: - client_id: - type: string - path_in_connector_config: ["client_id"] - client_secret: - type: string - path_in_connector_config: ["client_secret"] + oauth_connector_input_specification: + consent_url: "https://app.intercom.com/a/oauth/connect?{{client_id_param}}&{{redirect_uri_param}}&response_type=code&{{state_param}}" + access_token_url: "https://api.intercom.io/auth/eagle/token" + access_token_headers: + Content-Type: "application/x-www-form-urlencoded" + access_token_params: + code: "{{ auth_code_value }}" + client_id: "{{ client_id_value }}" + client_secret: "{{ client_secret_value }}" + extract_output: + - access_token complete_oauth_output_specification: type: object properties: diff --git a/airbyte-integrations/connectors/source-intercom/metadata.yaml b/airbyte-integrations/connectors/source-intercom/metadata.yaml index dad3ef27c79f..be95e1bf702b 100644 --- a/airbyte-integrations/connectors/source-intercom/metadata.yaml +++ b/airbyte-integrations/connectors/source-intercom/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: api connectorType: source definitionId: d8313939-3782-41b0-be29-b3ca20d8dd3a - dockerImageTag: 0.13.16 + dockerImageTag: 0.13.17 dockerRepository: airbyte/source-intercom documentationUrl: https://docs.airbyte.com/integrations/sources/intercom externalDocumentationUrls: diff --git a/docs/integrations/sources/intercom.md b/docs/integrations/sources/intercom.md index 50555ab16b03..b13e6c593195 100644 --- a/docs/integrations/sources/intercom.md +++ b/docs/integrations/sources/intercom.md @@ -123,6 +123,7 @@ Because these streams must read all records on every sync, syncing Companies and | Version | Date | Pull Request | Subject | |:-------------|:-----------|:---------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------| +| 0.13.17 | 2026-03-30 | [75575](https://github.com/airbytehq/airbyte/pull/75575) | Add `oauth_connector_input_specification` for declarative OAuth | | 0.13.16 | 2026-03-24 | [75419](https://github.com/airbytehq/airbyte/pull/75419) | Promote 0.13.16-rc.6 to GA — includes CDK 7.13.0 upgrade, block_simultaneous_read for companies, rate limiter fix, step size/end_datetime for incremental streams, and heartbeat timeout bump | | 0.13.16-rc.6 | 2026-03-19 | [75216](https://github.com/airbytehq/airbyte/pull/75216) | Bump CDK base image to 7.13.0 (includes block_simultaneous_read support and cursor field fix) | | 0.13.16-rc.5 | 2026-03-11 | [71141](https://github.com/airbytehq/airbyte/pull/71141) | Block simultaneous reading from companies endpoint | From 09b7265ff95ab6ed26ff9542311f6b7516ace6da Mon Sep 17 00:00:00 2001 From: Matt Bayley Date: Mon, 30 Mar 2026 17:14:11 -0700 Subject: [PATCH 053/379] feat(bulk-cdk): core/base changes for source-postgres (#75640) --- airbyte-cdk/bulk/core/base/changelog.md | 4 ++++ .../kotlin/io/airbyte/cdk/data/JsonCodec.kt | 18 +++++++++++++----- airbyte-cdk/bulk/core/base/version.properties | 2 +- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/airbyte-cdk/bulk/core/base/changelog.md b/airbyte-cdk/bulk/core/base/changelog.md index b535f521667c..8408984e522d 100644 --- a/airbyte-cdk/bulk/core/base/changelog.md +++ b/airbyte-cdk/bulk/core/base/changelog.md @@ -1,3 +1,7 @@ +## Version 1.0.2 + +Improved null handling for array types. + ## Version 1.0.1 Bump transitive deps with CVEs in unmaintained json schema lib (mbknor-jackson-jsonschema): upgrade classgraph to 4.8.112 (CVE-2021-47621, XXE) and scala-library to 2.13.9 (CVE-2022-36944, deserialization gadget chain). diff --git a/airbyte-cdk/bulk/core/base/src/main/kotlin/io/airbyte/cdk/data/JsonCodec.kt b/airbyte-cdk/bulk/core/base/src/main/kotlin/io/airbyte/cdk/data/JsonCodec.kt index 6d5c1079b39c..9732149b4c1b 100644 --- a/airbyte-cdk/bulk/core/base/src/main/kotlin/io/airbyte/cdk/data/JsonCodec.kt +++ b/airbyte-cdk/bulk/core/base/src/main/kotlin/io/airbyte/cdk/data/JsonCodec.kt @@ -2,6 +2,7 @@ package io.airbyte.cdk.data import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.node.NullNode import io.airbyte.cdk.util.Jsons import java.math.BigDecimal import java.net.URI @@ -187,7 +188,9 @@ data object FloatCodec : JsonCodec { } val decoded: Float = encoded.floatValue() if (encode(decoded).doubleValue().compareTo(encoded.doubleValue()) != 0) { - throw IllegalArgumentException("invalid IEEE-754 32-bit floating point value $encoded") + throw IllegalArgumentException( + "invalid IEEE-754 32-bit floating point value $encoded (type ${encoded.javaClass.canonicalName})" + ) } return decoded } @@ -367,18 +370,23 @@ data class ArrayEncoder( override fun encode(decoded: List): JsonNode = Jsons.arrayNode().apply { for (e in decoded) { - add(elementEncoder.encode(e)) + // Note: in generics, T can be nullable! + if (e == null) add(NullCodec.encode(e)) else add(elementEncoder.encode(e)) } } } data class ArrayDecoder( val elementDecoder: JsonDecoder, -) : JsonDecoder> { - override fun decode(encoded: JsonNode): List { +) : JsonDecoder> { + override fun decode(encoded: JsonNode): List { if (!encoded.isArray) { throw IllegalArgumentException("invalid array value $encoded") } - return encoded.elements().asSequence().map { elementDecoder.decode(it) }.toList() + return encoded + .elements() + .asSequence() + .map { if (it == null || it is NullNode) null else elementDecoder.decode(it) } + .toList() } } diff --git a/airbyte-cdk/bulk/core/base/version.properties b/airbyte-cdk/bulk/core/base/version.properties index 47a478aeda9f..325db2cfb7dc 100644 --- a/airbyte-cdk/bulk/core/base/version.properties +++ b/airbyte-cdk/bulk/core/base/version.properties @@ -1 +1 @@ -version=1.0.1 +version=1.0.2 From 9d4ab9ae5ea1959385c71f6514eb29d9ed5c24f2 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 00:36:11 +0000 Subject: [PATCH 054/379] docs(source-intercom): improve setup guide, rate limits, and config documentation (#75639) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- docs/integrations/sources/intercom.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/integrations/sources/intercom.md b/docs/integrations/sources/intercom.md index b13e6c593195..84bed5134fbf 100644 --- a/docs/integrations/sources/intercom.md +++ b/docs/integrations/sources/intercom.md @@ -26,12 +26,12 @@ This page contains the setup guide and reference information for the [Intercom]( ### Obtain an Intercom access token (Airbyte Open Source) -To authenticate the connector in **Airbyte Open Source**, you will need to obtain an access token. You can follow the setup steps below to create an Intercom app and generate the token. For more information on Intercom's authentication flow, refer to the [official documentation](https://developers.intercom.com/building-apps/docs/authentication-types). +To authenticate the connector in **Airbyte Open Source**, you need an access token. Follow the steps below to create an Intercom app and generate the token. For more information on Intercom's authentication flow, refer to the [official documentation](https://developers.intercom.com/docs/build-an-integration/learn-more/authentication). 1. Log in to your Intercom account and navigate to the [Developer Hub](https://developers.intercom.com/). 2. Click **Your apps** in the top-right corner, then click **New app**. 3. Choose an **App name**, select your Workspace from the dropdown, and click **Create app**. -4. To set the appropriate permissions, from the **Authentication** tab, click **Edit** in the top right corner and check the permissions you want to grant to the app. We recommend only granting **read** permissions (not **write**). Click **Save** when you are finished. +4. To set the appropriate permissions, from the **Authentication** tab, click **Edit** in the top right corner and check the permissions you want to grant to the app. Grant only **read** permissions (not **write**). Click **Save** when you are finished. 5. Under the **Access token** header, you will be prompted to regenerate your access token. Follow the instructions to do so, and copy the new token. @@ -41,19 +41,19 @@ To authenticate the connector in **Airbyte Open Source**, you will need to obtai #### For Airbyte Cloud: 1. [Log into your Airbyte Cloud](https://cloud.airbyte.com/workspaces) account. -2. Click Sources and then click + New source. -3. On the Set up the source page, select Intercom from the Source type dropdown. +2. Click **Sources** and then click **+ New source**. +3. On the Set up the source page, select **Intercom** from the Source type dropdown. 4. Enter a name for the Intercom connector. 5. To authenticate: -### For Airbyte Open Source: +#### For Airbyte Open Source: 1. Navigate to the Airbyte Open Source dashboard. -2. Click Sources and then click + New source. -3. On the Set up the source page, select Intercom from the Source type dropdown. +2. Click **Sources** and then click **+ New source**. +3. On the Set up the source page, select **Intercom** from the Source type dropdown. 4. Enter a name for the Intercom connector. @@ -65,7 +65,8 @@ To authenticate the connector in **Airbyte Open Source**, you will need to obtai 6. For **Start date**, use the provided datepicker or enter a UTC date and time in the format `YYYY-MM-DDTHH:mm:ssZ`. Only data created on or after this date is replicated. 7. Optionally, configure **Lookback window** to re-sync records updated within the specified number of days before the current cursor position. This helps capture late-arriving updates. The default is `0` (no lookback). -8. Click **Set up source** and wait for the tests to complete. +8. Optionally, configure **Activity logs stream slice step size** to control how many days of activity log data the connector fetches per request. The default is `30` days. Lower this value if you experience timeouts on the Activity Logs stream. +9. Click **Set up source** and wait for the tests to complete. ## Supported sync modes @@ -74,7 +75,7 @@ The Intercom source connector supports the following [sync modes](https://docs.a - Full Refresh - Incremental -## Supported Streams +## Supported streams The Intercom source connector supports the following streams: @@ -94,7 +95,7 @@ The Intercom source connector supports the following streams: ## Performance considerations -The connector is restricted by normal Intercom [rate limits](https://developers.intercom.com/docs/references/rest-api/errors/rate-limiting). The default rate limit is 1,000 requests per minute for public apps and 10,000 requests per minute for private apps. The connector monitors the `X-RateLimit-Remaining` header and proactively throttles itself before hitting the API rate limit, trading sync speed for stability. If the API returns a `429 Too Many Requests` response, the connector retries automatically. +The connector is restricted by normal Intercom [rate limits](https://developers.intercom.com/docs/references/rest-api/errors/rate-limiting). The default rate limit is 1,000 API calls per minute for public apps and 10,000 API calls per minute for private apps, with a workspace-level cap of 25,000 API calls per minute. The connector monitors the `X-RateLimit-Remaining` header and proactively throttles itself before hitting the API rate limit, trading sync speed for stability. If the API returns a `429 Too Many Requests` response, the connector retries automatically. The connector should not run into rate limit issues under normal usage. [Create an issue](https://github.com/airbytehq/airbyte/issues) if you see rate limit errors that are not automatically retried. From b4006acb28a33aa574244b7c23b946f410ff0376 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Mon, 30 Mar 2026 18:26:28 -0700 Subject: [PATCH 055/379] ci: fix empty permissions block on auto-ai-review caller workflow (#75641) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/auto-ai-review-label.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/auto-ai-review-label.yml b/.github/workflows/auto-ai-review-label.yml index c0f8eb1d8176..acfd3db1bdc3 100644 --- a/.github/workflows/auto-ai-review-label.yml +++ b/.github/workflows/auto-ai-review-label.yml @@ -12,7 +12,10 @@ on: run-name: "Auto AI Review for PR #${{ github.event.pull_request.number }}" -permissions: {} +permissions: + contents: read + issues: write + pull-requests: write jobs: dispatch-ai-review: From 19aeac14706abb79faac999b30dbc445e19b5a2a Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Mon, 30 Mar 2026 19:16:34 -0700 Subject: [PATCH 056/379] chore: certify destination-motherduck (#75642) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../connectors/destination-motherduck/metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airbyte-integrations/connectors/destination-motherduck/metadata.yaml b/airbyte-integrations/connectors/destination-motherduck/metadata.yaml index 34ce42295ab6..8fbfe74cc531 100644 --- a/airbyte-integrations/connectors/destination-motherduck/metadata.yaml +++ b/airbyte-integrations/connectors/destination-motherduck/metadata.yaml @@ -39,7 +39,7 @@ data: ab_internal: sl: 100 ql: 100 - supportLevel: community + supportLevel: certified connectorTestSuitesOptions: - suite: unitTests - suite: integrationTests From 04a83b91f73467533a07b6ad4381810f694ecadc Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Mon, 30 Mar 2026 19:26:55 -0700 Subject: [PATCH 057/379] chore: downgrade vector destinations from `certified` to `community` support (#75299) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../connectors/destination-milvus/metadata.yaml | 2 +- .../connectors/destination-pgvector/metadata.yaml | 2 +- .../connectors/destination-snowflake-cortex/metadata.yaml | 2 +- .../connectors/destination-weaviate/metadata.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/airbyte-integrations/connectors/destination-milvus/metadata.yaml b/airbyte-integrations/connectors/destination-milvus/metadata.yaml index 99c21fcd5bab..eeaaa02150c2 100644 --- a/airbyte-integrations/connectors/destination-milvus/metadata.yaml +++ b/airbyte-integrations/connectors/destination-milvus/metadata.yaml @@ -36,7 +36,7 @@ data: ab_internal: sl: 300 ql: 300 - supportLevel: certified + supportLevel: community connectorTestSuitesOptions: - suite: unitTests - suite: integrationTests diff --git a/airbyte-integrations/connectors/destination-pgvector/metadata.yaml b/airbyte-integrations/connectors/destination-pgvector/metadata.yaml index 9c4f6c0c7333..1ad900a7496d 100644 --- a/airbyte-integrations/connectors/destination-pgvector/metadata.yaml +++ b/airbyte-integrations/connectors/destination-pgvector/metadata.yaml @@ -36,7 +36,7 @@ data: resourceRequirements: memory_limit: 2Gi memory_request: 2Gi - supportLevel: certified + supportLevel: community tags: - language:python - cdk:python diff --git a/airbyte-integrations/connectors/destination-snowflake-cortex/metadata.yaml b/airbyte-integrations/connectors/destination-snowflake-cortex/metadata.yaml index e38fe76ed905..16bd91b82385 100644 --- a/airbyte-integrations/connectors/destination-snowflake-cortex/metadata.yaml +++ b/airbyte-integrations/connectors/destination-snowflake-cortex/metadata.yaml @@ -37,7 +37,7 @@ data: resourceRequirements: memory_limit: 2Gi memory_request: 2Gi - supportLevel: certified + supportLevel: community tags: - language:python - cdk:python diff --git a/airbyte-integrations/connectors/destination-weaviate/metadata.yaml b/airbyte-integrations/connectors/destination-weaviate/metadata.yaml index 2d9e47c42cbd..9980df0c7da6 100644 --- a/airbyte-integrations/connectors/destination-weaviate/metadata.yaml +++ b/airbyte-integrations/connectors/destination-weaviate/metadata.yaml @@ -37,7 +37,7 @@ data: resourceRequirements: memory_limit: 2Gi memory_request: 2Gi - supportLevel: certified + supportLevel: community tags: - language:python - cdk:python From a7d3a8370380bdbd4ef4eedf0d02a32fec236b23 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Mon, 30 Mar 2026 20:36:32 -0700 Subject: [PATCH 058/379] chore: bump patch versions to force registry update for supportLevel changes (#75645) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../connectors/destination-milvus/metadata.yaml | 2 +- .../connectors/destination-milvus/pyproject.toml | 2 +- .../connectors/destination-motherduck/metadata.yaml | 2 +- .../connectors/destination-motherduck/pyproject.toml | 2 +- .../connectors/destination-pgvector/metadata.yaml | 2 +- .../connectors/destination-pgvector/pyproject.toml | 2 +- .../connectors/destination-snowflake-cortex/metadata.yaml | 2 +- .../connectors/destination-snowflake-cortex/pyproject.toml | 2 +- .../connectors/destination-weaviate/metadata.yaml | 2 +- .../connectors/destination-weaviate/pyproject.toml | 2 +- docs/integrations/destinations/milvus.md | 1 + docs/integrations/destinations/motherduck.md | 1 + docs/integrations/destinations/pgvector.md | 1 + docs/integrations/destinations/snowflake-cortex.md | 1 + docs/integrations/destinations/weaviate.md | 1 + 15 files changed, 15 insertions(+), 10 deletions(-) diff --git a/airbyte-integrations/connectors/destination-milvus/metadata.yaml b/airbyte-integrations/connectors/destination-milvus/metadata.yaml index eeaaa02150c2..d3141574a28d 100644 --- a/airbyte-integrations/connectors/destination-milvus/metadata.yaml +++ b/airbyte-integrations/connectors/destination-milvus/metadata.yaml @@ -21,7 +21,7 @@ data: connectorSubtype: vectorstore connectorType: destination definitionId: 65de8962-48c9-11ee-be56-0242ac120002 - dockerImageTag: 0.0.57 + dockerImageTag: 0.0.58 dockerRepository: airbyte/destination-milvus githubIssueLabel: destination-milvus icon: milvus.svg diff --git a/airbyte-integrations/connectors/destination-milvus/pyproject.toml b/airbyte-integrations/connectors/destination-milvus/pyproject.toml index 983339fcab5b..dc0b58ad665e 100644 --- a/airbyte-integrations/connectors/destination-milvus/pyproject.toml +++ b/airbyte-integrations/connectors/destination-milvus/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "airbyte-destination-milvus" -version = "0.0.57" +version = "0.0.58" description = "Airbyte destination implementation for Milvus." authors = ["Airbyte "] license = "ELv2" diff --git a/airbyte-integrations/connectors/destination-motherduck/metadata.yaml b/airbyte-integrations/connectors/destination-motherduck/metadata.yaml index 8fbfe74cc531..102e70360e37 100644 --- a/airbyte-integrations/connectors/destination-motherduck/metadata.yaml +++ b/airbyte-integrations/connectors/destination-motherduck/metadata.yaml @@ -4,7 +4,7 @@ data: connectorSubtype: database connectorType: destination definitionId: 042ee9b5-eb98-4e99-a4e5-3f0d573bee66 - dockerImageTag: 0.2.2 + dockerImageTag: 0.2.3 dockerRepository: airbyte/destination-motherduck githubIssueLabel: destination-motherduck icon: duckdb.svg diff --git a/airbyte-integrations/connectors/destination-motherduck/pyproject.toml b/airbyte-integrations/connectors/destination-motherduck/pyproject.toml index 2b5f39cb8e64..1a1fde745fd4 100644 --- a/airbyte-integrations/connectors/destination-motherduck/pyproject.toml +++ b/airbyte-integrations/connectors/destination-motherduck/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "airbyte-destination-motherduck" -version = "0.2.2" +version = "0.2.3" description = "Destination implementation for MotherDuck." authors = ["Guen Prawiroatmodjo, Simon Späti, Airbyte"] license = "ELv2" diff --git a/airbyte-integrations/connectors/destination-pgvector/metadata.yaml b/airbyte-integrations/connectors/destination-pgvector/metadata.yaml index 1ad900a7496d..4d72dc938e48 100644 --- a/airbyte-integrations/connectors/destination-pgvector/metadata.yaml +++ b/airbyte-integrations/connectors/destination-pgvector/metadata.yaml @@ -12,7 +12,7 @@ data: connectorSubtype: vectorstore connectorType: destination definitionId: e0e06cd9-57a9-4d39-b032-bedd874ae875 - dockerImageTag: 0.1.8 + dockerImageTag: 0.1.9 dockerRepository: airbyte/destination-pgvector documentationUrl: https://docs.airbyte.com/integrations/destinations/pgvector githubIssueLabel: destination-pgvector diff --git a/airbyte-integrations/connectors/destination-pgvector/pyproject.toml b/airbyte-integrations/connectors/destination-pgvector/pyproject.toml index e91df5629443..781904d596cb 100644 --- a/airbyte-integrations/connectors/destination-pgvector/pyproject.toml +++ b/airbyte-integrations/connectors/destination-pgvector/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "airbyte-destination-pgvector" -version = "0.1.8" +version = "0.1.9" description = "Airbyte destination implementation for PGVector." authors = ["Airbyte "] license = "ELv2" diff --git a/airbyte-integrations/connectors/destination-snowflake-cortex/metadata.yaml b/airbyte-integrations/connectors/destination-snowflake-cortex/metadata.yaml index 16bd91b82385..14c3dcf357af 100644 --- a/airbyte-integrations/connectors/destination-snowflake-cortex/metadata.yaml +++ b/airbyte-integrations/connectors/destination-snowflake-cortex/metadata.yaml @@ -13,7 +13,7 @@ data: connectorSubtype: vectorstore connectorType: destination definitionId: d9e5418d-f0f4-4d19-a8b1-5630543638e2 - dockerImageTag: 0.2.27 + dockerImageTag: 0.2.28 dockerRepository: airbyte/destination-snowflake-cortex documentationUrl: https://docs.airbyte.com/integrations/destinations/snowflake-cortex githubIssueLabel: destination-snowflake-cortex diff --git a/airbyte-integrations/connectors/destination-snowflake-cortex/pyproject.toml b/airbyte-integrations/connectors/destination-snowflake-cortex/pyproject.toml index c3771e31d8ae..94913dbf1355 100644 --- a/airbyte-integrations/connectors/destination-snowflake-cortex/pyproject.toml +++ b/airbyte-integrations/connectors/destination-snowflake-cortex/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "airbyte-destination-snowflake-cortex" -version = "0.2.27" +version = "0.2.28" description = "Airbyte destination implementation for Snowflake cortex." authors = ["Airbyte "] license = "ELv2" diff --git a/airbyte-integrations/connectors/destination-weaviate/metadata.yaml b/airbyte-integrations/connectors/destination-weaviate/metadata.yaml index 9980df0c7da6..603b821a9e57 100644 --- a/airbyte-integrations/connectors/destination-weaviate/metadata.yaml +++ b/airbyte-integrations/connectors/destination-weaviate/metadata.yaml @@ -13,7 +13,7 @@ data: connectorSubtype: vectorstore connectorType: destination definitionId: 7b7d7a0d-954c-45a0-bcfc-39a634b97736 - dockerImageTag: 0.2.60 + dockerImageTag: 0.2.61 dockerRepository: airbyte/destination-weaviate documentationUrl: https://docs.airbyte.com/integrations/destinations/weaviate githubIssueLabel: destination-weaviate diff --git a/airbyte-integrations/connectors/destination-weaviate/pyproject.toml b/airbyte-integrations/connectors/destination-weaviate/pyproject.toml index 088ebc6c5a4a..80cfc50a6cb7 100644 --- a/airbyte-integrations/connectors/destination-weaviate/pyproject.toml +++ b/airbyte-integrations/connectors/destination-weaviate/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "airbyte-destination-weaviate" -version = "0.2.60" +version = "0.2.61" description = "Airbyte destination implementation for Weaviate." authors = ["Airbyte "] license = "ELv2" diff --git a/docs/integrations/destinations/milvus.md b/docs/integrations/destinations/milvus.md index 732b9b3439e1..215b99435506 100644 --- a/docs/integrations/destinations/milvus.md +++ b/docs/integrations/destinations/milvus.md @@ -120,6 +120,7 @@ This destination does not support [namespaces](https://docs.airbyte.com/platform | Version | Date | Pull Request | Subject | |:--------| :--------- | :-------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | +| 0.0.58 | 2026-03-31 | [75645](https://github.com/airbytehq/airbyte/pull/75645) | Bump version to force registry update for supportLevel change to community | | 0.0.57 | 2025-10-21 | [68333](https://github.com/airbytehq/airbyte/pull/68333) | Update dependencies | | 0.0.56 | 2025-10-14 | [61075](https://github.com/airbytehq/airbyte/pull/61075) | Update dependencies | | 0.0.55 | 2025-05-17 | [57175](https://github.com/airbytehq/airbyte/pull/57175) | Update dependencies | diff --git a/docs/integrations/destinations/motherduck.md b/docs/integrations/destinations/motherduck.md index e7b8de9e6d21..f0c45b7141f4 100644 --- a/docs/integrations/destinations/motherduck.md +++ b/docs/integrations/destinations/motherduck.md @@ -75,6 +75,7 @@ This destination supports [namespaces](https://docs.airbyte.com/platform/using-a | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------ | +| 0.2.3 | 2026-03-31 | [75645](https://github.com/airbytehq/airbyte/pull/75645) | Bump version to force registry update for supportLevel change to certified | | 0.2.2 | 2025-02-02 | [70438](https://github.com/airbytehq/airbyte/pull/70438) | Fix for camelCase columns being `NULL` | | 0.2.1 | 2025-12-19 | [70999](https://github.com/airbytehq/airbyte/pull/70999) | Fix for empty STRUCTs | | 0.2.0 | 2025-12-01 | [70221](https://github.com/airbytehq/airbyte/pull/70221) | Upgrade DuckDB to v1.4.2 and duckdb-engine to v0.17.0 | diff --git a/docs/integrations/destinations/pgvector.md b/docs/integrations/destinations/pgvector.md index 5812da1caa7c..84cba967d776 100644 --- a/docs/integrations/destinations/pgvector.md +++ b/docs/integrations/destinations/pgvector.md @@ -198,6 +198,7 @@ This destination does not support [namespaces](https://docs.airbyte.com/platform | Version | Date | Pull Request | Subject | |:--------| :--------- |:--------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------| +| 0.1.9 | 2026-03-31 | [75645](https://github.com/airbytehq/airbyte/pull/75645) | Bump version to force registry update for supportLevel change to community | | 0.1.8 | 2025-10-21 | [68347](https://github.com/airbytehq/airbyte/pull/68347) | Update dependencies | | 0.1.7 | 2025-10-14 | [67996](https://github.com/airbytehq/airbyte/pull/67996) | Update dependencies | | 0.1.6 | 2025-10-07 | [67175](https://github.com/airbytehq/airbyte/pull/67175) | Update dependencies | diff --git a/docs/integrations/destinations/snowflake-cortex.md b/docs/integrations/destinations/snowflake-cortex.md index 763eb4e34fef..a9ec87fad4b4 100644 --- a/docs/integrations/destinations/snowflake-cortex.md +++ b/docs/integrations/destinations/snowflake-cortex.md @@ -88,6 +88,7 @@ This destination does not support [namespaces](https://docs.airbyte.com/platform | Version | Date | Pull Request | Subject | |:--------| :--------- |:--------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------| +| 0.2.28 | 2026-03-31 | [75645](https://github.com/airbytehq/airbyte/pull/75645) | Bump version to force registry update for supportLevel change to community | | 0.2.27 | 2025-10-21 | [68344](https://github.com/airbytehq/airbyte/pull/68344) | Update dependencies | | 0.2.26 | 2025-10-14 | [63066](https://github.com/airbytehq/airbyte/pull/63066) | Update dependencies | | 0.2.25 | 2025-05-17 | [51743](https://github.com/airbytehq/airbyte/pull/51743) | Update dependencies | diff --git a/docs/integrations/destinations/weaviate.md b/docs/integrations/destinations/weaviate.md index aea6e4b71211..e92a6ec2bf2a 100644 --- a/docs/integrations/destinations/weaviate.md +++ b/docs/integrations/destinations/weaviate.md @@ -94,6 +94,7 @@ This destination does not support [namespaces](https://docs.airbyte.com/platform | Version | Date | Pull Request | Subject | |:--------| :--------- | :--------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | +| 0.2.61 | 2026-03-31 | [75645](https://github.com/airbytehq/airbyte/pull/75645) | Bump version to force registry update for supportLevel change to community | | 0.2.60 | 2025-09-16 | [61103](https://github.com/airbytehq/airbyte/pull/61103) | Update dependencies | | 0.2.59 | 2025-05-17 | [57180](https://github.com/airbytehq/airbyte/pull/57180) | Update dependencies | | 0.2.58 | 2025-03-29 | [56089](https://github.com/airbytehq/airbyte/pull/56089) | Update dependencies | From 1712295e2939ed67b29ea6aa627c69f8a512f947 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Mon, 30 Mar 2026 21:05:36 -0700 Subject: [PATCH 059/379] ci: remove legacy publish scripts (deps, spec cache, SBOM) (#75646) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/publish_connectors.yml | 46 +---- .../upload-additional-connector-metadata.sh | 118 ----------- poe-tasks/upload-python-dependencies.sh | 187 ------------------ 3 files changed, 6 insertions(+), 345 deletions(-) delete mode 100755 poe-tasks/upload-additional-connector-metadata.sh delete mode 100755 poe-tasks/upload-python-dependencies.sh diff --git a/.github/workflows/publish_connectors.yml b/.github/workflows/publish_connectors.yml index fdca377d9d64..ae6954bb8984 100644 --- a/.github/workflows/publish_connectors.yml +++ b/.github/workflows/publish_connectors.yml @@ -285,14 +285,6 @@ jobs: ;; esac - # We're intentionally not using the `google-github-actions/auth` action. - # The upload-additional-connector-metadata step runs a script which handles auth - # manually, because we're writing files to multiple buckets using different - # credentials for each bucket. - - name: Install gcloud - # v2.1.5 - uses: google-github-actions/setup-gcloud@6a7c903a70c8625ed6700fa299f5ddb4ca6022e9 - - name: Publish to Python Registry id: publish-python-registry if: steps.connector-metadata.outputs.connector-language == 'python' && needs.publish_options.outputs.dry-run != 'true' && needs.publish_options.outputs.with-semver-suffix == 'none' @@ -308,24 +300,6 @@ jobs: run: | echo "DRY-RUN: Skipping Python Registry publish for ${{ matrix.connector }}" - - name: Upload Python Dependencies to GCS - id: upload-python-dependencies-master - if: steps.connector-metadata.outputs.connector-language == 'python' && needs.publish_options.outputs.dry-run != 'true' - shell: bash - env: - GCS_CREDENTIALS: ${{ secrets.METADATA_SERVICE_PROD_GCS_CREDENTIALS }} - CONNECTOR_VERSION_TAG: ${{ steps.resolve-version.outputs.connector-version-tag }} - run: | - ./poe-tasks/upload-python-dependencies.sh \ - --name ${{ matrix.connector }} \ - --bucket prod-airbyte-cloud-connector-metadata-service \ - --with-semver-suffix ${{ needs.publish_options.outputs.with-semver-suffix }} - - - name: "[DRY-RUN] Skip Upload Python Dependencies to GCS" - if: steps.connector-metadata.outputs.connector-language == 'python' && needs.publish_options.outputs.dry-run == 'true' - run: | - echo "DRY-RUN: Skipping Python Dependencies upload for ${{ matrix.connector }}" - - name: Build and publish JVM connectors images id: build-and-publish-JVM-connectors-images if: steps.connector-metadata.outputs.connector-language == 'java' && needs.publish_options.outputs.dry-run != 'true' @@ -373,16 +347,6 @@ jobs: docker-hub-username: ${{ secrets.DOCKER_HUB_USERNAME }} docker-hub-password: ${{ secrets.DOCKER_HUB_PASSWORD }} - - name: Upload additional connector metadata (spec cache + SBOM) - id: upload-additional-connector-metadata - if: needs.publish_options.outputs.dry-run != 'true' - shell: bash - run: ./poe-tasks/upload-additional-connector-metadata.sh --name ${{ matrix.connector }} --with-semver-suffix ${{ needs.publish_options.outputs.with-semver-suffix }} - env: - SPEC_CACHE_GCS_CREDENTIALS: ${{ secrets.SPEC_CACHE_SERVICE_ACCOUNT_KEY_PUBLISH }} - METADATA_SERVICE_GCS_CREDENTIALS: ${{ secrets.METADATA_SERVICE_PROD_GCS_CREDENTIALS }} - CONNECTOR_VERSION_TAG: ${{ steps.resolve-version.outputs.connector-version-tag }} - # --- Registry artifact generation and publishing --- - name: Enable progressive rollout for RC builds @@ -428,15 +392,17 @@ jobs: registry connector-version artifacts generate \ --metadata-file "airbyte-integrations/connectors/${{ matrix.connector }}/metadata.yaml" \ --docker-image "${DOCKER_IMAGE}" \ - --output-dir ./registry-artifacts \ - --with-validate + --output-dir ./registry-artifacts/${{ matrix.connector }} \ + --with-validate \ + --with-sbom \ + --with-dependency-dump - name: Upload Registry CI Artifacts if: always() uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: registry-artifacts-${{ matrix.connector }}-${{ steps.resolve-docker-image-tag.outputs.docker-image-tag }} - path: ./registry-artifacts/ + path: ./registry-artifacts/${{ matrix.connector }}/ retention-days: 7 - name: Publish Registry Artifacts @@ -452,7 +418,7 @@ jobs: registry connector-version artifacts publish \ --name "${{ matrix.connector }}" \ --version "${{ steps.resolve-docker-image-tag.outputs.docker-image-tag }}" \ - --artifacts-dir ./registry-artifacts \ + --artifacts-dir ./registry-artifacts/${{ matrix.connector }} \ --store "${REGISTRY_STORE}" \ --with-validate diff --git a/poe-tasks/upload-additional-connector-metadata.sh b/poe-tasks/upload-additional-connector-metadata.sh deleted file mode 100755 index 0cc4da943e6c..000000000000 --- a/poe-tasks/upload-additional-connector-metadata.sh +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Uploads additional connector metadata (spec cache + SBOM) to GCS. -# -# The legacy `metadata_service upload` (metadata.yaml, icon.svg, doc.md, etc.) has been -# removed from this script — it is now handled by the ops CLI registry pipeline -# (publish_connector_registry_entries job in publish_connectors.yml). -# -# Usage: ./poe-tasks/upload-additional-connector-metadata.sh --name destination-bigquery --with-semver-suffix -# You must have two environment variables set (METADATA_SERVICE_GCS_CREDENTIALS, SPEC_CACHE_GCS_CREDENTIALS), -# each containing a JSON-formatted GCP service account key. -# SPEC_CACHE_GCS_CREDENTIALS needs write access to `gs://$spec_cache_bucket/specs`. -# METADATA_SERVICE_GCS_CREDENTIALS needs write access to `gs://$metadata_bucket/sbom`. - -source "${BASH_SOURCE%/*}/lib/util.sh" - -source "${BASH_SOURCE%/*}/lib/parse_args.sh" -connector=$(get_only_connector) - -if ! test "$SPEC_CACHE_GCS_CREDENTIALS"; then - echo "SPEC_CACHE_GCS_CREDENTIALS environment variable must be set" >&2 - exit 1 -fi -if ! test "$METADATA_SERVICE_GCS_CREDENTIALS"; then - echo "METADATA_SERVICE_GCS_CREDENTIALS environment variable must be set" >&2 - exit 1 -fi - -spec_cache_bucket="io-airbyte-cloud-spec-cache" -metadata_bucket="prod-airbyte-cloud-connector-metadata-service" - -syft_docker_image="anchore/syft:v1.6.0" -sbom_extension="spdx.json" - -meta="${CONNECTORS_DIR}/${connector}/metadata.yaml" - -docker_repository=$(yq -r '.data.dockerRepository' "$meta") -if test -z "$docker_repository" || test "$docker_repository" = "null"; then - echo "Error: docker_repository missing in ${meta}" >&2 - exit 1 -fi - -# Figure out the tag that we're working on (i.e. handle the prerelease case) -if [[ -n "${CONNECTOR_VERSION_TAG:-}" ]]; then - # When set by the publish workflow, use the pre-resolved tag directly. - docker_tag="$CONNECTOR_VERSION_TAG" -else - base_tag=$(yq -r '.data.dockerImageTag' "$meta") - if test -z "$base_tag" || test "$base_tag" = "null"; then - echo "Error: dockerImageTag missing in ${meta}" >&2 - exit 1 - fi - case "$semver_suffix" in - none) - docker_tag="$base_tag" - ;; - preview) - docker_tag=$(generate_dev_tag "$base_tag") - ;; - rc) - docker_tag=$(generate_rc_tag "$base_tag") - ;; - *) - echo "Error: Invalid semver_suffix '$semver_suffix'. Valid options are 'none', 'preview', or 'rc'." >&2 - exit 1 - ;; - esac -fi - -full_docker_image="$docker_repository:$docker_tag" - -# Upload the specs to the spec cache -run_connector_spec() { - local deployment_mode=$1 - local output_file=$2 - - # Run the spec command, filter for SPEC messages, and write those messages to the output file. - # The jq command has a lot going on: - # * --raw-input is needed, because many connectors emit some log messages in non-JSON format - # * then we use `fromjson?` to filter for valid JSON messages - # * and then we select any spec message (i.e. {"type": "SPEC", "spec": {...}}) - # * and then we extract just the `spec` field. - docker run --env DEPLOYMENT_MODE=$deployment_mode "$full_docker_image" spec | jq --raw-input --compact-output 'fromjson? | select(.type == "SPEC").spec' > $output_file - - # Verify that we had exactly one spec message. - # Depending on the platform, `wc -l` may return a right-padded string like " 1". - # `tr -d ' '` deletes those spaces. - local specMessageCount=$(cat $output_file | wc -l | tr -d ' ') - if test $specMessageCount -ne 1; then - echo "Expected to get exactly one spec message from the connector when running with deployment mode '$deployment_mode'; got $specMessageCount" >&2 - exit 1 - fi -} -echo '--- UPLOADING SPEC TO SPEC CACHE ---' -echo 'Running spec for OSS...' -run_connector_spec OSS spec.json -echo 'Running spec for CLOUD...' -run_connector_spec CLOUD spec.cloud.json -spec_cache_base_path="gs://$spec_cache_bucket/specs/$docker_repository/$docker_tag" -gcloud_activate_service_account "$SPEC_CACHE_GCS_CREDENTIALS" -gsutil cp spec.json "$spec_cache_base_path/spec.json" -# Only upload spec.cloud.json if it's different from spec.json. -# somewhat confusingly - `diff` returns true if the files are _identical_, so we need `! diff`. -if ! diff spec.json spec.cloud.json; then - gsutil cp spec.cloud.json "$spec_cache_base_path/spec.cloud.json" -fi - -# Upload the SBOM -echo '--- UPLOADING SBOM ---' -docker run \ - --volume $HOME/.docker/config.json:/config/config.json \ - --env DOCKER_CONFIG=/config \ - "$syft_docker_image" \ - -o spdx-json \ - "$full_docker_image" > "$sbom_extension" -gcloud_activate_service_account "$METADATA_SERVICE_GCS_CREDENTIALS" -gsutil cp "$sbom_extension" "gs://$metadata_bucket/sbom/$docker_repository/$docker_tag.$sbom_extension" diff --git a/poe-tasks/upload-python-dependencies.sh b/poe-tasks/upload-python-dependencies.sh deleted file mode 100755 index 02beeef1934f..000000000000 --- a/poe-tasks/upload-python-dependencies.sh +++ /dev/null @@ -1,187 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# -# Upload Python connector dependencies metadata to GCS -# Extracted from airbyte-ci publish pipeline for GitHub Actions integration -# -# Usage: ./poe-tasks/upload-python-dependencies.sh --name source-avri --with-semver-suffix [none | preview | rc] --bucket my-bucket --connector-version 1.2.3 -# - -# source utility functions -source "${BASH_SOURCE%/*}/lib/util.sh" - -function usage() { - cat << EOF -Usage: $0 [options] - -Upload Python connector dependencies metadata to GCS. - -Must be run from the root of the airbyte repo - -Options: - -n, --name CONNECTOR_NAME Connector name (required) - --bucket BUCKET_NAME GCS bucket name (optional, defaults to dev bucket) - --connector-version VERSION Connector version (optional, default reads from metadata.yaml) - --with-semver-suffix TYPE Semver suffix (optional): 'none', 'preview', or 'rc' (default is 'preview') - -h, --help Show this help message - -Environment Variables: - GCS_CREDENTIALS JSON-formatted GCP service account key set as an environment variable (required) - -Examples: - $0 --name source-avni - $0 --name source-avni --bucket my-test-bucket --version dev.1.2.3 -EOF -} - -# Default values -BUCKET_NAME="dev-airbyte-cloud-connector-metadata-service-2" -SEMVER_SUFFIX="preview" -CONNECTOR_NAME="" -VERSION="" - -# Parse command line arguments -while [[ $# -gt 0 ]]; do - case $1 in - -n|--name) - CONNECTOR_NAME="$2" - shift 2 - ;; - --bucket) - BUCKET_NAME="$2" - shift 2 - ;; - --connector-version) - VERSION="$2" - shift 2 - ;; - --with-semver-suffix) - SEMVER_SUFFIX="$2" - shift 2 - ;; - -h|--help) - usage - exit 0 - ;; - *) - echo "Unknown option: $1" >&2 - usage >&2 - exit 1 - ;; - esac -done - -# Validate required parameters -if [[ -z "$CONNECTOR_NAME" ]]; then - echo "Error: Connector name is required" >&2 - usage >&2 - exit 1 -fi - -# Use environment variables as fallback -if [[ -z "$BUCKET_NAME" ]]; then - echo "Error: GCS bucket name is required" >&2 - exit 1 -fi - -if ! test "$GCS_CREDENTIALS"; then - echo "GCS_CREDENTIALS environment variable must be set" >&2 - exit 1 -fi - -# Navigate to connector directory -CONNECTOR_DIR="airbyte-integrations/connectors/$CONNECTOR_NAME" -if [[ ! -d "$CONNECTOR_DIR" ]]; then - echo "Error: Connector directory not found: $CONNECTOR_DIR" >&2 - exit 1 -fi - -cd "$CONNECTOR_DIR" - -# Check if this is a Python connector -CONNECTOR_LANGUAGE=$(poe -qq get-language) -if [[ "$CONNECTOR_LANGUAGE" != "python" ]]; then - echo "⚠️ Connector language is '$CONNECTOR_LANGUAGE', not Python. Skipping dependencies upload." - exit 0 -fi - -# Resolve the connector version -if [[ -n "${CONNECTOR_VERSION_TAG:-}" ]]; then - # When set by the publish workflow, use the pre-resolved tag directly. - VERSION="$CONNECTOR_VERSION_TAG" -else - if [[ -z "$VERSION" ]]; then - VERSION=$(poe -qq get-version) - fi - case "$SEMVER_SUFFIX" in - none) - # Use exact version from metadata.yaml - ;; - preview) - VERSION=$(generate_dev_tag "$VERSION") - ;; - rc) - VERSION=$(generate_rc_tag "$VERSION") - ;; - *) - echo "Error: Invalid semver suffix '$SEMVER_SUFFIX'. Valid options are 'none', 'preview', or 'rc'." >&2 - exit 1 - ;; - esac -fi - -echo "📋 Uploading dependencies for connector: $CONNECTOR_NAME" -echo " 🏷️ Version: $VERSION" -echo " 🪣 GCS Bucket: $BUCKET_NAME" - -DOCKER_REPOSITORY=$(yq eval '.data.dockerRepository' metadata.yaml) -DEFINITION_ID=$(yq eval '.data.definitionId' metadata.yaml) - -# Authenticate with GCS -gcloud_activate_service_account "$GCS_CREDENTIALS" - -# Install the connector and get dependencies -if ! [[ -f "pyproject.toml" ]]; then - echo "⚠️ No pyproject.toml found, skipping dependency upload" >&2 - exit 0 -fi - -# Install connector dependencies using Poetry (without dev dependencies) -poetry install --without dev - -# This command reformats the output of `pip freeze` into a JSON array of objects -# Each line that looks like `package==version` is transformed into an object with `package_name` and `version` keys -# Example output: -# [ -# {"package_name": "requests", "version": "2.25.1"}, -# {"package_name": "pandas", "version": "1.2.3"} -# ] -DEPENDENCIES_JSON=$(poetry run pip freeze | jq -R -s -c 'split("\n") | map(select(contains("=="))) | map({package_name: split("==")[0], version: split("==")[1]})') - -# Get current timestamp. Sed command is used to remove the last 3 digits of nanoseconds for backwards compatibility -GENERATION_TIME=$(date -u +"%Y-%m-%dT%H:%M:%S.%N" | sed 's/\([0-9]\{6\}\)[0-9]\{3\}$/\1/') - -METADATA_JSON=$(cat << EOF -{ - "connector_technical_name": "$CONNECTOR_NAME", - "connector_repository": "$DOCKER_REPOSITORY", - "connector_version": "$VERSION", - "connector_definition_id": "$DEFINITION_ID", - "dependencies": $DEPENDENCIES_JSON, - "generation_time": "$GENERATION_TIME" -} -EOF -) - -# Create temporary file for upload -TEMP_FILE=$(mktemp) -echo "$METADATA_JSON" > "$TEMP_FILE" - -# Upload to GCS -GCS_KEY="connector_dependencies/${CONNECTOR_NAME}/${VERSION}/dependencies.json" -echo "Uploading to: gs://${BUCKET_NAME}/${GCS_KEY}" - -gsutil cp "$TEMP_FILE" "gs://${BUCKET_NAME}/${GCS_KEY}" - -echo "✅ Successfully uploaded dependencies metadata for $CONNECTOR_NAME ($VERSION)" From fc20c64cb86639c79571bfa7193d9108d6496b01 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:53:53 +0000 Subject: [PATCH 060/379] =?UTF-8?q?deps(source-campaign-monitor):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75683)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-campaign-monitor/metadata.yaml | 4 ++-- docs/integrations/sources/campaign-monitor.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-campaign-monitor/metadata.yaml b/airbyte-integrations/connectors/source-campaign-monitor/metadata.yaml index c41b4e499b23..890754896ed6 100644 --- a/airbyte-integrations/connectors/source-campaign-monitor/metadata.yaml +++ b/airbyte-integrations/connectors/source-campaign-monitor/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-campaign-monitor connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 9d350ec7-2860-4106-a331-7d9403dd9a02 - dockerImageTag: 0.0.41 + dockerImageTag: 0.0.42 dockerRepository: airbyte/source-campaign-monitor githubIssueLabel: source-campaign-monitor icon: icon.svg diff --git a/docs/integrations/sources/campaign-monitor.md b/docs/integrations/sources/campaign-monitor.md index 160bf5ff48b7..606596dc9b9c 100644 --- a/docs/integrations/sources/campaign-monitor.md +++ b/docs/integrations/sources/campaign-monitor.md @@ -59,6 +59,7 @@ The source connector supports the following [sync modes](https://docs.airbyte.co | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.42 | 2026-03-31 | [75683](https://github.com/airbytehq/airbyte/pull/75683) | Update dependencies | | 0.0.41 | 2026-03-17 | [74939](https://github.com/airbytehq/airbyte/pull/74939) | Update dependencies | | 0.0.40 | 2026-03-10 | [74631](https://github.com/airbytehq/airbyte/pull/74631) | Update dependencies | | 0.0.39 | 2026-03-03 | [74200](https://github.com/airbytehq/airbyte/pull/74200) | Update dependencies | From d55520c20d6fdcc4432139fb21f9a03aaca4bc7d Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:53:59 +0000 Subject: [PATCH 061/379] =?UTF-8?q?deps(source-capsule-crm):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75681)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-capsule-crm/metadata.yaml | 4 ++-- docs/integrations/sources/capsule-crm.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-capsule-crm/metadata.yaml b/airbyte-integrations/connectors/source-capsule-crm/metadata.yaml index 4c16df5caefc..de6fb61dd540 100644 --- a/airbyte-integrations/connectors/source-capsule-crm/metadata.yaml +++ b/airbyte-integrations/connectors/source-capsule-crm/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-capsule-crm connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 4f1b8b9c-fa2c-4fc2-b041-e3bde27a0cb1 - dockerImageTag: 0.0.39 + dockerImageTag: 0.0.40 dockerRepository: airbyte/source-capsule-crm githubIssueLabel: source-capsule-crm icon: icon.svg diff --git a/docs/integrations/sources/capsule-crm.md b/docs/integrations/sources/capsule-crm.md index d41e30dd23f2..04126e0dd7c2 100644 --- a/docs/integrations/sources/capsule-crm.md +++ b/docs/integrations/sources/capsule-crm.md @@ -36,6 +36,7 @@ Capsule CRM connector enables seamless data syncing from Capsule CRM to various | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.40 | 2026-03-31 | [75681](https://github.com/airbytehq/airbyte/pull/75681) | Update dependencies | | 0.0.39 | 2026-03-17 | [74916](https://github.com/airbytehq/airbyte/pull/74916) | Update dependencies | | 0.0.38 | 2026-03-03 | [74215](https://github.com/airbytehq/airbyte/pull/74215) | Update dependencies | | 0.0.37 | 2026-02-17 | [73425](https://github.com/airbytehq/airbyte/pull/73425) | Update dependencies | From 78e32e2852b19dbe52d7899ab5d6909263d4b360 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:54:03 +0000 Subject: [PATCH 062/379] =?UTF-8?q?deps(source-jotform):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75680)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-jotform/metadata.yaml | 4 ++-- docs/integrations/sources/jotform.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-jotform/metadata.yaml b/airbyte-integrations/connectors/source-jotform/metadata.yaml index 1eb80013d813..ef3b4569cddf 100644 --- a/airbyte-integrations/connectors/source-jotform/metadata.yaml +++ b/airbyte-integrations/connectors/source-jotform/metadata.yaml @@ -16,11 +16,11 @@ data: enabled: false packageName: airbyte-source-jotform connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 3456679e-2ff2-4ef7-aa9f-da6c0cc13894 - dockerImageTag: 0.0.45 + dockerImageTag: 0.0.46 dockerRepository: airbyte/source-jotform githubIssueLabel: source-jotform icon: icon.svg diff --git a/docs/integrations/sources/jotform.md b/docs/integrations/sources/jotform.md index 6e8d6800adaa..05bcfc79a28b 100644 --- a/docs/integrations/sources/jotform.md +++ b/docs/integrations/sources/jotform.md @@ -32,6 +32,7 @@ To get started, you need a valid API key. | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.46 | 2026-03-31 | [75680](https://github.com/airbytehq/airbyte/pull/75680) | Update dependencies | | 0.0.45 | 2026-03-24 | [74519](https://github.com/airbytehq/airbyte/pull/74519) | Update dependencies | | 0.0.44 | 2026-03-03 | [73929](https://github.com/airbytehq/airbyte/pull/73929) | Update dependencies | | 0.0.43 | 2026-02-17 | [73482](https://github.com/airbytehq/airbyte/pull/73482) | Update dependencies | From e4abeb7d458e1a98a79cd08cea30dba145e033ad Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:54:08 +0000 Subject: [PATCH 063/379] =?UTF-8?q?deps(source-ip2whois):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75679)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-ip2whois/metadata.yaml | 4 ++-- docs/integrations/sources/ip2whois.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-ip2whois/metadata.yaml b/airbyte-integrations/connectors/source-ip2whois/metadata.yaml index 1eac90cee8ba..68c53c9417aa 100644 --- a/airbyte-integrations/connectors/source-ip2whois/metadata.yaml +++ b/airbyte-integrations/connectors/source-ip2whois/metadata.yaml @@ -3,11 +3,11 @@ data: ql: 100 sl: 100 connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: f23b7b7c-d705-49a3-9042-09add3b104a5 - dockerImageTag: 0.2.49 + dockerImageTag: 0.2.50 dockerRepository: airbyte/source-ip2whois documentationUrl: https://docs.airbyte.com/integrations/sources/ip2whois githubIssueLabel: source-ip2whois diff --git a/docs/integrations/sources/ip2whois.md b/docs/integrations/sources/ip2whois.md index 77846578d3aa..b06c7e5a45c7 100644 --- a/docs/integrations/sources/ip2whois.md +++ b/docs/integrations/sources/ip2whois.md @@ -32,6 +32,7 @@ Ip2whois APIs allows you to query up to 500 WHOIS domain name per month. | Version | Date | Pull Request | Subject | | :------ | :--------- | :-------------------------------------------------------- | :------------------------------------------------------------------------------ | +| 0.2.50 | 2026-03-31 | [75679](https://github.com/airbytehq/airbyte/pull/75679) | Update dependencies | | 0.2.49 | 2026-03-17 | [75061](https://github.com/airbytehq/airbyte/pull/75061) | Update dependencies | | 0.2.48 | 2026-03-10 | [74498](https://github.com/airbytehq/airbyte/pull/74498) | Update dependencies | | 0.2.47 | 2026-02-24 | [73894](https://github.com/airbytehq/airbyte/pull/73894) | Update dependencies | From bc8d2dd49bfac5b285162325ee4cfbb0d5a8f94e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:54:13 +0000 Subject: [PATCH 064/379] =?UTF-8?q?deps(source-imagga):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75677)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-imagga/metadata.yaml | 4 ++-- docs/integrations/sources/imagga.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-imagga/metadata.yaml b/airbyte-integrations/connectors/source-imagga/metadata.yaml index c1fa45f83ca0..c898a3b93abb 100644 --- a/airbyte-integrations/connectors/source-imagga/metadata.yaml +++ b/airbyte-integrations/connectors/source-imagga/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-imagga connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 3d4a824d-13a1-441a-ae9d-610b10013b49 - dockerImageTag: 0.0.31 + dockerImageTag: 0.0.32 dockerRepository: airbyte/source-imagga githubIssueLabel: source-imagga icon: icon.svg diff --git a/docs/integrations/sources/imagga.md b/docs/integrations/sources/imagga.md index 74653373125d..bb813cf93dcb 100644 --- a/docs/integrations/sources/imagga.md +++ b/docs/integrations/sources/imagga.md @@ -28,6 +28,7 @@ API Reference: https://docs.imagga.com/#introduction | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.32 | 2026-03-31 | [75677](https://github.com/airbytehq/airbyte/pull/75677) | Update dependencies | | 0.0.31 | 2026-03-24 | [75339](https://github.com/airbytehq/airbyte/pull/75339) | Update dependencies | | 0.0.30 | 2026-03-10 | [74497](https://github.com/airbytehq/airbyte/pull/74497) | Update dependencies | | 0.0.29 | 2026-03-03 | [73084](https://github.com/airbytehq/airbyte/pull/73084) | Update dependencies | From c3bfeda67aa03f8af35bf6eb53647c1fc529dbde Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:54:17 +0000 Subject: [PATCH 065/379] =?UTF-8?q?deps(source-insightful):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75676)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-insightful/metadata.yaml | 4 ++-- docs/integrations/sources/insightful.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-insightful/metadata.yaml b/airbyte-integrations/connectors/source-insightful/metadata.yaml index f760cf43d791..bc8af2dd25f7 100644 --- a/airbyte-integrations/connectors/source-insightful/metadata.yaml +++ b/airbyte-integrations/connectors/source-insightful/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-insightful connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: befe5bfb-617c-4250-9f7d-c9ad32277817 - dockerImageTag: 0.0.33 + dockerImageTag: 0.0.34 dockerRepository: airbyte/source-insightful githubIssueLabel: source-insightful icon: icon.svg diff --git a/docs/integrations/sources/insightful.md b/docs/integrations/sources/insightful.md index 74923e1b7cff..c5546d0b9d36 100644 --- a/docs/integrations/sources/insightful.md +++ b/docs/integrations/sources/insightful.md @@ -28,6 +28,7 @@ API Reference: https://developers.insightful.io/ | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.34 | 2026-03-31 | [75676](https://github.com/airbytehq/airbyte/pull/75676) | Update dependencies | | 0.0.33 | 2026-03-24 | [75337](https://github.com/airbytehq/airbyte/pull/75337) | Update dependencies | | 0.0.32 | 2026-03-10 | [74517](https://github.com/airbytehq/airbyte/pull/74517) | Update dependencies | | 0.0.31 | 2026-03-03 | [74184](https://github.com/airbytehq/airbyte/pull/74184) | Update dependencies | From 8ed8d7dc4abd157b6776a7a080b25b640d7312b9 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:54:22 +0000 Subject: [PATCH 066/379] =?UTF-8?q?deps(source-pabbly-subscriptions-billin?= =?UTF-8?q?g):=20=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#7?= =?UTF-8?q?5675)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../source-pabbly-subscriptions-billing/metadata.yaml | 4 ++-- docs/integrations/sources/pabbly-subscriptions-billing.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-pabbly-subscriptions-billing/metadata.yaml b/airbyte-integrations/connectors/source-pabbly-subscriptions-billing/metadata.yaml index 9585544fd2af..de3c6d854bfa 100644 --- a/airbyte-integrations/connectors/source-pabbly-subscriptions-billing/metadata.yaml +++ b/airbyte-integrations/connectors/source-pabbly-subscriptions-billing/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-pabbly-subscriptions-billing connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: b461c060-9d6a-43c9-a73c-634eaf83c4bf - dockerImageTag: 0.0.46 + dockerImageTag: 0.0.47 dockerRepository: airbyte/source-pabbly-subscriptions-billing githubIssueLabel: source-pabbly-subscriptions-billing icon: icon.svg diff --git a/docs/integrations/sources/pabbly-subscriptions-billing.md b/docs/integrations/sources/pabbly-subscriptions-billing.md index 7e0babb20faa..b3080ca54d41 100644 --- a/docs/integrations/sources/pabbly-subscriptions-billing.md +++ b/docs/integrations/sources/pabbly-subscriptions-billing.md @@ -32,6 +32,7 @@ Airbyte connector for [Pabbly Subscriptions Billing](https://www.pabbly.com/subs | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.47 | 2026-03-31 | [75675](https://github.com/airbytehq/airbyte/pull/75675) | Update dependencies | | 0.0.46 | 2026-03-24 | [75327](https://github.com/airbytehq/airbyte/pull/75327) | Update dependencies | | 0.0.45 | 2026-03-10 | [74649](https://github.com/airbytehq/airbyte/pull/74649) | Update dependencies | | 0.0.44 | 2026-02-24 | [73814](https://github.com/airbytehq/airbyte/pull/73814) | Update dependencies | From cb19253617dc2a3ad66cfc4cc8c087605b267048 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:54:27 +0000 Subject: [PATCH 067/379] =?UTF-8?q?deps(source-gologin):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75674)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-gologin/metadata.yaml | 4 ++-- docs/integrations/sources/gologin.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-gologin/metadata.yaml b/airbyte-integrations/connectors/source-gologin/metadata.yaml index 47b443a2c30b..ef0b6a49e8a5 100644 --- a/airbyte-integrations/connectors/source-gologin/metadata.yaml +++ b/airbyte-integrations/connectors/source-gologin/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-gologin connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 02e5177c-84cf-424c-91e4-9f7ce344b813 - dockerImageTag: 0.0.30 + dockerImageTag: 0.0.31 dockerRepository: airbyte/source-gologin githubIssueLabel: source-gologin icon: icon.svg diff --git a/docs/integrations/sources/gologin.md b/docs/integrations/sources/gologin.md index 1d7f4c932374..5385799c19b8 100644 --- a/docs/integrations/sources/gologin.md +++ b/docs/integrations/sources/gologin.md @@ -29,6 +29,7 @@ Postman API Reference: https://documenter.getpostman.com/view/21126834/Uz5GnvaL# | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.31 | 2026-03-31 | [75674](https://github.com/airbytehq/airbyte/pull/75674) | Update dependencies | | 0.0.30 | 2026-03-17 | [74562](https://github.com/airbytehq/airbyte/pull/74562) | Update dependencies | | 0.0.29 | 2026-02-24 | [73767](https://github.com/airbytehq/airbyte/pull/73767) | Update dependencies | | 0.0.28 | 2026-02-17 | [73087](https://github.com/airbytehq/airbyte/pull/73087) | Update dependencies | From e85da8d87235ab57d60454366a450b57eed55ebd Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:54:32 +0000 Subject: [PATCH 068/379] =?UTF-8?q?deps(source-onepagecrm):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75673)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-onepagecrm/metadata.yaml | 4 ++-- docs/integrations/sources/onepagecrm.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-onepagecrm/metadata.yaml b/airbyte-integrations/connectors/source-onepagecrm/metadata.yaml index 020a64af261a..ae73813f4682 100644 --- a/airbyte-integrations/connectors/source-onepagecrm/metadata.yaml +++ b/airbyte-integrations/connectors/source-onepagecrm/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-onepagecrm connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: d59cce29-baa8-4202-b1ca-a4759c20c908 - dockerImageTag: 0.0.49 + dockerImageTag: 0.0.50 dockerRepository: airbyte/source-onepagecrm githubIssueLabel: source-onepagecrm icon: icon.svg diff --git a/docs/integrations/sources/onepagecrm.md b/docs/integrations/sources/onepagecrm.md index ac7d7882f414..653f2bd9bc32 100644 --- a/docs/integrations/sources/onepagecrm.md +++ b/docs/integrations/sources/onepagecrm.md @@ -40,6 +40,7 @@ Using this stream we can extarct data from various streams such as contacts , de | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.50 | 2026-03-31 | [75673](https://github.com/airbytehq/airbyte/pull/75673) | Update dependencies | | 0.0.49 | 2026-03-24 | [74988](https://github.com/airbytehq/airbyte/pull/74988) | Update dependencies | | 0.0.48 | 2026-03-10 | [74659](https://github.com/airbytehq/airbyte/pull/74659) | Update dependencies | | 0.0.47 | 2026-03-03 | [73570](https://github.com/airbytehq/airbyte/pull/73570) | Update dependencies | From 186711416ddf93dd410db422af0a78f918d0bc8d Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:54:38 +0000 Subject: [PATCH 069/379] =?UTF-8?q?deps(source-brevo):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75672)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-brevo/metadata.yaml | 4 ++-- docs/integrations/sources/brevo.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-brevo/metadata.yaml b/airbyte-integrations/connectors/source-brevo/metadata.yaml index 855bd527d9be..4b03b4ec193d 100644 --- a/airbyte-integrations/connectors/source-brevo/metadata.yaml +++ b/airbyte-integrations/connectors/source-brevo/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-brevo connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: e2276f19-1c19-4d4e-ae6c-7df3c9c4ad49 - dockerImageTag: 0.2.28 + dockerImageTag: 0.2.29 dockerRepository: airbyte/source-brevo githubIssueLabel: source-brevo icon: icon.svg diff --git a/docs/integrations/sources/brevo.md b/docs/integrations/sources/brevo.md index 2d91c3fc9e28..7dc29e707168 100644 --- a/docs/integrations/sources/brevo.md +++ b/docs/integrations/sources/brevo.md @@ -49,6 +49,7 @@ Visit `https://app.brevo.com/settings/keys/api` for getting your api key. | Version | Date | Pull Request | Subject | | ------------------ | ------------ | --- | ---------------- | +| 0.2.29 | 2026-03-31 | [75672](https://github.com/airbytehq/airbyte/pull/75672) | Update dependencies | | 0.2.28 | 2026-03-24 | [75312](https://github.com/airbytehq/airbyte/pull/75312) | Update dependencies | | 0.2.27 | 2026-02-17 | [73432](https://github.com/airbytehq/airbyte/pull/73432) | Update dependencies | | 0.2.26 | 2026-02-03 | [72612](https://github.com/airbytehq/airbyte/pull/72612) | Update dependencies | From ef90d0f7a3957b148b196c7472a52bb4d30d1d32 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:54:43 +0000 Subject: [PATCH 070/379] =?UTF-8?q?deps(source-google-calendar):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75671)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-google-calendar/metadata.yaml | 4 ++-- docs/integrations/sources/google-calendar.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-google-calendar/metadata.yaml b/airbyte-integrations/connectors/source-google-calendar/metadata.yaml index 84e9d403418e..0dfb280c4ac1 100644 --- a/airbyte-integrations/connectors/source-google-calendar/metadata.yaml +++ b/airbyte-integrations/connectors/source-google-calendar/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-google-calendar connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: c01b6259-bdf4-45ff-bcd5-66424cd2f18b - dockerImageTag: 0.0.36 + dockerImageTag: 0.0.37 dockerRepository: airbyte/source-google-calendar githubIssueLabel: source-google-calendar icon: icon.svg diff --git a/docs/integrations/sources/google-calendar.md b/docs/integrations/sources/google-calendar.md index b9558e9506d8..98de41dd0517 100644 --- a/docs/integrations/sources/google-calendar.md +++ b/docs/integrations/sources/google-calendar.md @@ -26,6 +26,7 @@ Solves https://github.com/airbytehq/airbyte/issues/45995 | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.37 | 2026-03-31 | [75671](https://github.com/airbytehq/airbyte/pull/75671) | Update dependencies | | 0.0.36 | 2026-03-17 | [74985](https://github.com/airbytehq/airbyte/pull/74985) | Update dependencies | | 0.0.35 | 2026-02-24 | [73746](https://github.com/airbytehq/airbyte/pull/73746) | Update dependencies | | 0.0.34 | 2026-02-17 | [73085](https://github.com/airbytehq/airbyte/pull/73085) | Update dependencies | From c8284cbddaef4353e09337cadf3c284d9305a252 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:54:50 +0000 Subject: [PATCH 071/379] =?UTF-8?q?deps(source-campayn):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75669)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-campayn/metadata.yaml | 4 ++-- docs/integrations/sources/campayn.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-campayn/metadata.yaml b/airbyte-integrations/connectors/source-campayn/metadata.yaml index 03e47c81c3ca..d516a8bb6d31 100644 --- a/airbyte-integrations/connectors/source-campayn/metadata.yaml +++ b/airbyte-integrations/connectors/source-campayn/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-campayn connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 5674ae5a-511e-4093-9da9-086bf5f0b568 - dockerImageTag: 0.0.43 + dockerImageTag: 0.0.44 dockerRepository: airbyte/source-campayn githubIssueLabel: source-campayn icon: icon.svg diff --git a/docs/integrations/sources/campayn.md b/docs/integrations/sources/campayn.md index 61d59616a7f1..fae27639b0ce 100644 --- a/docs/integrations/sources/campayn.md +++ b/docs/integrations/sources/campayn.md @@ -24,6 +24,7 @@ The Airbyte connector for [Campayn](https://campayn.com/) enables seamless data | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.44 | 2026-03-31 | [75669](https://github.com/airbytehq/airbyte/pull/75669) | Update dependencies | | 0.0.43 | 2026-03-24 | [74942](https://github.com/airbytehq/airbyte/pull/74942) | Update dependencies | | 0.0.42 | 2026-02-24 | [73788](https://github.com/airbytehq/airbyte/pull/73788) | Update dependencies | | 0.0.41 | 2026-02-17 | [73434](https://github.com/airbytehq/airbyte/pull/73434) | Update dependencies | From 5be7b25ac8c4d44326ed0bb182c9cd329354813e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:54:56 +0000 Subject: [PATCH 072/379] =?UTF-8?q?deps(source-getgist):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75668)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-getgist/metadata.yaml | 4 ++-- docs/integrations/sources/getgist.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-getgist/metadata.yaml b/airbyte-integrations/connectors/source-getgist/metadata.yaml index 9e3b003eb27c..b1beb7663020 100644 --- a/airbyte-integrations/connectors/source-getgist/metadata.yaml +++ b/airbyte-integrations/connectors/source-getgist/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-getgist connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: bc670226-bee1-470c-a013-df05e5ac8f1a - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-getgist githubIssueLabel: source-getgist icon: icon.svg diff --git a/docs/integrations/sources/getgist.md b/docs/integrations/sources/getgist.md index 38b0df0db112..d28c17bc105f 100644 --- a/docs/integrations/sources/getgist.md +++ b/docs/integrations/sources/getgist.md @@ -27,6 +27,7 @@ An Airbyte connector for [Gist](https://getgist.com/) would enable data syncing | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.48 | 2026-03-31 | [75668](https://github.com/airbytehq/airbyte/pull/75668) | Update dependencies | | 0.0.47 | 2026-03-17 | [74957](https://github.com/airbytehq/airbyte/pull/74957) | Update dependencies | | 0.0.46 | 2026-03-10 | [74533](https://github.com/airbytehq/airbyte/pull/74533) | Update dependencies | | 0.0.45 | 2026-02-24 | [73768](https://github.com/airbytehq/airbyte/pull/73768) | Update dependencies | From d8dc02bd9e949d27720a8b61f2437341a2f92e0d Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:55:05 +0000 Subject: [PATCH 073/379] =?UTF-8?q?deps(source-care-quality-commission):?= =?UTF-8?q?=20=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#7566?= =?UTF-8?q?6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-care-quality-commission/metadata.yaml | 4 ++-- docs/integrations/sources/care-quality-commission.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-care-quality-commission/metadata.yaml b/airbyte-integrations/connectors/source-care-quality-commission/metadata.yaml index 45e5361dfa56..0e898b4dc062 100644 --- a/airbyte-integrations/connectors/source-care-quality-commission/metadata.yaml +++ b/airbyte-integrations/connectors/source-care-quality-commission/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-care-quality-commission connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 2366b7bf-b83e-471c-b4a0-1405887fdf6e - dockerImageTag: 0.0.46 + dockerImageTag: 0.0.47 dockerRepository: airbyte/source-care-quality-commission githubIssueLabel: source-care-quality-commission icon: icon.svg diff --git a/docs/integrations/sources/care-quality-commission.md b/docs/integrations/sources/care-quality-commission.md index 66f6691d0bcb..99c691616925 100644 --- a/docs/integrations/sources/care-quality-commission.md +++ b/docs/integrations/sources/care-quality-commission.md @@ -25,6 +25,7 @@ https://www.cqc.org.uk/ | Version | Date | Pull Request | Subject | |---------|------------|----------------------------------------------------------|-------------------------------------------------------------------------------------------| +| 0.0.47 | 2026-03-31 | [75666](https://github.com/airbytehq/airbyte/pull/75666) | Update dependencies | | 0.0.46 | 2026-03-24 | [75310](https://github.com/airbytehq/airbyte/pull/75310) | Update dependencies | | 0.0.45 | 2026-03-10 | [74606](https://github.com/airbytehq/airbyte/pull/74606) | Update dependencies | | 0.0.44 | 2026-02-17 | [73424](https://github.com/airbytehq/airbyte/pull/73424) | Update dependencies | From 370054b1b270e101215195655cceaf2344bce58e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:55:12 +0000 Subject: [PATCH 074/379] =?UTF-8?q?deps(source-hubspot):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75665)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-hubspot/metadata.yaml | 4 ++-- docs/integrations/sources/hubspot.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-hubspot/metadata.yaml b/airbyte-integrations/connectors/source-hubspot/metadata.yaml index 2e66076de1f4..2b6f7fdb0161 100644 --- a/airbyte-integrations/connectors/source-hubspot/metadata.yaml +++ b/airbyte-integrations/connectors/source-hubspot/metadata.yaml @@ -6,11 +6,11 @@ data: hosts: - api.hubapi.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 36c891d9-4bd9-43ac-bad2-10e12756272c - dockerImageTag: 6.3.4 + dockerImageTag: 6.3.5 dockerRepository: airbyte/source-hubspot documentationUrl: https://docs.airbyte.com/integrations/sources/hubspot resourceRequirements: diff --git a/docs/integrations/sources/hubspot.md b/docs/integrations/sources/hubspot.md index bd5b70583eed..5144a7efa3d1 100644 --- a/docs/integrations/sources/hubspot.md +++ b/docs/integrations/sources/hubspot.md @@ -342,6 +342,7 @@ If you use [custom properties](https://knowledge.hubspot.com/properties/create-a | Version | Date | Pull Request | Subject | |:------------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 6.3.5 | 2026-03-31 | [75665](https://github.com/airbytehq/airbyte/pull/75665) | Update dependencies | | 6.3.4 | 2026-03-30 | [75595](https://github.com/airbytehq/airbyte/pull/75595) | Fixed HTTP 429 responses mapped to RETRY instead of RATE_LIMITED, enabling correct rate-limit handling | | 6.3.3 | 2026-03-26 | [75452](https://github.com/airbytehq/airbyte/pull/75452) | Fixed HTTP 401 errors retrying indefinitely for Private App Token authentication | | 6.3.2 | 2026-03-17 | [74526](https://github.com/airbytehq/airbyte/pull/74526) | Update dependencies | From f506857d3a626c64e5bb6258b495bac5a761244d Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:55:17 +0000 Subject: [PATCH 075/379] =?UTF-8?q?deps(source-freshservice):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75664)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-freshservice/metadata.yaml | 4 ++-- docs/integrations/sources/freshservice.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-freshservice/metadata.yaml b/airbyte-integrations/connectors/source-freshservice/metadata.yaml index a8e6aac821b3..96b345d699f6 100644 --- a/airbyte-integrations/connectors/source-freshservice/metadata.yaml +++ b/airbyte-integrations/connectors/source-freshservice/metadata.yaml @@ -3,11 +3,11 @@ data: hosts: - ${domain_name}/api/v2 connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 9bb85338-ea95-4c93-b267-6be89125b267 - dockerImageTag: 1.4.52 + dockerImageTag: 1.4.53 dockerRepository: airbyte/source-freshservice documentationUrl: https://docs.airbyte.com/integrations/sources/freshservice githubIssueLabel: source-freshservice diff --git a/docs/integrations/sources/freshservice.md b/docs/integrations/sources/freshservice.md index 4d038abd9594..b55e40897fce 100644 --- a/docs/integrations/sources/freshservice.md +++ b/docs/integrations/sources/freshservice.md @@ -80,6 +80,7 @@ This connector uses the [Freshservice REST API v2](https://api.freshservice.com/ | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- |:---------------------------------------------------------------------------------------| +| 1.4.53 | 2026-03-31 | [75664](https://github.com/airbytehq/airbyte/pull/75664) | Update dependencies | | 1.4.52 | 2026-03-17 | [74560](https://github.com/airbytehq/airbyte/pull/74560) | Update dependencies | | 1.4.51 | 2026-03-03 | [74208](https://github.com/airbytehq/airbyte/pull/74208) | Update dependencies | | 1.4.50 | 2026-02-17 | [73399](https://github.com/airbytehq/airbyte/pull/73399) | Update dependencies | From 14fea0cb28938116e081a75b29e16556d88e3bb8 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:55:25 +0000 Subject: [PATCH 076/379] =?UTF-8?q?deps(source-bluetally):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75662)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-bluetally/metadata.yaml | 4 ++-- docs/integrations/sources/bluetally.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-bluetally/metadata.yaml b/airbyte-integrations/connectors/source-bluetally/metadata.yaml index 6c417fefc289..b700b47699e8 100644 --- a/airbyte-integrations/connectors/source-bluetally/metadata.yaml +++ b/airbyte-integrations/connectors/source-bluetally/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-bluetally connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: d4154c0b-7737-42c3-92dc-7a8e046e6456 - dockerImageTag: 0.0.22 + dockerImageTag: 0.0.23 dockerRepository: airbyte/source-bluetally githubIssueLabel: source-bluetally icon: icon.svg diff --git a/docs/integrations/sources/bluetally.md b/docs/integrations/sources/bluetally.md index 28e3fc8301ee..dccc47dccdb5 100644 --- a/docs/integrations/sources/bluetally.md +++ b/docs/integrations/sources/bluetally.md @@ -21,6 +21,7 @@ Connector for fetching asset and employee data from Bluetelly | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.23 | 2026-03-31 | [75662](https://github.com/airbytehq/airbyte/pull/75662) | Update dependencies | | 0.0.22 | 2026-03-17 | [74915](https://github.com/airbytehq/airbyte/pull/74915) | Update dependencies | | 0.0.21 | 2026-02-10 | [73144](https://github.com/airbytehq/airbyte/pull/73144) | Update dependencies | | 0.0.20 | 2026-02-03 | [72625](https://github.com/airbytehq/airbyte/pull/72625) | Update dependencies | From aaa27f61430f98663f1afa07b09b446d2884b9e8 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:55:31 +0000 Subject: [PATCH 077/379] =?UTF-8?q?deps(source-google-classroom):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75660)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-google-classroom/metadata.yaml | 4 ++-- docs/integrations/sources/google-classroom.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-google-classroom/metadata.yaml b/airbyte-integrations/connectors/source-google-classroom/metadata.yaml index 3ce2250a7017..96ef746a8d1f 100644 --- a/airbyte-integrations/connectors/source-google-classroom/metadata.yaml +++ b/airbyte-integrations/connectors/source-google-classroom/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-google-classroom connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 2c3aa088-396d-4ee6-8096-971ecd11598c - dockerImageTag: 0.0.45 + dockerImageTag: 0.0.46 dockerRepository: airbyte/source-google-classroom githubIssueLabel: source-google-classroom icon: icon.svg diff --git a/docs/integrations/sources/google-classroom.md b/docs/integrations/sources/google-classroom.md index cb2ed2067862..25e6015b9b19 100644 --- a/docs/integrations/sources/google-classroom.md +++ b/docs/integrations/sources/google-classroom.md @@ -26,6 +26,7 @@ Google Classroom connector enables seamless data integration between Google Clas | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.46 | 2026-03-31 | [75660](https://github.com/airbytehq/airbyte/pull/75660) | Update dependencies | | 0.0.45 | 2026-03-17 | [74656](https://github.com/airbytehq/airbyte/pull/74656) | Update dependencies | | 0.0.44 | 2026-02-24 | [73933](https://github.com/airbytehq/airbyte/pull/73933) | Update dependencies | | 0.0.43 | 2026-01-20 | [71927](https://github.com/airbytehq/airbyte/pull/71927) | Update dependencies | From 733a3bdcb70dfc1a1b776aee31aaf936288259b9 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:55:36 +0000 Subject: [PATCH 078/379] =?UTF-8?q?deps(source-invoiced):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75658)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-invoiced/metadata.yaml | 4 ++-- docs/integrations/sources/invoiced.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-invoiced/metadata.yaml b/airbyte-integrations/connectors/source-invoiced/metadata.yaml index fcfeb450bd72..cb2cd429b128 100644 --- a/airbyte-integrations/connectors/source-invoiced/metadata.yaml +++ b/airbyte-integrations/connectors/source-invoiced/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-invoiced connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 5f43588b-998b-4398-bb15-fb6eb4fc015e - dockerImageTag: 0.0.51 + dockerImageTag: 0.0.52 dockerRepository: airbyte/source-invoiced githubIssueLabel: source-invoiced icon: icon.svg diff --git a/docs/integrations/sources/invoiced.md b/docs/integrations/sources/invoiced.md index 4f54bc2ca445..eabd37cb961d 100644 --- a/docs/integrations/sources/invoiced.md +++ b/docs/integrations/sources/invoiced.md @@ -35,6 +35,7 @@ This Airbyte connector for **Invoiced** enables seamless data integration betwee | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.52 | 2026-03-31 | [75658](https://github.com/airbytehq/airbyte/pull/75658) | Update dependencies | | 0.0.51 | 2026-03-17 | [75056](https://github.com/airbytehq/airbyte/pull/75056) | Update dependencies | | 0.0.50 | 2026-03-10 | [74505](https://github.com/airbytehq/airbyte/pull/74505) | Update dependencies | | 0.0.49 | 2026-03-03 | [74174](https://github.com/airbytehq/airbyte/pull/74174) | Update dependencies | From ae7bd1a800c9477307bbc011c228af8bed21699b Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:55:40 +0000 Subject: [PATCH 079/379] =?UTF-8?q?deps(source-calendly):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75659)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-calendly/metadata.yaml | 4 ++-- docs/integrations/sources/calendly.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-calendly/metadata.yaml b/airbyte-integrations/connectors/source-calendly/metadata.yaml index 51302fd843d7..7cbec64d9d44 100644 --- a/airbyte-integrations/connectors/source-calendly/metadata.yaml +++ b/airbyte-integrations/connectors/source-calendly/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-calendly connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: b8f2cbee-b073-4dd8-9b80-97d7bae967a4 - dockerImageTag: 0.1.35 + dockerImageTag: 0.1.36 dockerRepository: airbyte/source-calendly githubIssueLabel: source-calendly icon: icon.svg diff --git a/docs/integrations/sources/calendly.md b/docs/integrations/sources/calendly.md index 77d7df33b29c..3c290ddc5f67 100644 --- a/docs/integrations/sources/calendly.md +++ b/docs/integrations/sources/calendly.md @@ -32,6 +32,7 @@ Incremental sync in `scheduled_events` uses `start_time` as a cursor. This may l | Version | Date | Pull Request | Subject | | ------- | ---------- | -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 0.1.36 | 2026-03-31 | [75659](https://github.com/airbytehq/airbyte/pull/75659) | Update dependencies | | 0.1.35 | 2026-03-17 | [74912](https://github.com/airbytehq/airbyte/pull/74912) | Update dependencies | | 0.1.34 | 2026-03-10 | [74632](https://github.com/airbytehq/airbyte/pull/74632) | Update dependencies | | 0.1.33 | 2026-03-03 | [73791](https://github.com/airbytehq/airbyte/pull/73791) | Update dependencies | From f7e05367178d4c01a0899f1bfe1d290de0c4dd82 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:55:45 +0000 Subject: [PATCH 080/379] =?UTF-8?q?deps(source-hugging-face-datasets):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75656)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-hugging-face-datasets/metadata.yaml | 4 ++-- docs/integrations/sources/hugging-face-datasets.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-hugging-face-datasets/metadata.yaml b/airbyte-integrations/connectors/source-hugging-face-datasets/metadata.yaml index 5ae8eb2c3793..4e2299b46de2 100644 --- a/airbyte-integrations/connectors/source-hugging-face-datasets/metadata.yaml +++ b/airbyte-integrations/connectors/source-hugging-face-datasets/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-hugging-face-datasets connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 38438040-03d9-406d-b10b-af83beadd3ef - dockerImageTag: 0.0.46 + dockerImageTag: 0.0.47 dockerRepository: airbyte/source-hugging-face-datasets githubIssueLabel: source-hugging-face-datasets icon: icon.svg diff --git a/docs/integrations/sources/hugging-face-datasets.md b/docs/integrations/sources/hugging-face-datasets.md index 0682e142d301..faf5d9f0840b 100644 --- a/docs/integrations/sources/hugging-face-datasets.md +++ b/docs/integrations/sources/hugging-face-datasets.md @@ -23,6 +23,7 @@ Only datasets with [Parquet exports](https://huggingface.co/docs/dataset-viewer/ | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.47 | 2026-03-31 | [75656](https://github.com/airbytehq/airbyte/pull/75656) | Update dependencies | | 0.0.46 | 2026-03-17 | [74523](https://github.com/airbytehq/airbyte/pull/74523) | Update dependencies | | 0.0.45 | 2026-03-03 | [73521](https://github.com/airbytehq/airbyte/pull/73521) | Update dependencies | | 0.0.44 | 2026-02-10 | [73049](https://github.com/airbytehq/airbyte/pull/73049) | Update dependencies | From fc13aa55bbdad6309d8d088030baf310e22854eb Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:55:50 +0000 Subject: [PATCH 081/379] =?UTF-8?q?deps(source-illumina-basespace):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75655)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-illumina-basespace/metadata.yaml | 4 ++-- docs/integrations/sources/illumina-basespace.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-illumina-basespace/metadata.yaml b/airbyte-integrations/connectors/source-illumina-basespace/metadata.yaml index 7ae626eed1e7..a68fcf104241 100644 --- a/airbyte-integrations/connectors/source-illumina-basespace/metadata.yaml +++ b/airbyte-integrations/connectors/source-illumina-basespace/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-illumina-basespace connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 62e9c4f2-a768-48f7-a8bf-d54bf1d96425 - dockerImageTag: 0.0.50 + dockerImageTag: 0.0.51 dockerRepository: airbyte/source-illumina-basespace githubIssueLabel: source-illumina-basespace icon: icon.svg diff --git a/docs/integrations/sources/illumina-basespace.md b/docs/integrations/sources/illumina-basespace.md index 50f40e19f00d..16f2b4bc5e27 100644 --- a/docs/integrations/sources/illumina-basespace.md +++ b/docs/integrations/sources/illumina-basespace.md @@ -28,6 +28,7 @@ Connector for the Basespace v1 API. This can be used to extract data on projects | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.51 | 2026-03-31 | [75655](https://github.com/airbytehq/airbyte/pull/75655) | Update dependencies | | 0.0.50 | 2026-03-17 | [75083](https://github.com/airbytehq/airbyte/pull/75083) | Update dependencies | | 0.0.49 | 2026-02-24 | [73895](https://github.com/airbytehq/airbyte/pull/73895) | Update dependencies | | 0.0.48 | 2026-02-17 | [73489](https://github.com/airbytehq/airbyte/pull/73489) | Update dependencies | From c152f1efe6e75b6e067f11c24e90e23b4775cd00 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:55:54 +0000 Subject: [PATCH 082/379] =?UTF-8?q?deps(source-boldsign):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75654)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-boldsign/metadata.yaml | 4 ++-- docs/integrations/sources/boldsign.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-boldsign/metadata.yaml b/airbyte-integrations/connectors/source-boldsign/metadata.yaml index f0c968363e3a..bf3d9d6a6d30 100644 --- a/airbyte-integrations/connectors/source-boldsign/metadata.yaml +++ b/airbyte-integrations/connectors/source-boldsign/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-boldsign connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: b013676a-2286-4f7a-bca4-811477207761 - dockerImageTag: 0.0.24 + dockerImageTag: 0.0.25 dockerRepository: airbyte/source-boldsign githubIssueLabel: source-boldsign icon: icon.svg diff --git a/docs/integrations/sources/boldsign.md b/docs/integrations/sources/boldsign.md index a266cb38a4df..dffd22e4839c 100644 --- a/docs/integrations/sources/boldsign.md +++ b/docs/integrations/sources/boldsign.md @@ -28,6 +28,7 @@ API Reference: https://developers.boldsign.com/api-overview/getting-started/?reg | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.25 | 2026-03-31 | [75654](https://github.com/airbytehq/airbyte/pull/75654) | Update dependencies | | 0.0.24 | 2026-03-17 | [74917](https://github.com/airbytehq/airbyte/pull/74917) | Update dependencies | | 0.0.23 | 2026-02-24 | [73790](https://github.com/airbytehq/airbyte/pull/73790) | Update dependencies | | 0.0.22 | 2026-02-03 | [72062](https://github.com/airbytehq/airbyte/pull/72062) | Update dependencies | From 83afe056e396a7ca8409a65ef2095993a78437a5 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:56:00 +0000 Subject: [PATCH 083/379] =?UTF-8?q?deps(source-humanitix):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75653)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-humanitix/metadata.yaml | 4 ++-- docs/integrations/sources/humanitix.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-humanitix/metadata.yaml b/airbyte-integrations/connectors/source-humanitix/metadata.yaml index 7fff95656b2c..2538fa1ebf16 100644 --- a/airbyte-integrations/connectors/source-humanitix/metadata.yaml +++ b/airbyte-integrations/connectors/source-humanitix/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-humanitix connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 89f37cda-8b7d-4179-ad8a-91cf5045b5fd - dockerImageTag: 0.0.45 + dockerImageTag: 0.0.46 dockerRepository: airbyte/source-humanitix githubIssueLabel: source-humanitix icon: icon.svg diff --git a/docs/integrations/sources/humanitix.md b/docs/integrations/sources/humanitix.md index c26fa2709254..872f7359f7c9 100644 --- a/docs/integrations/sources/humanitix.md +++ b/docs/integrations/sources/humanitix.md @@ -24,6 +24,7 @@ Docs : https://humanitix.stoplight.io/docs/humanitix-public-api/e508a657c1467-hu | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.46 | 2026-03-31 | [75653](https://github.com/airbytehq/airbyte/pull/75653) | Update dependencies | | 0.0.45 | 2026-03-17 | [74522](https://github.com/airbytehq/airbyte/pull/74522) | Update dependencies | | 0.0.44 | 2026-02-24 | [73090](https://github.com/airbytehq/airbyte/pull/73090) | Update dependencies | | 0.0.43 | 2026-02-03 | [72752](https://github.com/airbytehq/airbyte/pull/72752) | Update dependencies | From 74485635d33440a97f75df7c5b48156e413e5be9 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:56:05 +0000 Subject: [PATCH 084/379] =?UTF-8?q?deps(source-openaq):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75652)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-openaq/metadata.yaml | 4 ++-- docs/integrations/sources/openaq.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-openaq/metadata.yaml b/airbyte-integrations/connectors/source-openaq/metadata.yaml index c97d03c1cb71..1a95b63c99b6 100644 --- a/airbyte-integrations/connectors/source-openaq/metadata.yaml +++ b/airbyte-integrations/connectors/source-openaq/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-openaq connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 5b7216ca-1d6d-4a50-89c3-067746806586 - dockerImageTag: 0.0.50 + dockerImageTag: 0.0.51 dockerRepository: airbyte/source-openaq githubIssueLabel: source-openaq icon: icon.svg diff --git a/docs/integrations/sources/openaq.md b/docs/integrations/sources/openaq.md index e1c5dda64563..85159feb7d3f 100644 --- a/docs/integrations/sources/openaq.md +++ b/docs/integrations/sources/openaq.md @@ -38,6 +38,7 @@ Docs : https://docs.openaq.org/using-the-api/quick-start | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.51 | 2026-03-31 | [75652](https://github.com/airbytehq/airbyte/pull/75652) | Update dependencies | | 0.0.50 | 2026-03-17 | [74983](https://github.com/airbytehq/airbyte/pull/74983) | Update dependencies | | 0.0.49 | 2026-03-10 | [74664](https://github.com/airbytehq/airbyte/pull/74664) | Update dependencies | | 0.0.48 | 2026-03-03 | [74221](https://github.com/airbytehq/airbyte/pull/74221) | Update dependencies | From 4e2d7c5dce9471a87b698d5ed3ea11899a10e7f2 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:56:10 +0000 Subject: [PATCH 085/379] =?UTF-8?q?deps(source-brex):=20=F0=9F=90=99=20upd?= =?UTF-8?q?ate=20dependencies=20[2026-03-31]=20(#75651)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-brex/metadata.yaml | 4 ++-- docs/integrations/sources/brex.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-brex/metadata.yaml b/airbyte-integrations/connectors/source-brex/metadata.yaml index 45fe2d98fd9c..f53a4824f79f 100644 --- a/airbyte-integrations/connectors/source-brex/metadata.yaml +++ b/airbyte-integrations/connectors/source-brex/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-brex connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 7d605ca7-f2b8-41c4-96a7-3d5637e58d6d - dockerImageTag: 0.0.40 + dockerImageTag: 0.0.41 dockerRepository: airbyte/source-brex githubIssueLabel: source-brex icon: icon.svg diff --git a/docs/integrations/sources/brex.md b/docs/integrations/sources/brex.md index 75e0e8877153..aef1d460c42a 100644 --- a/docs/integrations/sources/brex.md +++ b/docs/integrations/sources/brex.md @@ -25,6 +25,7 @@ Fetches data on users, expenses, transactions, vendors, and budgets from Brex AP | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.41 | 2026-03-31 | [75651](https://github.com/airbytehq/airbyte/pull/75651) | Update dependencies | | 0.0.40 | 2026-03-24 | [74944](https://github.com/airbytehq/airbyte/pull/74944) | Update dependencies | | 0.0.39 | 2026-03-10 | [74609](https://github.com/airbytehq/airbyte/pull/74609) | Update dependencies | | 0.0.38 | 2026-03-03 | [74202](https://github.com/airbytehq/airbyte/pull/74202) | Update dependencies | From 66fa87c53c72f36a82b2e8035076cd5ccc7292a0 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:56:14 +0000 Subject: [PATCH 086/379] =?UTF-8?q?deps(source-judge-me-reviews):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75650)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-judge-me-reviews/metadata.yaml | 4 ++-- docs/integrations/sources/judge-me-reviews.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-judge-me-reviews/metadata.yaml b/airbyte-integrations/connectors/source-judge-me-reviews/metadata.yaml index bd03cb6969a3..ed2329c7b166 100644 --- a/airbyte-integrations/connectors/source-judge-me-reviews/metadata.yaml +++ b/airbyte-integrations/connectors/source-judge-me-reviews/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-judge-me-reviews connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: a9184721-17d5-40c0-894d-f49b86749465 - dockerImageTag: 0.0.23 + dockerImageTag: 0.0.24 dockerRepository: airbyte/source-judge-me-reviews githubIssueLabel: source-judge-me-reviews icon: icon.svg diff --git a/docs/integrations/sources/judge-me-reviews.md b/docs/integrations/sources/judge-me-reviews.md index 5b3bf9b0b201..b72add1e8677 100644 --- a/docs/integrations/sources/judge-me-reviews.md +++ b/docs/integrations/sources/judge-me-reviews.md @@ -22,6 +22,7 @@ API: https://judge.me/api/docs#tag/Reviews/operation/reviews#index | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.24 | 2026-03-31 | [75650](https://github.com/airbytehq/airbyte/pull/75650) | Update dependencies | | 0.0.23 | 2026-03-17 | [75059](https://github.com/airbytehq/airbyte/pull/75059) | Update dependencies | | 0.0.22 | 2026-03-10 | [74527](https://github.com/airbytehq/airbyte/pull/74527) | Update dependencies | | 0.0.21 | 2026-02-24 | [73922](https://github.com/airbytehq/airbyte/pull/73922) | Update dependencies | From 13ef4615731453451690afb8c827170197a57ded Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:56:19 +0000 Subject: [PATCH 087/379] =?UTF-8?q?deps(source-opinion-stage):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75649)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-opinion-stage/metadata.yaml | 4 ++-- docs/integrations/sources/opinion-stage.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-opinion-stage/metadata.yaml b/airbyte-integrations/connectors/source-opinion-stage/metadata.yaml index fc74498f4785..1f80bc7118e8 100644 --- a/airbyte-integrations/connectors/source-opinion-stage/metadata.yaml +++ b/airbyte-integrations/connectors/source-opinion-stage/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-opinion-stage connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 2718eb27-a931-450d-91b2-8bc084f341e7 - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-opinion-stage githubIssueLabel: source-opinion-stage icon: icon.svg diff --git a/docs/integrations/sources/opinion-stage.md b/docs/integrations/sources/opinion-stage.md index 7185f9172770..d44a66b804be 100644 --- a/docs/integrations/sources/opinion-stage.md +++ b/docs/integrations/sources/opinion-stage.md @@ -21,6 +21,7 @@ The Airbyte connector for [OpinionStage](https://opinionstage.com) enables seaml | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.49 | 2026-03-31 | [75649](https://github.com/airbytehq/airbyte/pull/75649) | Update dependencies | | 0.0.48 | 2026-03-17 | [74959](https://github.com/airbytehq/airbyte/pull/74959) | Update dependencies | | 0.0.47 | 2026-03-10 | [74655](https://github.com/airbytehq/airbyte/pull/74655) | Update dependencies | | 0.0.46 | 2026-02-24 | [73812](https://github.com/airbytehq/airbyte/pull/73812) | Update dependencies | From 19e39ed9b5b01f168e6b70415f50035f94505c88 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 04:56:25 +0000 Subject: [PATCH 088/379] =?UTF-8?q?deps(source-onesignal):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75648)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-onesignal/metadata.yaml | 4 ++-- docs/integrations/sources/onesignal.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-onesignal/metadata.yaml b/airbyte-integrations/connectors/source-onesignal/metadata.yaml index 246c384855e2..c8eeb9507608 100644 --- a/airbyte-integrations/connectors/source-onesignal/metadata.yaml +++ b/airbyte-integrations/connectors/source-onesignal/metadata.yaml @@ -3,7 +3,7 @@ data: hosts: - onesignal.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorTestSuitesOptions: - suite: liveTests @@ -19,7 +19,7 @@ data: type: GSM connectorType: source definitionId: bb6afd81-87d5-47e3-97c4-e2c2901b1cf8 - dockerImageTag: 1.2.50 + dockerImageTag: 1.2.51 dockerRepository: airbyte/source-onesignal documentationUrl: https://docs.airbyte.com/integrations/sources/onesignal githubIssueLabel: source-onesignal diff --git a/docs/integrations/sources/onesignal.md b/docs/integrations/sources/onesignal.md index 9aea4e080d98..88e2a020ffe5 100644 --- a/docs/integrations/sources/onesignal.md +++ b/docs/integrations/sources/onesignal.md @@ -78,6 +78,7 @@ The connector is restricted by normal OneSignal [rate limits](https://documentat | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------- | +| 1.2.51 | 2026-03-31 | [75648](https://github.com/airbytehq/airbyte/pull/75648) | Update dependencies | | 1.2.50 | 2026-03-24 | [74991](https://github.com/airbytehq/airbyte/pull/74991) | Update dependencies | | 1.2.49 | 2026-03-10 | [74661](https://github.com/airbytehq/airbyte/pull/74661) | Update dependencies | | 1.2.48 | 2026-02-24 | [73815](https://github.com/airbytehq/airbyte/pull/73815) | Update dependencies | From d28571f5567acfa5d674b2af68571d3ed5962e6a Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Mon, 30 Mar 2026 22:43:37 -0700 Subject: [PATCH 089/379] chore: bump source-faker to 7.0.4 (test ops CLI publish with deps + SBOM) (#75657) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-faker/metadata.yaml | 2 +- airbyte-integrations/connectors/source-faker/pyproject.toml | 2 +- docs/integrations/sources/faker.md | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-faker/metadata.yaml b/airbyte-integrations/connectors/source-faker/metadata.yaml index 43ca6ba130c7..dd022bc3917d 100644 --- a/airbyte-integrations/connectors/source-faker/metadata.yaml +++ b/airbyte-integrations/connectors/source-faker/metadata.yaml @@ -9,7 +9,7 @@ data: connectorSubtype: api connectorType: source definitionId: dfd88b22-b603-4c3d-aad7-3701784586b1 - dockerImageTag: 7.0.3 + dockerImageTag: 7.0.4 dockerRepository: airbyte/source-faker documentationUrl: https://docs.airbyte.com/integrations/sources/faker externalDocumentationUrls: diff --git a/airbyte-integrations/connectors/source-faker/pyproject.toml b/airbyte-integrations/connectors/source-faker/pyproject.toml index b3d8288ccf40..62dd1ea81e9e 100644 --- a/airbyte-integrations/connectors/source-faker/pyproject.toml +++ b/airbyte-integrations/connectors/source-faker/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "7.0.3" +version = "7.0.4" name = "source-faker" description = "Source implementation for fake but realistic looking data." authors = [ "Airbyte ",] diff --git a/docs/integrations/sources/faker.md b/docs/integrations/sources/faker.md index 6678622dfabf..20508eb6b3d0 100644 --- a/docs/integrations/sources/faker.md +++ b/docs/integrations/sources/faker.md @@ -47,6 +47,7 @@ Each purchase record includes: `id`, `user_id`, `product_id`, `created_at`, `upd | Version | Date | Pull Request | Subject | |:------------|:-----------| :-------------------------------------------------------------------------------------------------------------------- |:----------------------------------------------------------------------------------------------------------------| +| 7.0.4 | 2026-03-31 | [75646](https://github.com/airbytehq/airbyte/pull/75646) | Patch version bump (test publish) | | 7.0.3 | 2026-03-20 | [75256](https://github.com/airbytehq/airbyte/pull/75256) | Re-release to verify yank/un-yank behavior in ops CLI registry pipeline | | 7.0.2 | 2026-03-19 | [75232](https://github.com/airbytehq/airbyte/pull/75232) | Patch version bump (ops CLI registry post-launch test) | | 7.0.1 | 2026-03-13 | [74818](https://github.com/airbytehq/airbyte/pull/74818) | Patch version bump (publish test) | From 7e79a59bf22dc5864d35b2a65d8e236eb12b0b6d Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:35:49 +0000 Subject: [PATCH 090/379] =?UTF-8?q?deps(source-finnworlds):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75758)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-finnworlds/metadata.yaml | 4 ++-- docs/integrations/sources/finnworlds.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-finnworlds/metadata.yaml b/airbyte-integrations/connectors/source-finnworlds/metadata.yaml index 90928333012b..6972a131aa79 100644 --- a/airbyte-integrations/connectors/source-finnworlds/metadata.yaml +++ b/airbyte-integrations/connectors/source-finnworlds/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-finnworlds connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: b8a9a60f-7178-468a-a333-23b431e355b7 - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-finnworlds githubIssueLabel: source-finnworlds icon: icon.svg diff --git a/docs/integrations/sources/finnworlds.md b/docs/integrations/sources/finnworlds.md index 03294042aacb..8395f54eb001 100644 --- a/docs/integrations/sources/finnworlds.md +++ b/docs/integrations/sources/finnworlds.md @@ -33,6 +33,7 @@ Docs : https://finnworlds.com/ | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.48 | 2026-03-31 | [75758](https://github.com/airbytehq/airbyte/pull/75758) | Update dependencies | | 0.0.47 | 2026-03-17 | [74684](https://github.com/airbytehq/airbyte/pull/74684) | Update dependencies | | 0.0.46 | 2026-02-24 | [73779](https://github.com/airbytehq/airbyte/pull/73779) | Update dependencies | | 0.0.45 | 2026-02-17 | [73409](https://github.com/airbytehq/airbyte/pull/73409) | Update dependencies | From 89bfec4f7c56c4858f313bf304ac461658ebdb9c Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:35:54 +0000 Subject: [PATCH 091/379] =?UTF-8?q?deps(source-fillout):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75756)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-fillout/metadata.yaml | 4 ++-- docs/integrations/sources/fillout.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-fillout/metadata.yaml b/airbyte-integrations/connectors/source-fillout/metadata.yaml index 6b5adcda05bc..28acf8051ced 100644 --- a/airbyte-integrations/connectors/source-fillout/metadata.yaml +++ b/airbyte-integrations/connectors/source-fillout/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-fillout connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: fae4092b-fcb4-4dba-8ad4-f8bf9a32d25e - dockerImageTag: 0.2.44 + dockerImageTag: 0.2.45 dockerRepository: airbyte/source-fillout githubIssueLabel: source-fillout icon: icon.svg diff --git a/docs/integrations/sources/fillout.md b/docs/integrations/sources/fillout.md index 4996cf5d12d4..9f810dcaa184 100644 --- a/docs/integrations/sources/fillout.md +++ b/docs/integrations/sources/fillout.md @@ -24,6 +24,7 @@ The Airbyte connector for Fillout.com enables seamless data synchronization betw | Version | Date | Pull Request | Subject | | ------- | ---------- | ------------ | ----------------------------------------------------------------------------------- | +| 0.2.45 | 2026-03-31 | [75756](https://github.com/airbytehq/airbyte/pull/75756) | Update dependencies | | 0.2.44 | 2026-03-17 | [74686](https://github.com/airbytehq/airbyte/pull/74686) | Update dependencies | | 0.2.43 | 2026-02-24 | [73766](https://github.com/airbytehq/airbyte/pull/73766) | Update dependencies | | 0.2.42 | 2026-01-20 | [71956](https://github.com/airbytehq/airbyte/pull/71956) | Update dependencies | From d776904a95aa6934e6b6033e8f5ba24d0951c839 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:36:02 +0000 Subject: [PATCH 092/379] =?UTF-8?q?deps(source-clockodo):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75751)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-clockodo/metadata.yaml | 4 ++-- docs/integrations/sources/clockodo.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-clockodo/metadata.yaml b/airbyte-integrations/connectors/source-clockodo/metadata.yaml index 96c6c5e1bc9e..53a6b426246d 100644 --- a/airbyte-integrations/connectors/source-clockodo/metadata.yaml +++ b/airbyte-integrations/connectors/source-clockodo/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-clockodo connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 9cddb136-acda-4755-9200-9014944650fc - dockerImageTag: 0.0.49 + dockerImageTag: 0.0.50 dockerRepository: airbyte/source-clockodo githubIssueLabel: source-clockodo icon: icon.svg diff --git a/docs/integrations/sources/clockodo.md b/docs/integrations/sources/clockodo.md index 90e67c84972d..8f4cf3ca8dba 100644 --- a/docs/integrations/sources/clockodo.md +++ b/docs/integrations/sources/clockodo.md @@ -40,6 +40,7 @@ The Airbyte connector for Clockodo enables seamless data integration between Clo | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.50 | 2026-03-31 | [75751](https://github.com/airbytehq/airbyte/pull/75751) | Update dependencies | | 0.0.49 | 2026-03-17 | [75067](https://github.com/airbytehq/airbyte/pull/75067) | Update dependencies | | 0.0.48 | 2026-03-10 | [74418](https://github.com/airbytehq/airbyte/pull/74418) | Update dependencies | | 0.0.47 | 2026-02-24 | [73806](https://github.com/airbytehq/airbyte/pull/73806) | Update dependencies | From 5d86ad89130a22a6448f2cf4a2d1d5cb50cf60e2 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:36:09 +0000 Subject: [PATCH 093/379] =?UTF-8?q?deps(source-tempo):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75748)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-tempo/metadata.yaml | 4 ++-- docs/integrations/sources/tempo.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-tempo/metadata.yaml b/airbyte-integrations/connectors/source-tempo/metadata.yaml index c5a2dc2377ef..da1a9f964765 100644 --- a/airbyte-integrations/connectors/source-tempo/metadata.yaml +++ b/airbyte-integrations/connectors/source-tempo/metadata.yaml @@ -8,7 +8,7 @@ data: connectorSubtype: api connectorType: source definitionId: d1aa448b-7c54-498e-ad95-263cbebcd2db - dockerImageTag: 0.4.45 + dockerImageTag: 0.4.46 dockerRepository: airbyte/source-tempo documentationUrl: https://docs.airbyte.com/integrations/sources/tempo githubIssueLabel: source-tempo @@ -50,7 +50,7 @@ data: type: GSM alias: airbyte-connector-testing-secret-store connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e externalDocumentationUrls: - title: Tempo Timesheets API url: https://apidocs.tempo.io/ diff --git a/docs/integrations/sources/tempo.md b/docs/integrations/sources/tempo.md index 088e61becbf6..1d61db580294 100644 --- a/docs/integrations/sources/tempo.md +++ b/docs/integrations/sources/tempo.md @@ -49,6 +49,7 @@ If there are more endpoints you'd like Airbyte to support, please [create an iss | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :-------------------------------------------------------- | +| 0.4.46 | 2026-03-31 | [75748](https://github.com/airbytehq/airbyte/pull/75748) | Update dependencies | | 0.4.45 | 2026-03-17 | [74548](https://github.com/airbytehq/airbyte/pull/74548) | Update dependencies | | 0.4.44 | 2026-02-24 | [73838](https://github.com/airbytehq/airbyte/pull/73838) | Update dependencies | | 0.4.43 | 2026-02-17 | [72769](https://github.com/airbytehq/airbyte/pull/72769) | Update dependencies | From 66d540e68ee0aa7d6854c7e7e76f7ec5b0b94478 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:36:17 +0000 Subject: [PATCH 094/379] =?UTF-8?q?deps(source-taboola):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75745)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-taboola/metadata.yaml | 4 ++-- docs/integrations/sources/taboola.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-taboola/metadata.yaml b/airbyte-integrations/connectors/source-taboola/metadata.yaml index f5029937485c..f49b3368482a 100644 --- a/airbyte-integrations/connectors/source-taboola/metadata.yaml +++ b/airbyte-integrations/connectors/source-taboola/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-taboola connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 40bb20de-e03c-4aa2-80bc-72234598380f - dockerImageTag: 0.0.44 + dockerImageTag: 0.0.45 dockerRepository: airbyte/source-taboola githubIssueLabel: source-taboola icon: icon.svg diff --git a/docs/integrations/sources/taboola.md b/docs/integrations/sources/taboola.md index 5f3c3dc11e16..e98f0746b589 100644 --- a/docs/integrations/sources/taboola.md +++ b/docs/integrations/sources/taboola.md @@ -33,6 +33,7 @@ You can learn more about the API here https://developers.taboola.com/backstage-a | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.45 | 2026-03-31 | [75745](https://github.com/airbytehq/airbyte/pull/75745) | Update dependencies | | 0.0.44 | 2026-03-17 | [75085](https://github.com/airbytehq/airbyte/pull/75085) | Update dependencies | | 0.0.43 | 2026-03-10 | [74589](https://github.com/airbytehq/airbyte/pull/74589) | Update dependencies | | 0.0.42 | 2026-03-03 | [74223](https://github.com/airbytehq/airbyte/pull/74223) | Update dependencies | From a8bb6979b5e7e97c336b4493ed73d83b53e646cf Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:36:21 +0000 Subject: [PATCH 095/379] =?UTF-8?q?deps(source-cin7):=20=F0=9F=90=99=20upd?= =?UTF-8?q?ate=20dependencies=20[2026-03-31]=20(#75744)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-cin7/metadata.yaml | 4 ++-- docs/integrations/sources/cin7.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-cin7/metadata.yaml b/airbyte-integrations/connectors/source-cin7/metadata.yaml index 10bfd5a027fa..cd3629467562 100644 --- a/airbyte-integrations/connectors/source-cin7/metadata.yaml +++ b/airbyte-integrations/connectors/source-cin7/metadata.yaml @@ -13,7 +13,7 @@ data: enabled: false packageName: airbyte-source-cin7 connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorTestSuitesOptions: - suite: acceptanceTests testSecrets: @@ -25,7 +25,7 @@ data: connectorSubtype: api connectorType: source definitionId: ff48bf15-f917-4fff-ba28-cbab56ef892f - dockerImageTag: 0.3.30 + dockerImageTag: 0.3.31 dockerRepository: airbyte/source-cin7 githubIssueLabel: source-cin7 icon: icon.svg diff --git a/docs/integrations/sources/cin7.md b/docs/integrations/sources/cin7.md index a9ac188a7fe8..1541e574ada5 100644 --- a/docs/integrations/sources/cin7.md +++ b/docs/integrations/sources/cin7.md @@ -39,6 +39,7 @@ Create an application and note down the Account Id and the API key, you will nee | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.3.31 | 2026-03-31 | [75744](https://github.com/airbytehq/airbyte/pull/75744) | Update dependencies | | 0.3.30 | 2026-03-17 | [75102](https://github.com/airbytehq/airbyte/pull/75102) | Update dependencies | | 0.3.29 | 2026-02-24 | [73826](https://github.com/airbytehq/airbyte/pull/73826) | Update dependencies | | 0.3.28 | 2026-02-17 | [73024](https://github.com/airbytehq/airbyte/pull/73024) | Update dependencies | From 4145732b3a1afd4a6afb9e0d7591a5038c5a5c50 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:36:26 +0000 Subject: [PATCH 096/379] =?UTF-8?q?deps(source-testrail):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75743)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-testrail/metadata.yaml | 4 ++-- docs/integrations/sources/testrail.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-testrail/metadata.yaml b/airbyte-integrations/connectors/source-testrail/metadata.yaml index 2cc5e762580b..aaa1c73dab74 100644 --- a/airbyte-integrations/connectors/source-testrail/metadata.yaml +++ b/airbyte-integrations/connectors/source-testrail/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-testrail connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: ab49ae02-a22d-4c9a-b0be-f260e61a4011 - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-testrail githubIssueLabel: source-testrail icon: icon.svg diff --git a/docs/integrations/sources/testrail.md b/docs/integrations/sources/testrail.md index 81cfa05d27a4..0dd9f335b569 100644 --- a/docs/integrations/sources/testrail.md +++ b/docs/integrations/sources/testrail.md @@ -45,6 +45,7 @@ Visit `https://support.testrail.com/hc/en-us/articles/7077196481428-Attachments` | Version | Date | Pull Request | Subject | | ------------------ | ------------ | -- | ---------------- | +| 0.0.49 | 2026-03-31 | [75743](https://github.com/airbytehq/airbyte/pull/75743) | Update dependencies | | 0.0.48 | 2026-03-17 | [75064](https://github.com/airbytehq/airbyte/pull/75064) | Update dependencies | | 0.0.47 | 2026-03-10 | [74585](https://github.com/airbytehq/airbyte/pull/74585) | Update dependencies | | 0.0.46 | 2026-02-24 | [73880](https://github.com/airbytehq/airbyte/pull/73880) | Update dependencies | From fbbe05322b3d64f832e2b0a16c2b58f5160d88f3 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:36:32 +0000 Subject: [PATCH 097/379] =?UTF-8?q?deps(source-ninjaone-rmm):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75742)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-ninjaone-rmm/metadata.yaml | 4 ++-- docs/integrations/sources/ninjaone-rmm.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-ninjaone-rmm/metadata.yaml b/airbyte-integrations/connectors/source-ninjaone-rmm/metadata.yaml index b3aa5550bc58..549b5ef190d1 100644 --- a/airbyte-integrations/connectors/source-ninjaone-rmm/metadata.yaml +++ b/airbyte-integrations/connectors/source-ninjaone-rmm/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-ninjaone-rmm connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 49897212-53be-4898-ba2e-b73e72d645ef - dockerImageTag: 0.0.32 + dockerImageTag: 0.0.33 dockerRepository: airbyte/source-ninjaone-rmm githubIssueLabel: source-ninjaone-rmm icon: icon.svg diff --git a/docs/integrations/sources/ninjaone-rmm.md b/docs/integrations/sources/ninjaone-rmm.md index a6711ce45ff7..d1fb6219bcf2 100644 --- a/docs/integrations/sources/ninjaone-rmm.md +++ b/docs/integrations/sources/ninjaone-rmm.md @@ -28,6 +28,7 @@ API Reference: https://app.ninjarmm.com/apidocs/?links.active=core | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.33 | 2026-03-31 | [75742](https://github.com/airbytehq/airbyte/pull/75742) | Update dependencies | | 0.0.32 | 2026-03-17 | [75066](https://github.com/airbytehq/airbyte/pull/75066) | Update dependencies | | 0.0.31 | 2026-03-10 | [74596](https://github.com/airbytehq/airbyte/pull/74596) | Update dependencies | | 0.0.30 | 2026-02-24 | [73833](https://github.com/airbytehq/airbyte/pull/73833) | Update dependencies | From 5aeeb299cffe4a879483f1a5ebc3dfcf1dec7289 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:36:39 +0000 Subject: [PATCH 098/379] =?UTF-8?q?deps(source-tremendous):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75741)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-tremendous/metadata.yaml | 4 ++-- docs/integrations/sources/tremendous.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-tremendous/metadata.yaml b/airbyte-integrations/connectors/source-tremendous/metadata.yaml index 24ca6f90fb0b..8e9644a29579 100644 --- a/airbyte-integrations/connectors/source-tremendous/metadata.yaml +++ b/airbyte-integrations/connectors/source-tremendous/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-tremendous connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 6a91b109-0286-40a0-801b-ac86933a44d4 - dockerImageTag: 0.0.49 + dockerImageTag: 0.0.50 dockerRepository: airbyte/source-tremendous githubIssueLabel: source-tremendous icon: icon.svg diff --git a/docs/integrations/sources/tremendous.md b/docs/integrations/sources/tremendous.md index 28bdbb5fe4e6..204f60f64e95 100644 --- a/docs/integrations/sources/tremendous.md +++ b/docs/integrations/sources/tremendous.md @@ -29,6 +29,7 @@ Tremendous connector enables seamless integration with Tremendous API. This con | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.50 | 2026-03-31 | [75741](https://github.com/airbytehq/airbyte/pull/75741) | Update dependencies | | 0.0.49 | 2026-03-17 | [74547](https://github.com/airbytehq/airbyte/pull/74547) | Update dependencies | | 0.0.48 | 2026-03-03 | [73879](https://github.com/airbytehq/airbyte/pull/73879) | Update dependencies | | 0.0.47 | 2026-02-17 | [73533](https://github.com/airbytehq/airbyte/pull/73533) | Update dependencies | From a356d0defc93333589a5b8deb5f984749545051e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:36:45 +0000 Subject: [PATCH 099/379] =?UTF-8?q?deps(source-churnkey):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75740)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-churnkey/metadata.yaml | 4 ++-- docs/integrations/sources/churnkey.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-churnkey/metadata.yaml b/airbyte-integrations/connectors/source-churnkey/metadata.yaml index 391bf139216f..34184854180b 100644 --- a/airbyte-integrations/connectors/source-churnkey/metadata.yaml +++ b/airbyte-integrations/connectors/source-churnkey/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-churnkey connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 0f1a0659-0239-48a7-bf34-072a5bf2713a - dockerImageTag: 0.0.24 + dockerImageTag: 0.0.25 dockerRepository: airbyte/source-churnkey githubIssueLabel: source-churnkey icon: icon.svg diff --git a/docs/integrations/sources/churnkey.md b/docs/integrations/sources/churnkey.md index 18910ad4b738..50dec8d26a9b 100644 --- a/docs/integrations/sources/churnkey.md +++ b/docs/integrations/sources/churnkey.md @@ -21,6 +21,7 @@ connects to churnkey to retrieve session details | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.25 | 2026-03-31 | [75740](https://github.com/airbytehq/airbyte/pull/75740) | Update dependencies | | 0.0.24 | 2026-03-24 | [75397](https://github.com/airbytehq/airbyte/pull/75397) | Update dependencies | | 0.0.23 | 2026-03-10 | [74420](https://github.com/airbytehq/airbyte/pull/74420) | Update dependencies | | 0.0.22 | 2026-02-24 | [73801](https://github.com/airbytehq/airbyte/pull/73801) | Update dependencies | From 338567972362db96c17c6e150b3dc9de13dc2f25 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:36:52 +0000 Subject: [PATCH 100/379] =?UTF-8?q?deps(source-nylas):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75739)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-nylas/metadata.yaml | 4 ++-- docs/integrations/sources/nylas.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-nylas/metadata.yaml b/airbyte-integrations/connectors/source-nylas/metadata.yaml index 26e58eba353d..a354b538aabf 100644 --- a/airbyte-integrations/connectors/source-nylas/metadata.yaml +++ b/airbyte-integrations/connectors/source-nylas/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-nylas connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.10.4@sha256:2f551a3fb5d580b34f4253aa1904d26c309364b09538f0b0fef3d8a98546f795 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 136a1ee6-5b95-4e09-9f3f-5c8df35df690 - dockerImageTag: 0.0.52 + dockerImageTag: 0.0.53 dockerRepository: airbyte/source-nylas githubIssueLabel: source-nylas icon: icon.svg diff --git a/docs/integrations/sources/nylas.md b/docs/integrations/sources/nylas.md index 4c8bfd3c219a..7fa823aa24e3 100644 --- a/docs/integrations/sources/nylas.md +++ b/docs/integrations/sources/nylas.md @@ -33,6 +33,7 @@ The Nylas platform provides an integration layer that makes it easy to connect a | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.53 | 2026-03-31 | [75739](https://github.com/airbytehq/airbyte/pull/75739) | Update dependencies | | 0.0.52 | 2026-03-10 | [74611](https://github.com/airbytehq/airbyte/pull/74611) | Update dependencies | | 0.0.51 | 2026-03-03 | [74183](https://github.com/airbytehq/airbyte/pull/74183) | Update dependencies | | 0.0.50 | 2026-02-17 | [73547](https://github.com/airbytehq/airbyte/pull/73547) | Update dependencies | From 2039013023e96624c74974639d86a4f2ba636da3 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:36:57 +0000 Subject: [PATCH 101/379] =?UTF-8?q?deps(source-visma-economic):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75738)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-visma-economic/metadata.yaml | 4 ++-- docs/integrations/sources/visma-economic.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-visma-economic/metadata.yaml b/airbyte-integrations/connectors/source-visma-economic/metadata.yaml index d20d5427a9b8..65bb5d63276b 100644 --- a/airbyte-integrations/connectors/source-visma-economic/metadata.yaml +++ b/airbyte-integrations/connectors/source-visma-economic/metadata.yaml @@ -3,11 +3,11 @@ data: hosts: - restapi.e-conomic.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 42495935-95de-4f5c-ae08-8fac00f6b308 - dockerImageTag: 0.3.53 + dockerImageTag: 0.3.54 dockerRepository: airbyte/source-visma-economic documentationUrl: https://docs.airbyte.com/integrations/sources/visma-economic githubIssueLabel: source-visma-economic diff --git a/docs/integrations/sources/visma-economic.md b/docs/integrations/sources/visma-economic.md index fe28dcd82b8a..22cc9d5ef047 100644 --- a/docs/integrations/sources/visma-economic.md +++ b/docs/integrations/sources/visma-economic.md @@ -56,6 +56,7 @@ For more information, see the [e-conomic REST API documentation](https://restdoc | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------ | +| 0.3.54 | 2026-03-31 | [75738](https://github.com/airbytehq/airbyte/pull/75738) | Update dependencies | | 0.3.53 | 2026-03-17 | [75124](https://github.com/airbytehq/airbyte/pull/75124) | Increase check_connection memory from 2Gi to 4Gi to prevent OOM | | 0.3.52 | 2026-03-17 | [75055](https://github.com/airbytehq/airbyte/pull/75055) | Update dependencies | | 0.3.51 | 2026-03-10 | [74513](https://github.com/airbytehq/airbyte/pull/74513) | Update dependencies | From aac0112db8ae5811772000f2de905da8772c6d90 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:37:02 +0000 Subject: [PATCH 102/379] =?UTF-8?q?deps(source-granola):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75737)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-granola/metadata.yaml | 4 ++-- docs/integrations/sources/granola.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-granola/metadata.yaml b/airbyte-integrations/connectors/source-granola/metadata.yaml index 7ffb148073b3..f37822c34332 100644 --- a/airbyte-integrations/connectors/source-granola/metadata.yaml +++ b/airbyte-integrations/connectors/source-granola/metadata.yaml @@ -3,11 +3,11 @@ data: ql: 100 sl: 100 connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 9023923c-002f-4131-9554-3ebdf56540a4 - dockerImageTag: 0.1.1 + dockerImageTag: 0.1.2 dockerRepository: airbyte/source-granola documentationUrl: https://docs.airbyte.com/integrations/sources/granola githubIssueLabel: source-granola diff --git a/docs/integrations/sources/granola.md b/docs/integrations/sources/granola.md index 96ad4c08787b..d27475db8eba 100644 --- a/docs/integrations/sources/granola.md +++ b/docs/integrations/sources/granola.md @@ -76,6 +76,7 @@ The connector handles rate limiting automatically by retrying requests when a `4 | Version | Date | Pull Request | Subject | | :------ | :--------- | :----------- | :-------------- | +| 0.1.2 | 2026-03-31 | [75737](https://github.com/airbytehq/airbyte/pull/75737) | Update dependencies | | 0.1.1 | 2026-03-24 | [75353](https://github.com/airbytehq/airbyte/pull/75353) | Update dependencies | | 0.1.0 | 2026-02-25 | [74033](https://github.com/airbytehq/airbyte/pull/74033) | Add detailed_notes substream with full note content via SubstreamPartitionRouter | | 0.0.3 | 2026-02-24 | [73377](https://github.com/airbytehq/airbyte/pull/73377) | Update dependencies | From 77ca13eeb7df31bbe8e4df599c2ad098a1b2b241 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:37:08 +0000 Subject: [PATCH 103/379] =?UTF-8?q?deps(source-help-scout):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75736)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-help-scout/metadata.yaml | 4 ++-- docs/integrations/sources/help-scout.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-help-scout/metadata.yaml b/airbyte-integrations/connectors/source-help-scout/metadata.yaml index 06677d8b17af..db5db9e751ab 100644 --- a/airbyte-integrations/connectors/source-help-scout/metadata.yaml +++ b/airbyte-integrations/connectors/source-help-scout/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-help-scout connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 96377d38-0bc6-47c0-9c84-c0fcc0f8ce40 - dockerImageTag: 0.0.39 + dockerImageTag: 0.0.40 dockerRepository: airbyte/source-help-scout githubIssueLabel: source-help-scout icon: icon.svg diff --git a/docs/integrations/sources/help-scout.md b/docs/integrations/sources/help-scout.md index a320354ddf09..7e2a09805a04 100644 --- a/docs/integrations/sources/help-scout.md +++ b/docs/integrations/sources/help-scout.md @@ -32,6 +32,7 @@ Auth Overview: https://developer.helpscout.com/mailbox-api/overview/authenticati | Version | Date | Pull Request | Subject | |------------------|-------------------|------------------------------------------------------|----------------| +| 0.0.40 | 2026-03-31 | [75736](https://github.com/airbytehq/airbyte/pull/75736) | Update dependencies | | 0.0.39 | 2026-03-24 | [74927](https://github.com/airbytehq/airbyte/pull/74927) | Update dependencies | | 0.0.38 | 2026-03-10 | [74681](https://github.com/airbytehq/airbyte/pull/74681) | Update dependencies | | 0.0.37 | 2026-02-24 | [73934](https://github.com/airbytehq/airbyte/pull/73934) | Update dependencies | From 60df0cd1eecad7ff62b252693e04ae083b45f21f Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:37:13 +0000 Subject: [PATCH 104/379] =?UTF-8?q?deps(source-hibob):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75735)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-hibob/metadata.yaml | 4 ++-- docs/integrations/sources/hibob.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-hibob/metadata.yaml b/airbyte-integrations/connectors/source-hibob/metadata.yaml index 2e2286f781c3..fdfc8915bb8a 100644 --- a/airbyte-integrations/connectors/source-hibob/metadata.yaml +++ b/airbyte-integrations/connectors/source-hibob/metadata.yaml @@ -16,11 +16,11 @@ data: # Please update to the latest version of the connector base image. # https://hub.docker.com/r/airbyte/python-connector-base # Please use the full address with sha256 hash to guarantee build reproducibility. - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 4dc991ed-3dcc-4c40-ac28-9402836709f1 - dockerImageTag: 0.2.45 + dockerImageTag: 0.2.46 dockerRepository: airbyte/source-hibob githubIssueLabel: source-hibob icon: icon.svg diff --git a/docs/integrations/sources/hibob.md b/docs/integrations/sources/hibob.md index 5b2aa84dc662..05c16c82c45a 100644 --- a/docs/integrations/sources/hibob.md +++ b/docs/integrations/sources/hibob.md @@ -80,6 +80,7 @@ Link to HiBob API documentation [here](https://apidocs.hibob.com/docs/). | Version | Date | Pull Request | Subject | |:---------|:-----------|:---------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------| +| 0.2.46 | 2026-03-31 | [75735](https://github.com/airbytehq/airbyte/pull/75735) | Update dependencies | | 0.2.45 | 2026-03-24 | [75352](https://github.com/airbytehq/airbyte/pull/75352) | Update dependencies | | 0.2.44 | 2026-03-10 | [74683](https://github.com/airbytehq/airbyte/pull/74683) | Update dependencies | | 0.2.43 | 2026-02-24 | [73966](https://github.com/airbytehq/airbyte/pull/73966) | Update dependencies | From c8a55cff31059b31e4053566e26f6b137a5be58d Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:37:18 +0000 Subject: [PATCH 105/379] =?UTF-8?q?deps(source-google-pagespeed-insights):?= =?UTF-8?q?=20=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#7573?= =?UTF-8?q?4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-google-pagespeed-insights/metadata.yaml | 4 ++-- docs/integrations/sources/google-pagespeed-insights.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-google-pagespeed-insights/metadata.yaml b/airbyte-integrations/connectors/source-google-pagespeed-insights/metadata.yaml index fabc20d9cac5..ce0de2ec6fbb 100644 --- a/airbyte-integrations/connectors/source-google-pagespeed-insights/metadata.yaml +++ b/airbyte-integrations/connectors/source-google-pagespeed-insights/metadata.yaml @@ -3,11 +3,11 @@ data: ql: 100 sl: 100 connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 1e9086ab-ddac-4c1d-aafd-ba43ff575fe4 - dockerImageTag: 0.2.45 + dockerImageTag: 0.2.46 dockerRepository: airbyte/source-google-pagespeed-insights documentationUrl: https://docs.airbyte.com/integrations/sources/google-pagespeed-insights githubIssueLabel: source-google-pagespeed-insights diff --git a/docs/integrations/sources/google-pagespeed-insights.md b/docs/integrations/sources/google-pagespeed-insights.md index 1583c27d6831..5ff174521069 100644 --- a/docs/integrations/sources/google-pagespeed-insights.md +++ b/docs/integrations/sources/google-pagespeed-insights.md @@ -55,6 +55,7 @@ If the connector is used with an API key, Google allows for 25.000 queries per d | Version | Date | Pull Request | Subject | | :------ | :--------- | :-------------------------------------------------------- | :------------------------------------------------------------------------------ | +| 0.2.46 | 2026-03-31 | [75734](https://github.com/airbytehq/airbyte/pull/75734) | Update dependencies | | 0.2.45 | 2026-03-17 | [74938](https://github.com/airbytehq/airbyte/pull/74938) | Update dependencies | | 0.2.44 | 2026-02-24 | [73931](https://github.com/airbytehq/airbyte/pull/73931) | Update dependencies | | 0.2.43 | 2026-02-17 | [73374](https://github.com/airbytehq/airbyte/pull/73374) | Update dependencies | From 2c922b3aedff83df20380aa9127b8ed5fb345e07 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:37:23 +0000 Subject: [PATCH 106/379] =?UTF-8?q?deps(source-web-scrapper):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75733)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-web-scrapper/metadata.yaml | 4 ++-- docs/integrations/sources/web-scrapper.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-web-scrapper/metadata.yaml b/airbyte-integrations/connectors/source-web-scrapper/metadata.yaml index 739d772da015..50e3f81ef7ae 100644 --- a/airbyte-integrations/connectors/source-web-scrapper/metadata.yaml +++ b/airbyte-integrations/connectors/source-web-scrapper/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-web-scrapper connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 2f87b960-0220-4b76-9ab3-fba67ca4c959 - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-web-scrapper githubIssueLabel: source-web-scrapper icon: icon.svg diff --git a/docs/integrations/sources/web-scrapper.md b/docs/integrations/sources/web-scrapper.md index 1aaad5173b5e..2857ea5a3ea2 100644 --- a/docs/integrations/sources/web-scrapper.md +++ b/docs/integrations/sources/web-scrapper.md @@ -23,6 +23,7 @@ | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.49 | 2026-03-31 | [75733](https://github.com/airbytehq/airbyte/pull/75733) | Update dependencies | | 0.0.48 | 2026-03-24 | [75060](https://github.com/airbytehq/airbyte/pull/75060) | Update dependencies | | 0.0.47 | 2026-03-10 | [74489](https://github.com/airbytehq/airbyte/pull/74489) | Update dependencies | | 0.0.46 | 2026-02-24 | [73445](https://github.com/airbytehq/airbyte/pull/73445) | Update dependencies | From 4010d3833f9554c0b8243265969c958349a14e34 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:37:27 +0000 Subject: [PATCH 107/379] =?UTF-8?q?deps(source-high-level):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75732)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-high-level/metadata.yaml | 4 ++-- docs/integrations/sources/high-level.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-high-level/metadata.yaml b/airbyte-integrations/connectors/source-high-level/metadata.yaml index 0d4b59f2bcab..879386addaea 100644 --- a/airbyte-integrations/connectors/source-high-level/metadata.yaml +++ b/airbyte-integrations/connectors/source-high-level/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-high-level connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 2028e68a-8c97-45c4-b196-e61bad7b6f40 - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-high-level githubIssueLabel: source-high-level icon: icon.svg diff --git a/docs/integrations/sources/high-level.md b/docs/integrations/sources/high-level.md index 29a225c694a9..f252a4eb6afd 100644 --- a/docs/integrations/sources/high-level.md +++ b/docs/integrations/sources/high-level.md @@ -33,6 +33,7 @@ Proxy connector for [Go High Level](https://gohighlevel.com) (Lead Connector). R | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.48 | 2026-03-31 | [75732](https://github.com/airbytehq/airbyte/pull/75732) | Update dependencies | | 0.0.47 | 2026-03-17 | [74665](https://github.com/airbytehq/airbyte/pull/74665) | Update dependencies | | 0.0.46 | 2026-03-03 | [74173](https://github.com/airbytehq/airbyte/pull/74173) | Update dependencies | | 0.0.45 | 2026-02-10 | [73117](https://github.com/airbytehq/airbyte/pull/73117) | Update dependencies | From ada33bdbb7c3c8f87d99675fc9820a41cd70bd78 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:37:32 +0000 Subject: [PATCH 108/379] =?UTF-8?q?deps(source-watchmode):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75731)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-watchmode/metadata.yaml | 4 ++-- docs/integrations/sources/watchmode.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-watchmode/metadata.yaml b/airbyte-integrations/connectors/source-watchmode/metadata.yaml index 1e3f31045324..329ae2afa6ce 100644 --- a/airbyte-integrations/connectors/source-watchmode/metadata.yaml +++ b/airbyte-integrations/connectors/source-watchmode/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-watchmode connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: c10bae9d-398b-480a-a49b-5ae69cdc0759 - dockerImageTag: 0.0.32 + dockerImageTag: 0.0.33 dockerRepository: airbyte/source-watchmode githubIssueLabel: source-watchmode icon: icon.svg diff --git a/docs/integrations/sources/watchmode.md b/docs/integrations/sources/watchmode.md index f71436aad06c..a13213c6e9e5 100644 --- a/docs/integrations/sources/watchmode.md +++ b/docs/integrations/sources/watchmode.md @@ -29,6 +29,7 @@ API Reference: https://api.watchmode.com/docs | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.33 | 2026-03-31 | [75731](https://github.com/airbytehq/airbyte/pull/75731) | Update dependencies | | 0.0.32 | 2026-03-17 | [75050](https://github.com/airbytehq/airbyte/pull/75050) | Update dependencies | | 0.0.31 | 2026-03-10 | [74508](https://github.com/airbytehq/airbyte/pull/74508) | Update dependencies | | 0.0.30 | 2026-02-24 | [73921](https://github.com/airbytehq/airbyte/pull/73921) | Update dependencies | From b95d38ccc0105df3fc528786330abf6e770fb76e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:37:37 +0000 Subject: [PATCH 109/379] =?UTF-8?q?deps(source-kisi):=20=F0=9F=90=99=20upd?= =?UTF-8?q?ate=20dependencies=20[2026-03-31]=20(#75730)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-kisi/metadata.yaml | 4 ++-- docs/integrations/sources/kisi.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-kisi/metadata.yaml b/airbyte-integrations/connectors/source-kisi/metadata.yaml index bb1b98ffa62e..8ab74771f158 100644 --- a/airbyte-integrations/connectors/source-kisi/metadata.yaml +++ b/airbyte-integrations/connectors/source-kisi/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-kisi connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 7706728b-f644-456e-8dd4-ac92c4d8f31a - dockerImageTag: 0.0.54 + dockerImageTag: 0.0.55 dockerRepository: airbyte/source-kisi githubIssueLabel: source-kisi icon: icon.svg diff --git a/docs/integrations/sources/kisi.md b/docs/integrations/sources/kisi.md index 656de9625315..8261af9a0aba 100644 --- a/docs/integrations/sources/kisi.md +++ b/docs/integrations/sources/kisi.md @@ -39,6 +39,7 @@ You can learn more about the API key here https://api.kisi.io/docs#/ | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.55 | 2026-03-31 | [75730](https://github.com/airbytehq/airbyte/pull/75730) | Update dependencies | | 0.0.54 | 2026-03-24 | [75029](https://github.com/airbytehq/airbyte/pull/75029) | Update dependencies | | 0.0.53 | 2026-03-10 | [74419](https://github.com/airbytehq/airbyte/pull/74419) | Update dependencies | | 0.0.52 | 2026-03-03 | [73956](https://github.com/airbytehq/airbyte/pull/73956) | Update dependencies | From dabaf2c187f8b502ab53a5e4d6ef37532fb7d138 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:37:42 +0000 Subject: [PATCH 110/379] =?UTF-8?q?deps(source-greenhouse):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75729)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-greenhouse/metadata.yaml | 4 ++-- docs/integrations/sources/greenhouse.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-greenhouse/metadata.yaml b/airbyte-integrations/connectors/source-greenhouse/metadata.yaml index 1e4cfbcf0440..7cf3aae224ae 100644 --- a/airbyte-integrations/connectors/source-greenhouse/metadata.yaml +++ b/airbyte-integrations/connectors/source-greenhouse/metadata.yaml @@ -6,11 +6,11 @@ data: hosts: - harvest.greenhouse.io connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 59f1e50a-331f-4f09-b3e8-2e8d4d355f44 - dockerImageTag: 0.7.18 + dockerImageTag: 0.7.19 dockerRepository: airbyte/source-greenhouse documentationUrl: https://docs.airbyte.com/integrations/sources/greenhouse githubIssueLabel: source-greenhouse diff --git a/docs/integrations/sources/greenhouse.md b/docs/integrations/sources/greenhouse.md index b9f4c0a81092..ab5a704954c1 100644 --- a/docs/integrations/sources/greenhouse.md +++ b/docs/integrations/sources/greenhouse.md @@ -74,6 +74,7 @@ The Greenhouse connector should not run into Greenhouse API limitations under no | Version | Date | Pull Request | Subject | |:-----------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0.7.19 | 2026-03-31 | [75729](https://github.com/airbytehq/airbyte/pull/75729) | Update dependencies | | 0.7.18 | 2026-03-17 | [74919](https://github.com/airbytehq/airbyte/pull/74919) | Update dependencies | | 0.7.17 | 2026-03-10 | [74688](https://github.com/airbytehq/airbyte/pull/74688) | Update dependencies | | 0.7.16 | 2026-03-03 | [74176](https://github.com/airbytehq/airbyte/pull/74176) | Update dependencies | From a140c598cfac70f92870b0b10250e5a870fd1726 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:37:47 +0000 Subject: [PATCH 111/379] =?UTF-8?q?deps(source-lightspeed-retail):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75728)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-lightspeed-retail/metadata.yaml | 4 ++-- docs/integrations/sources/lightspeed-retail.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-lightspeed-retail/metadata.yaml b/airbyte-integrations/connectors/source-lightspeed-retail/metadata.yaml index 223172d89096..029f42b4f50b 100644 --- a/airbyte-integrations/connectors/source-lightspeed-retail/metadata.yaml +++ b/airbyte-integrations/connectors/source-lightspeed-retail/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-lightspeed-retail connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 0f242d62-dbef-49d7-8cc1-72ff7e54c9ca - dockerImageTag: 0.0.50 + dockerImageTag: 0.0.51 dockerRepository: airbyte/source-lightspeed-retail githubIssueLabel: source-lightspeed-retail icon: icon.svg diff --git a/docs/integrations/sources/lightspeed-retail.md b/docs/integrations/sources/lightspeed-retail.md index 9c0a4dae57d4..cb81d6286e71 100644 --- a/docs/integrations/sources/lightspeed-retail.md +++ b/docs/integrations/sources/lightspeed-retail.md @@ -51,6 +51,7 @@ After logging in, you can create your personal token by navigating to Setup -> | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.51 | 2026-03-31 | [75728](https://github.com/airbytehq/airbyte/pull/75728) | Update dependencies | | 0.0.50 | 2026-03-24 | [75033](https://github.com/airbytehq/airbyte/pull/75033) | Update dependencies | | 0.0.49 | 2026-02-24 | [73954](https://github.com/airbytehq/airbyte/pull/73954) | Update dependencies | | 0.0.48 | 2026-02-17 | [73541](https://github.com/airbytehq/airbyte/pull/73541) | Update dependencies | From 99ab11ace22a43e69e3d8eedf79f3472d9c96571 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:37:54 +0000 Subject: [PATCH 112/379] =?UTF-8?q?deps(source-justcall):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75726)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-justcall/metadata.yaml | 4 ++-- docs/integrations/sources/justcall.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-justcall/metadata.yaml b/airbyte-integrations/connectors/source-justcall/metadata.yaml index 889ccef65cc4..93ea9514a09c 100644 --- a/airbyte-integrations/connectors/source-justcall/metadata.yaml +++ b/airbyte-integrations/connectors/source-justcall/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-justcall connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 488cdc64-36cd-451d-bcfa-c6478b461e94 - dockerImageTag: 0.0.46 + dockerImageTag: 0.0.47 dockerRepository: airbyte/source-justcall githubIssueLabel: source-justcall icon: icon.svg diff --git a/docs/integrations/sources/justcall.md b/docs/integrations/sources/justcall.md index f8c9643bb993..7d9e9bfdb1a4 100644 --- a/docs/integrations/sources/justcall.md +++ b/docs/integrations/sources/justcall.md @@ -25,6 +25,7 @@ JustCall connector enables seamless data integration by syncing call logs, conta | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.47 | 2026-03-31 | [75726](https://github.com/airbytehq/airbyte/pull/75726) | Update dependencies | | 0.0.46 | 2026-03-24 | [75034](https://github.com/airbytehq/airbyte/pull/75034) | Update dependencies | | 0.0.45 | 2026-02-24 | [73952](https://github.com/airbytehq/airbyte/pull/73952) | Update dependencies | | 0.0.44 | 2026-02-17 | [73551](https://github.com/airbytehq/airbyte/pull/73551) | Update dependencies | From 3a45036b497413379b539bc97f18410437360ad2 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:37:59 +0000 Subject: [PATCH 113/379] =?UTF-8?q?deps(source-fleetio):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75725)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-fleetio/metadata.yaml | 4 ++-- docs/integrations/sources/fleetio.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-fleetio/metadata.yaml b/airbyte-integrations/connectors/source-fleetio/metadata.yaml index 674088d50d55..e2a275839092 100644 --- a/airbyte-integrations/connectors/source-fleetio/metadata.yaml +++ b/airbyte-integrations/connectors/source-fleetio/metadata.yaml @@ -5,11 +5,11 @@ data: oss: enabled: true connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 13a7652d-1d94-4033-931a-613d22d3cbb3 - dockerImageTag: 0.2.47 + dockerImageTag: 0.2.48 dockerRepository: airbyte/source-fleetio githubIssueLabel: source-fleetio icon: icon.svg diff --git a/docs/integrations/sources/fleetio.md b/docs/integrations/sources/fleetio.md index edc942e19a8a..aac829cd524f 100644 --- a/docs/integrations/sources/fleetio.md +++ b/docs/integrations/sources/fleetio.md @@ -51,6 +51,7 @@ Our source connector adheres to the standard rate limiting with the Airbyte low- | Version | Date | Pull Request | Subject | |:--------|:-----------|:---------------------------------------------------------|:------------------------------------------------| +| 0.2.48 | 2026-03-31 | [75725](https://github.com/airbytehq/airbyte/pull/75725) | Update dependencies | | 0.2.47 | 2026-03-17 | [74637](https://github.com/airbytehq/airbyte/pull/74637) | Update dependencies | | 0.2.46 | 2026-02-24 | [73754](https://github.com/airbytehq/airbyte/pull/73754) | Update dependencies | | 0.2.45 | 2026-02-17 | [73378](https://github.com/airbytehq/airbyte/pull/73378) | Update dependencies | From 438b029d909d4aefac1c0fe8bea6874d228fda66 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:38:06 +0000 Subject: [PATCH 114/379] docs(source-faker): fix changelog PR link for v7.0.4 (#75724) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- docs/integrations/sources/faker.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/sources/faker.md b/docs/integrations/sources/faker.md index 20508eb6b3d0..e98df6b66b7c 100644 --- a/docs/integrations/sources/faker.md +++ b/docs/integrations/sources/faker.md @@ -47,7 +47,7 @@ Each purchase record includes: `id`, `user_id`, `product_id`, `created_at`, `upd | Version | Date | Pull Request | Subject | |:------------|:-----------| :-------------------------------------------------------------------------------------------------------------------- |:----------------------------------------------------------------------------------------------------------------| -| 7.0.4 | 2026-03-31 | [75646](https://github.com/airbytehq/airbyte/pull/75646) | Patch version bump (test publish) | +| 7.0.4 | 2026-03-31 | [75657](https://github.com/airbytehq/airbyte/pull/75657) | Patch version bump (test publish) | | 7.0.3 | 2026-03-20 | [75256](https://github.com/airbytehq/airbyte/pull/75256) | Re-release to verify yank/un-yank behavior in ops CLI registry pipeline | | 7.0.2 | 2026-03-19 | [75232](https://github.com/airbytehq/airbyte/pull/75232) | Patch version bump (ops CLI registry post-launch test) | | 7.0.1 | 2026-03-13 | [74818](https://github.com/airbytehq/airbyte/pull/74818) | Patch version bump (publish test) | From 7a30de49e3b1a54c8a2e60c512fa04b3285d6681 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:38:15 +0000 Subject: [PATCH 115/379] =?UTF-8?q?deps(source-freshsales):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75723)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-freshsales/metadata.yaml | 4 ++-- docs/integrations/sources/freshsales.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-freshsales/metadata.yaml b/airbyte-integrations/connectors/source-freshsales/metadata.yaml index 56f25e7c2b59..861b44d89034 100644 --- a/airbyte-integrations/connectors/source-freshsales/metadata.yaml +++ b/airbyte-integrations/connectors/source-freshsales/metadata.yaml @@ -18,11 +18,11 @@ data: # Please update to the latest version of the connector base image. # https://hub.docker.com/r/airbyte/python-connector-base # Please use the full address with sha256 hash to guarantee build reproducibility. - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: eca08d79-7b92-4065-b7f3-79c14836ebe7 - dockerImageTag: 1.1.45 + dockerImageTag: 1.1.46 releases: breakingChanges: 1.0.0: diff --git a/docs/integrations/sources/freshsales.md b/docs/integrations/sources/freshsales.md index cba0980043b6..351aa8a93244 100644 --- a/docs/integrations/sources/freshsales.md +++ b/docs/integrations/sources/freshsales.md @@ -68,6 +68,7 @@ The Freshsales connector should not run into Freshsales API limitations under no | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :----------------------------------------------------------- | +| 1.1.46 | 2026-03-31 | [75723](https://github.com/airbytehq/airbyte/pull/75723) | Update dependencies | | 1.1.45 | 2026-03-24 | [75315](https://github.com/airbytehq/airbyte/pull/75315) | Update dependencies | | 1.1.44 | 2026-03-03 | [74194](https://github.com/airbytehq/airbyte/pull/74194) | Update dependencies | | 1.1.43 | 2026-02-17 | [73402](https://github.com/airbytehq/airbyte/pull/73402) | Update dependencies | From 41514590c4f2ac48fd56e30a472b1c8a8ea76c77 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:38:20 +0000 Subject: [PATCH 116/379] =?UTF-8?q?deps(source-when-i-work):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75722)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-when-i-work/metadata.yaml | 4 ++-- docs/integrations/sources/when-i-work.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-when-i-work/metadata.yaml b/airbyte-integrations/connectors/source-when-i-work/metadata.yaml index 338c18d7f39d..e755b89c7943 100644 --- a/airbyte-integrations/connectors/source-when-i-work/metadata.yaml +++ b/airbyte-integrations/connectors/source-when-i-work/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-when-i-work connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 81ee3b58-ae1e-4727-be23-30248fa27a0a - dockerImageTag: 0.0.49 + dockerImageTag: 0.0.50 dockerRepository: airbyte/source-when-i-work githubIssueLabel: source-when-i-work icon: icon.svg diff --git a/docs/integrations/sources/when-i-work.md b/docs/integrations/sources/when-i-work.md index 3605bc29f019..e58811a9caf1 100644 --- a/docs/integrations/sources/when-i-work.md +++ b/docs/integrations/sources/when-i-work.md @@ -38,6 +38,7 @@ You have to give your login email and password used with `when-i-work` account f | Version | Date | Pull Request | Subject | | ------------------ | ------------ | --- | ---------------- | +| 0.0.50 | 2026-03-31 | [75722](https://github.com/airbytehq/airbyte/pull/75722) | Update dependencies | | 0.0.49 | 2026-03-17 | [75058](https://github.com/airbytehq/airbyte/pull/75058) | Update dependencies | | 0.0.48 | 2026-03-10 | [74492](https://github.com/airbytehq/airbyte/pull/74492) | Update dependencies | | 0.0.47 | 2026-03-03 | [74207](https://github.com/airbytehq/airbyte/pull/74207) | Update dependencies | From 4967d49158839f0af23ceca1aacf2a489ab0e1b2 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:38:24 +0000 Subject: [PATCH 117/379] =?UTF-8?q?deps(source-firehydrant):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75721)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-firehydrant/metadata.yaml | 4 ++-- docs/integrations/sources/firehydrant.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-firehydrant/metadata.yaml b/airbyte-integrations/connectors/source-firehydrant/metadata.yaml index 56d985149b5b..947acfd384e4 100644 --- a/airbyte-integrations/connectors/source-firehydrant/metadata.yaml +++ b/airbyte-integrations/connectors/source-firehydrant/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-firehydrant connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: b58c3536-7900-439c-80a8-fc2b94460781 - dockerImageTag: 1.0.2 + dockerImageTag: 1.0.3 dockerRepository: airbyte/source-firehydrant githubIssueLabel: source-firehydrant icon: icon.svg diff --git a/docs/integrations/sources/firehydrant.md b/docs/integrations/sources/firehydrant.md index 0fccff43891d..73754d114ed3 100644 --- a/docs/integrations/sources/firehydrant.md +++ b/docs/integrations/sources/firehydrant.md @@ -58,6 +58,7 @@ The Airbyte connector for FireHydrant enables seamless data integration between | Version | Date | Pull Request | Subject | |---------|-------------------|--------------|----------------| +| 1.0.3 | 2026-03-31 | [75721](https://github.com/airbytehq/airbyte/pull/75721) | Update dependencies | | 1.0.2 | 2026-03-17 | [74945](https://github.com/airbytehq/airbyte/pull/74945) | Update dependencies | | 1.0.1 | 2026-03-03 | [73781](https://github.com/airbytehq/airbyte/pull/73781) | Update dependencies | | 1.0.0 | 2026-02-24 | [74008](https://github.com/airbytehq/airbyte/pull/74008) | Rename `enviroments` stream to `environments` | From 5bd35b9227c375cc16bdc026942b5132eb63b19e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:38:29 +0000 Subject: [PATCH 118/379] =?UTF-8?q?deps(source-linear):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75720)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-linear/metadata.yaml | 4 ++-- docs/integrations/sources/linear.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-linear/metadata.yaml b/airbyte-integrations/connectors/source-linear/metadata.yaml index d4613a434a88..c71c10d7d1cf 100644 --- a/airbyte-integrations/connectors/source-linear/metadata.yaml +++ b/airbyte-integrations/connectors/source-linear/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-linear connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 1c5d8316-ed42-4473-8fbc-2626f03f070c - dockerImageTag: 0.0.35 + dockerImageTag: 0.0.36 dockerRepository: airbyte/source-linear githubIssueLabel: source-linear icon: icon.svg diff --git a/docs/integrations/sources/linear.md b/docs/integrations/sources/linear.md index 3ee3682e1b95..e5df923062e4 100644 --- a/docs/integrations/sources/linear.md +++ b/docs/integrations/sources/linear.md @@ -80,6 +80,7 @@ The connector retrieves data that the authenticated user has access to. If you c | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.36 | 2026-03-31 | [75720](https://github.com/airbytehq/airbyte/pull/75720) | Update dependencies | | 0.0.35 | 2026-03-17 | [75023](https://github.com/airbytehq/airbyte/pull/75023) | Update dependencies | | 0.0.34 | 2026-03-03 | [74239](https://github.com/airbytehq/airbyte/pull/74239) | Update dependencies | | 0.0.33 | 2026-02-10 | [73035](https://github.com/airbytehq/airbyte/pull/73035) | Update dependencies | From 93831d022eaac705ce64d5b083edabf03db79fc7 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:38:35 +0000 Subject: [PATCH 119/379] =?UTF-8?q?deps(source-freshdesk):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75719)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-freshdesk/metadata.yaml | 4 ++-- docs/integrations/sources/freshdesk.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-freshdesk/metadata.yaml b/airbyte-integrations/connectors/source-freshdesk/metadata.yaml index 0be93b11845b..c438fcda1582 100644 --- a/airbyte-integrations/connectors/source-freshdesk/metadata.yaml +++ b/airbyte-integrations/connectors/source-freshdesk/metadata.yaml @@ -6,11 +6,11 @@ data: hosts: - "*.freshdesk.com" connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: ec4b9503-13cb-48ab-a4ab-6ade4be46567 - dockerImageTag: 3.2.12 + dockerImageTag: 3.2.13 dockerRepository: airbyte/source-freshdesk documentationUrl: https://docs.airbyte.com/integrations/sources/freshdesk externalDocumentationUrls: diff --git a/docs/integrations/sources/freshdesk.md b/docs/integrations/sources/freshdesk.md index 27b5b615aa35..56c048cb4904 100644 --- a/docs/integrations/sources/freshdesk.md +++ b/docs/integrations/sources/freshdesk.md @@ -72,6 +72,7 @@ If you don't use the start date Freshdesk will retrieve only the last 30 days. M | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------------ | +| 3.2.13 | 2026-03-31 | [75719](https://github.com/airbytehq/airbyte/pull/75719) | Update dependencies | | 3.2.12 | 2026-03-24 | [74647](https://github.com/airbytehq/airbyte/pull/74647) | Update dependencies | | 3.2.11 | 2026-03-03 | [74188](https://github.com/airbytehq/airbyte/pull/74188) | Update dependencies | | 3.2.10 | 2026-02-17 | [73400](https://github.com/airbytehq/airbyte/pull/73400) | Update dependencies | From f81e985fb3cb4ed1c39e73291d0ae36ac2992157 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:38:41 +0000 Subject: [PATCH 120/379] =?UTF-8?q?deps(source-vantage):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75718)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-vantage/metadata.yaml | 4 ++-- docs/integrations/sources/vantage.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-vantage/metadata.yaml b/airbyte-integrations/connectors/source-vantage/metadata.yaml index 9efadf9560c9..4e068fe646c3 100644 --- a/airbyte-integrations/connectors/source-vantage/metadata.yaml +++ b/airbyte-integrations/connectors/source-vantage/metadata.yaml @@ -2,7 +2,7 @@ data: connectorSubtype: api connectorType: source definitionId: 28ce1fbd-1e15-453f-aa9f-da6c4d928e92 - dockerImageTag: 0.2.45 + dockerImageTag: 0.2.46 dockerRepository: airbyte/source-vantage githubIssueLabel: source-vantage icon: vantage.svg @@ -39,7 +39,7 @@ data: type: GSM alias: airbyte-connector-testing-secret-store connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e externalDocumentationUrls: - title: Vantage API documentation url: https://docs.vantage.sh/ diff --git a/docs/integrations/sources/vantage.md b/docs/integrations/sources/vantage.md index 4b4ffb29f13c..f739eab097eb 100644 --- a/docs/integrations/sources/vantage.md +++ b/docs/integrations/sources/vantage.md @@ -35,6 +35,7 @@ Vantage APIs are under rate limits for the number of API calls allowed per API k | Version | Date | Pull Request | Subject | | :------ | :--------- | :-------------------------------------------------------- | :---------------------------------------- | +| 0.2.46 | 2026-03-31 | [75718](https://github.com/airbytehq/airbyte/pull/75718) | Update dependencies | | 0.2.45 | 2026-03-17 | [75040](https://github.com/airbytehq/airbyte/pull/75040) | Update dependencies | | 0.2.44 | 2026-02-24 | [73918](https://github.com/airbytehq/airbyte/pull/73918) | Update dependencies | | 0.2.43 | 2026-02-17 | [73428](https://github.com/airbytehq/airbyte/pull/73428) | Update dependencies | From efec4fc34b99a3b403407689806c13a41845c359 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:38:47 +0000 Subject: [PATCH 121/379] =?UTF-8?q?deps(source-feishu):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75717)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-feishu/metadata.yaml | 4 ++-- docs/integrations/sources/feishu.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-feishu/metadata.yaml b/airbyte-integrations/connectors/source-feishu/metadata.yaml index 60af5aa75848..886685bd53ee 100644 --- a/airbyte-integrations/connectors/source-feishu/metadata.yaml +++ b/airbyte-integrations/connectors/source-feishu/metadata.yaml @@ -14,11 +14,11 @@ data: enabled: false packageName: airbyte-source-feishu connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 3f1aa18a-a111-4e3b-8cac-9b79a091cc13 - dockerImageTag: 0.0.3 + dockerImageTag: 0.0.4 dockerRepository: airbyte/source-feishu githubIssueLabel: source-feishu icon: icon.svg diff --git a/docs/integrations/sources/feishu.md b/docs/integrations/sources/feishu.md index 9a64339ad364..65321942794a 100644 --- a/docs/integrations/sources/feishu.md +++ b/docs/integrations/sources/feishu.md @@ -71,6 +71,7 @@ The **records** stream returns all records from the specified Bitable table. Eac | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.4 | 2026-03-31 | [75717](https://github.com/airbytehq/airbyte/pull/75717) | Update dependencies | | 0.0.3 | 2026-03-17 | [74640](https://github.com/airbytehq/airbyte/pull/74640) | Update dependencies | | 0.0.2 | 2026-02-24 | [73777](https://github.com/airbytehq/airbyte/pull/73777) | Update dependencies | | 0.0.1 | 2026-02-19 | [71256](https://github.com/airbytehq/airbyte/pull/71256) | Initial release by [@WYW-min](https://github.com/WYW-min) via Connector Builder | From 300f2440453333af9dcb8521e8dc041527d77019 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:38:52 +0000 Subject: [PATCH 122/379] =?UTF-8?q?deps(source-financial-modelling):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75716)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-financial-modelling/metadata.yaml | 4 ++-- docs/integrations/sources/financial-modelling.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-financial-modelling/metadata.yaml b/airbyte-integrations/connectors/source-financial-modelling/metadata.yaml index 959695530910..f8e136d6cabf 100644 --- a/airbyte-integrations/connectors/source-financial-modelling/metadata.yaml +++ b/airbyte-integrations/connectors/source-financial-modelling/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-financial-modelling connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 4c3d6bdd-dc0e-4a66-b48a-2e7956195eec - dockerImageTag: 0.0.46 + dockerImageTag: 0.0.47 dockerRepository: airbyte/source-financial-modelling githubIssueLabel: source-financial-modelling icon: icon.svg diff --git a/docs/integrations/sources/financial-modelling.md b/docs/integrations/sources/financial-modelling.md index 0b8b968eaac5..10f8bb15f2b7 100644 --- a/docs/integrations/sources/financial-modelling.md +++ b/docs/integrations/sources/financial-modelling.md @@ -42,6 +42,7 @@ Docs : https://site.financialmodelingprep.com/developer/docs | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.47 | 2026-03-31 | [75716](https://github.com/airbytehq/airbyte/pull/75716) | Update dependencies | | 0.0.46 | 2026-03-17 | [74642](https://github.com/airbytehq/airbyte/pull/74642) | Update dependencies | | 0.0.45 | 2026-02-24 | [73743](https://github.com/airbytehq/airbyte/pull/73743) | Update dependencies | | 0.0.44 | 2026-02-17 | [73405](https://github.com/airbytehq/airbyte/pull/73405) | Update dependencies | From 638ec70bd37240c24aabdc74a9a515612bd11167 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:38:59 +0000 Subject: [PATCH 123/379] =?UTF-8?q?deps(source-guru):=20=F0=9F=90=99=20upd?= =?UTF-8?q?ate=20dependencies=20[2026-03-31]=20(#75715)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-guru/metadata.yaml | 4 ++-- docs/integrations/sources/guru.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-guru/metadata.yaml b/airbyte-integrations/connectors/source-guru/metadata.yaml index 31366985c4a1..facd128c11ee 100644 --- a/airbyte-integrations/connectors/source-guru/metadata.yaml +++ b/airbyte-integrations/connectors/source-guru/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-guru connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 30e2d5f2-63c1-4993-8079-c8abf24e747d - dockerImageTag: 0.0.52 + dockerImageTag: 0.0.53 dockerRepository: airbyte/source-guru githubIssueLabel: source-guru icon: icon.svg diff --git a/docs/integrations/sources/guru.md b/docs/integrations/sources/guru.md index 19ac617c1f99..3cf96c3a5cc3 100644 --- a/docs/integrations/sources/guru.md +++ b/docs/integrations/sources/guru.md @@ -50,6 +50,7 @@ To set up the Guru source connector, you'll need the [Guru Auth keys](https://de | Version | Date | Pull Request | Subject | | ------------------ | ------------ | --- | ---------------- | +| 0.0.53 | 2026-03-31 | [75715](https://github.com/airbytehq/airbyte/pull/75715) | Update dependencies | | 0.0.52 | 2026-03-17 | [74653](https://github.com/airbytehq/airbyte/pull/74653) | Update dependencies | | 0.0.51 | 2026-03-03 | [74177](https://github.com/airbytehq/airbyte/pull/74177) | Update dependencies | | 0.0.50 | 2026-02-17 | [73381](https://github.com/airbytehq/airbyte/pull/73381) | Update dependencies | From 036935e8500e5e444058d9cfa2e69556684050b5 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:39:05 +0000 Subject: [PATCH 124/379] =?UTF-8?q?deps(source-freightview):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75714)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-freightview/metadata.yaml | 4 ++-- docs/integrations/sources/freightview.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-freightview/metadata.yaml b/airbyte-integrations/connectors/source-freightview/metadata.yaml index 4edb483f9340..7e13f1ccc976 100644 --- a/airbyte-integrations/connectors/source-freightview/metadata.yaml +++ b/airbyte-integrations/connectors/source-freightview/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-freightview connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: aaedb415-d131-468f-84ab-5319d72e02ed - dockerImageTag: 0.0.46 + dockerImageTag: 0.0.47 dockerRepository: airbyte/source-freightview githubIssueLabel: source-freightview icon: icon.svg diff --git a/docs/integrations/sources/freightview.md b/docs/integrations/sources/freightview.md index ac1d5daddcaa..1310464de6ba 100644 --- a/docs/integrations/sources/freightview.md +++ b/docs/integrations/sources/freightview.md @@ -22,6 +22,7 @@ An **Airbyte connector for Freightview** enables seamless data integration by ex | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.47 | 2026-03-31 | [75714](https://github.com/airbytehq/airbyte/pull/75714) | Update dependencies | | 0.0.46 | 2026-03-17 | [74918](https://github.com/airbytehq/airbyte/pull/74918) | Update dependencies | | 0.0.45 | 2026-02-24 | [73764](https://github.com/airbytehq/airbyte/pull/73764) | Update dependencies | | 0.0.44 | 2026-02-17 | [73383](https://github.com/airbytehq/airbyte/pull/73383) | Update dependencies | From 7fa09db282648e2a8ea1f2e71a202bfb3f9d0fb9 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:39:10 +0000 Subject: [PATCH 125/379] =?UTF-8?q?deps(source-flowlu):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75713)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-flowlu/metadata.yaml | 4 ++-- docs/integrations/sources/flowlu.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-flowlu/metadata.yaml b/airbyte-integrations/connectors/source-flowlu/metadata.yaml index bd7a227795fa..aab66ec47ec2 100644 --- a/airbyte-integrations/connectors/source-flowlu/metadata.yaml +++ b/airbyte-integrations/connectors/source-flowlu/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-flowlu connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: c9db3f2d-054a-43bc-96cc-0d2843bce018 - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-flowlu githubIssueLabel: source-flowlu icon: icon.svg diff --git a/docs/integrations/sources/flowlu.md b/docs/integrations/sources/flowlu.md index 66d56f075aa0..5eba1d6a7b16 100644 --- a/docs/integrations/sources/flowlu.md +++ b/docs/integrations/sources/flowlu.md @@ -55,6 +55,7 @@ Flowlu connector enables seamless data integration between Flowlu, a project man | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.48 | 2026-03-31 | [75713](https://github.com/airbytehq/airbyte/pull/75713) | Update dependencies | | 0.0.47 | 2026-03-24 | [75314](https://github.com/airbytehq/airbyte/pull/75314) | Update dependencies | | 0.0.46 | 2026-03-03 | [73776](https://github.com/airbytehq/airbyte/pull/73776) | Update dependencies | | 0.0.45 | 2026-02-17 | [73376](https://github.com/airbytehq/airbyte/pull/73376) | Update dependencies | From 51f1939fdf28c59aaa88e09ca27926f1c5a53b48 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:39:16 +0000 Subject: [PATCH 126/379] =?UTF-8?q?deps(source-veeqo):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75711)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-veeqo/metadata.yaml | 4 ++-- docs/integrations/sources/veeqo.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-veeqo/metadata.yaml b/airbyte-integrations/connectors/source-veeqo/metadata.yaml index 2221a63ccfbe..f32402997577 100644 --- a/airbyte-integrations/connectors/source-veeqo/metadata.yaml +++ b/airbyte-integrations/connectors/source-veeqo/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-veeqo connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: ae647c65-da81-4ae5-958a-86490ce53a5e - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-veeqo githubIssueLabel: source-veeqo icon: icon.svg diff --git a/docs/integrations/sources/veeqo.md b/docs/integrations/sources/veeqo.md index d2e397af96ec..7d70d475a8c7 100644 --- a/docs/integrations/sources/veeqo.md +++ b/docs/integrations/sources/veeqo.md @@ -30,6 +30,7 @@ Veeqo Airbyte connector for Veeqo enables seamless data integration between Veeq | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.49 | 2026-03-31 | [75711](https://github.com/airbytehq/airbyte/pull/75711) | Update dependencies | | 0.0.48 | 2026-03-17 | [75057](https://github.com/airbytehq/airbyte/pull/75057) | Update dependencies | | 0.0.47 | 2026-03-10 | [74495](https://github.com/airbytehq/airbyte/pull/74495) | Update dependencies | | 0.0.46 | 2026-02-24 | [72083](https://github.com/airbytehq/airbyte/pull/72083) | Update dependencies | From 67396aa5c51cfbd1207c58c2ba6a706fbb4192ac Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:39:22 +0000 Subject: [PATCH 127/379] =?UTF-8?q?deps(source-launchdarkly):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75710)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-launchdarkly/metadata.yaml | 4 ++-- docs/integrations/sources/launchdarkly.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-launchdarkly/metadata.yaml b/airbyte-integrations/connectors/source-launchdarkly/metadata.yaml index 3aa8006ca306..fd00041cb965 100644 --- a/airbyte-integrations/connectors/source-launchdarkly/metadata.yaml +++ b/airbyte-integrations/connectors/source-launchdarkly/metadata.yaml @@ -6,11 +6,11 @@ data: # Please update to the latest version of the connector base image. # https://hub.docker.com/r/airbyte/python-connector-base # Please use the full address with sha256 hash to guarantee build reproducibility. - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: f96bb511-5e3c-48fc-b408-547953cd81a4 - dockerImageTag: 0.2.48 + dockerImageTag: 0.2.49 dockerRepository: airbyte/source-launchdarkly githubIssueLabel: source-launchdarkly icon: launchdarkly.svg diff --git a/docs/integrations/sources/launchdarkly.md b/docs/integrations/sources/launchdarkly.md index b651366b76a4..c7e75f52f014 100644 --- a/docs/integrations/sources/launchdarkly.md +++ b/docs/integrations/sources/launchdarkly.md @@ -37,6 +37,7 @@ Launchdarkly APIs are under rate limits for the number of API calls allowed per | Version | Date | Pull Request | Subject | | :------ | :--------- | :-------------------------------------------------------- | :--------------------------------------------- | +| 0.2.49 | 2026-03-31 | [75710](https://github.com/airbytehq/airbyte/pull/75710) | Update dependencies | | 0.2.48 | 2026-03-17 | [75008](https://github.com/airbytehq/airbyte/pull/75008) | Update dependencies | | 0.2.47 | 2026-02-24 | [73941](https://github.com/airbytehq/airbyte/pull/73941) | Update dependencies | | 0.2.46 | 2026-02-17 | [73560](https://github.com/airbytehq/airbyte/pull/73560) | Update dependencies | From 2a05f7193f3e9016a38df0cae13a8a106d46fe7f Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:39:29 +0000 Subject: [PATCH 128/379] =?UTF-8?q?deps(source-linkrunner):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75709)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-linkrunner/metadata.yaml | 4 ++-- docs/integrations/sources/linkrunner.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-linkrunner/metadata.yaml b/airbyte-integrations/connectors/source-linkrunner/metadata.yaml index 01a61c32d799..42be6895db04 100644 --- a/airbyte-integrations/connectors/source-linkrunner/metadata.yaml +++ b/airbyte-integrations/connectors/source-linkrunner/metadata.yaml @@ -12,11 +12,11 @@ data: enabled: false packageName: airbyte-source-linkrunner connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: ec739bc6-f8a5-4cb3-9e7b-7e0f8f53ce74 - dockerImageTag: 0.0.3 + dockerImageTag: 0.0.4 dockerRepository: airbyte/source-linkrunner githubIssueLabel: source-linkrunner icon: icon.svg diff --git a/docs/integrations/sources/linkrunner.md b/docs/integrations/sources/linkrunner.md index 784127e1139f..0d040de27c41 100644 --- a/docs/integrations/sources/linkrunner.md +++ b/docs/integrations/sources/linkrunner.md @@ -35,6 +35,7 @@ Linkrunner is a Mobile Measurement Partner (MMP) that helps track user journeys | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.4 | 2026-03-31 | [75709](https://github.com/airbytehq/airbyte/pull/75709) | Update dependencies | | 0.0.3 | 2026-03-17 | [74997](https://github.com/airbytehq/airbyte/pull/74997) | Update dependencies | | 0.0.2 | 2026-03-10 | [74423](https://github.com/airbytehq/airbyte/pull/74423) | Update dependencies | | 0.0.1 | 2026-02-06 | | Initial release by [@ChetanBhosale](https://github.com/ChetanBhosale) via Connector Builder | From b57dfee3e0e6ec526d8af0cc5a3ba2c02ea9db5e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:39:34 +0000 Subject: [PATCH 129/379] =?UTF-8?q?deps(source-vwo):=20=F0=9F=90=99=20upda?= =?UTF-8?q?te=20dependencies=20[2026-03-31]=20(#75708)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-vwo/metadata.yaml | 4 ++-- docs/integrations/sources/vwo.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-vwo/metadata.yaml b/airbyte-integrations/connectors/source-vwo/metadata.yaml index c96687344f08..c529d2703805 100644 --- a/airbyte-integrations/connectors/source-vwo/metadata.yaml +++ b/airbyte-integrations/connectors/source-vwo/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-vwo connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: c739daf4-71c9-4dde-b115-269bcd1b87d6 - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-vwo githubIssueLabel: source-vwo icon: icon.svg diff --git a/docs/integrations/sources/vwo.md b/docs/integrations/sources/vwo.md index bed164726c2a..32f960db6068 100644 --- a/docs/integrations/sources/vwo.md +++ b/docs/integrations/sources/vwo.md @@ -34,6 +34,7 @@ Visit `https://developers.vwo.com/reference/introduction-1` for API documentatio | Version | Date | Pull Request | Subject | | ------------------ | ------------ | --- | ---------------- | +| 0.0.48 | 2026-03-31 | [75708](https://github.com/airbytehq/airbyte/pull/75708) | Update dependencies | | 0.0.47 | 2026-03-17 | [74509](https://github.com/airbytehq/airbyte/pull/74509) | Update dependencies | | 0.0.46 | 2026-03-03 | [72677](https://github.com/airbytehq/airbyte/pull/72677) | Update dependencies | | 0.0.45 | 2026-01-20 | [72049](https://github.com/airbytehq/airbyte/pull/72049) | Update dependencies | From 7bd6f5171d3fdfbc3c55c2693c12ef1c10d5ab5f Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:39:40 +0000 Subject: [PATCH 130/379] =?UTF-8?q?deps(source-greythr):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75706)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-greythr/metadata.yaml | 4 ++-- docs/integrations/sources/greythr.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-greythr/metadata.yaml b/airbyte-integrations/connectors/source-greythr/metadata.yaml index 4e56437d7c9a..212e6b9c06a4 100644 --- a/airbyte-integrations/connectors/source-greythr/metadata.yaml +++ b/airbyte-integrations/connectors/source-greythr/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-greythr connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 1a807325-5a1c-4e0f-a574-841034b1765d - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-greythr githubIssueLabel: source-greythr icon: icon.svg diff --git a/docs/integrations/sources/greythr.md b/docs/integrations/sources/greythr.md index eae45467734f..fbb6bc508672 100644 --- a/docs/integrations/sources/greythr.md +++ b/docs/integrations/sources/greythr.md @@ -32,6 +32,7 @@ The GreytHR Connector for Airbyte allows seamless integration with the GreytHR p | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.49 | 2026-03-31 | [75706](https://github.com/airbytehq/airbyte/pull/75706) | Update dependencies | | 0.0.48 | 2026-03-24 | [75354](https://github.com/airbytehq/airbyte/pull/75354) | Update dependencies | | 0.0.47 | 2026-02-24 | [73965](https://github.com/airbytehq/airbyte/pull/73965) | Update dependencies | | 0.0.46 | 2026-02-10 | [73071](https://github.com/airbytehq/airbyte/pull/73071) | Update dependencies | From a4b3237d369f756d3b1aa6664f347677d04de557 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:39:45 +0000 Subject: [PATCH 131/379] =?UTF-8?q?deps(source-less-annoying-crm):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75705)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-less-annoying-crm/metadata.yaml | 4 ++-- docs/integrations/sources/less-annoying-crm.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-less-annoying-crm/metadata.yaml b/airbyte-integrations/connectors/source-less-annoying-crm/metadata.yaml index e96818ae107a..dd637f247318 100644 --- a/airbyte-integrations/connectors/source-less-annoying-crm/metadata.yaml +++ b/airbyte-integrations/connectors/source-less-annoying-crm/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-less-annoying-crm connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 96f224c5-8e85-4427-b299-dbd5c52de47c - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-less-annoying-crm githubIssueLabel: source-less-annoying-crm icon: icon.svg diff --git a/docs/integrations/sources/less-annoying-crm.md b/docs/integrations/sources/less-annoying-crm.md index 954240fcc2b7..14144ad9b40d 100644 --- a/docs/integrations/sources/less-annoying-crm.md +++ b/docs/integrations/sources/less-annoying-crm.md @@ -27,6 +27,7 @@ Less Annoying CRM connector enables seamless data integration, allowing users t | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.48 | 2026-03-31 | [75705](https://github.com/airbytehq/airbyte/pull/75705) | Update dependencies | | 0.0.47 | 2026-03-24 | [74426](https://github.com/airbytehq/airbyte/pull/74426) | Update dependencies | | 0.0.46 | 2026-02-24 | [73981](https://github.com/airbytehq/airbyte/pull/73981) | Update dependencies | | 0.0.45 | 2026-02-17 | [73555](https://github.com/airbytehq/airbyte/pull/73555) | Update dependencies | From 11136250e87ae5f088215224a430c0a2fa616e5a Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:39:50 +0000 Subject: [PATCH 132/379] =?UTF-8?q?deps(source-google-tasks):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75704)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-google-tasks/metadata.yaml | 4 ++-- docs/integrations/sources/google-tasks.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-google-tasks/metadata.yaml b/airbyte-integrations/connectors/source-google-tasks/metadata.yaml index 3d9f270ebed9..03802143595d 100644 --- a/airbyte-integrations/connectors/source-google-tasks/metadata.yaml +++ b/airbyte-integrations/connectors/source-google-tasks/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-google-tasks connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 751c2519-1446-416e-9736-9b98585f8125 - dockerImageTag: 0.0.51 + dockerImageTag: 0.0.52 dockerRepository: airbyte/source-google-tasks githubIssueLabel: source-google-tasks icon: icon.svg diff --git a/docs/integrations/sources/google-tasks.md b/docs/integrations/sources/google-tasks.md index a9bf5a54cc9f..7f8743e7b2a1 100644 --- a/docs/integrations/sources/google-tasks.md +++ b/docs/integrations/sources/google-tasks.md @@ -43,6 +43,7 @@ Steps: | Version | Date | Pull Request | Subject | | ------------------ | ------------ | --- | ---------------- | +| 0.0.52 | 2026-03-31 | [75704](https://github.com/airbytehq/airbyte/pull/75704) | Update dependencies | | 0.0.51 | 2026-03-24 | [75356](https://github.com/airbytehq/airbyte/pull/75356) | Update dependencies | | 0.0.50 | 2026-03-10 | [74679](https://github.com/airbytehq/airbyte/pull/74679) | Update dependencies | | 0.0.49 | 2026-03-03 | [74168](https://github.com/airbytehq/airbyte/pull/74168) | Update dependencies | From 501029dd0787924ad21a4b04ee6324a0a786c6df Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:39:55 +0000 Subject: [PATCH 133/379] =?UTF-8?q?deps(source-uptick):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75703)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-uptick/metadata.yaml | 4 ++-- docs/integrations/sources/uptick.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-uptick/metadata.yaml b/airbyte-integrations/connectors/source-uptick/metadata.yaml index f3349da90671..d2a9b1ffe25b 100644 --- a/airbyte-integrations/connectors/source-uptick/metadata.yaml +++ b/airbyte-integrations/connectors/source-uptick/metadata.yaml @@ -13,7 +13,7 @@ data: enabled: false packageName: airbyte-source-uptick connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorTestSuitesOptions: - suite: unitTests - suite: integrationTests @@ -33,7 +33,7 @@ data: connectorSubtype: api connectorType: source definitionId: 54c75c42-df4a-4f3e-a5f3-d50cf80f1649 - dockerImageTag: 0.5.6 + dockerImageTag: 0.5.7 dockerRepository: airbyte/source-uptick githubIssueLabel: source-uptick icon: icon.svg diff --git a/docs/integrations/sources/uptick.md b/docs/integrations/sources/uptick.md index 4a0ad9bf95be..1957962d5b4f 100644 --- a/docs/integrations/sources/uptick.md +++ b/docs/integrations/sources/uptick.md @@ -157,6 +157,7 @@ The Uptick connector syncs data from the following streams, organized by functio | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.5.7 | 2026-03-31 | [75703](https://github.com/airbytehq/airbyte/pull/75703) | Update dependencies | | 0.5.6 | 2026-03-17 | [75044](https://github.com/airbytehq/airbyte/pull/75044) | Update dependencies | | 0.5.5 | 2026-03-10 | [74493](https://github.com/airbytehq/airbyte/pull/74493) | Update dependencies | | 0.5.4 | 2026-02-24 | [73926](https://github.com/airbytehq/airbyte/pull/73926) | Update dependencies | From 7530833d5a3ef4b95dc283905d6ce70294baa800 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:40:02 +0000 Subject: [PATCH 134/379] =?UTF-8?q?deps(source-vercel):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75702)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-vercel/metadata.yaml | 4 ++-- docs/integrations/sources/vercel.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-vercel/metadata.yaml b/airbyte-integrations/connectors/source-vercel/metadata.yaml index f20c27183f43..f80d72ffc2d8 100644 --- a/airbyte-integrations/connectors/source-vercel/metadata.yaml +++ b/airbyte-integrations/connectors/source-vercel/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-vercel connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 7de74599-7bbe-4610-8635-00c76885e51d - dockerImageTag: 0.0.49 + dockerImageTag: 0.0.50 dockerRepository: airbyte/source-vercel githubIssueLabel: source-vercel icon: icon.svg diff --git a/docs/integrations/sources/vercel.md b/docs/integrations/sources/vercel.md index c5e9e3714e06..078256df685b 100644 --- a/docs/integrations/sources/vercel.md +++ b/docs/integrations/sources/vercel.md @@ -28,6 +28,7 @@ | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.50 | 2026-03-31 | [75702](https://github.com/airbytehq/airbyte/pull/75702) | Update dependencies | | 0.0.49 | 2026-03-24 | [75322](https://github.com/airbytehq/airbyte/pull/75322) | Update dependencies | | 0.0.48 | 2026-03-10 | [74486](https://github.com/airbytehq/airbyte/pull/74486) | Update dependencies | | 0.0.47 | 2026-02-24 | [73902](https://github.com/airbytehq/airbyte/pull/73902) | Update dependencies | From 9476abda44929835abc22ecd30a9db28c8b88793 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:40:09 +0000 Subject: [PATCH 135/379] =?UTF-8?q?deps(source-hoorayhr):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75701)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-hoorayhr/metadata.yaml | 4 ++-- docs/integrations/sources/hoorayhr.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-hoorayhr/metadata.yaml b/airbyte-integrations/connectors/source-hoorayhr/metadata.yaml index ce337df26144..9f249c499735 100644 --- a/airbyte-integrations/connectors/source-hoorayhr/metadata.yaml +++ b/airbyte-integrations/connectors/source-hoorayhr/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-hoorayhr connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: a2e34f7c-7de1-422c-b909-ce12f3e051af - dockerImageTag: 0.1.44 + dockerImageTag: 0.1.45 dockerRepository: airbyte/source-hoorayhr githubIssueLabel: source-hoorayhr icon: icon.svg diff --git a/docs/integrations/sources/hoorayhr.md b/docs/integrations/sources/hoorayhr.md index 833ef94e6cd2..7c258571b511 100644 --- a/docs/integrations/sources/hoorayhr.md +++ b/docs/integrations/sources/hoorayhr.md @@ -27,6 +27,7 @@ Use the credentials of your HoorayHR account to configure the connector. Make su | Version | Date | Pull Request | Subject | | ------- | ---------- | ------------ | --------------------------------------------------------------------------------------------------- | +| 0.1.45 | 2026-03-31 | [75701](https://github.com/airbytehq/airbyte/pull/75701) | Update dependencies | | 0.1.44 | 2026-03-17 | [74521](https://github.com/airbytehq/airbyte/pull/74521) | Update dependencies | | 0.1.43 | 2026-02-24 | [73903](https://github.com/airbytehq/airbyte/pull/73903) | Update dependencies | | 0.1.42 | 2026-02-17 | [73379](https://github.com/airbytehq/airbyte/pull/73379) | Update dependencies | From 6ec4b209bb8d5cbd7ead277124521e05370d187e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:40:14 +0000 Subject: [PATCH 136/379] =?UTF-8?q?deps(source-keka):=20=F0=9F=90=99=20upd?= =?UTF-8?q?ate=20dependencies=20[2026-03-31]=20(#75700)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-keka/metadata.yaml | 4 ++-- docs/integrations/sources/keka.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-keka/metadata.yaml b/airbyte-integrations/connectors/source-keka/metadata.yaml index 1dcd7a21c17d..4da1d8a0b3bc 100644 --- a/airbyte-integrations/connectors/source-keka/metadata.yaml +++ b/airbyte-integrations/connectors/source-keka/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-keka connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 54664ae8-39aa-467f-9703-9b343ee23b9b - dockerImageTag: 0.0.37 + dockerImageTag: 0.0.38 dockerRepository: airbyte/source-keka githubIssueLabel: source-keka icon: icon.svg diff --git a/docs/integrations/sources/keka.md b/docs/integrations/sources/keka.md index a3a9e9a501c4..322278f7c9c6 100644 --- a/docs/integrations/sources/keka.md +++ b/docs/integrations/sources/keka.md @@ -29,6 +29,7 @@ The Keka Connector for Airbyte allows seamless integration with the Keka platfor | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.38 | 2026-03-31 | [75700](https://github.com/airbytehq/airbyte/pull/75700) | Update dependencies | | 0.0.37 | 2026-03-24 | [74439](https://github.com/airbytehq/airbyte/pull/74439) | Update dependencies | | 0.0.36 | 2026-03-03 | [74235](https://github.com/airbytehq/airbyte/pull/74235) | Update dependencies | | 0.0.35 | 2026-02-17 | [73542](https://github.com/airbytehq/airbyte/pull/73542) | Update dependencies | From db0bdb31352f56293a4f135735c4d2b1ecf13d0e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:40:20 +0000 Subject: [PATCH 137/379] =?UTF-8?q?deps(source-google-search-console):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75699)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-google-search-console/metadata.yaml | 4 ++-- docs/integrations/sources/google-search-console.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-google-search-console/metadata.yaml b/airbyte-integrations/connectors/source-google-search-console/metadata.yaml index 00bfe7142b39..b7f08663589a 100644 --- a/airbyte-integrations/connectors/source-google-search-console/metadata.yaml +++ b/airbyte-integrations/connectors/source-google-search-console/metadata.yaml @@ -6,11 +6,11 @@ data: hosts: - "*.googleapis.com" connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: eb4c9e00-db83-4d63-a386-39cfa91012a8 - dockerImageTag: 1.10.27 + dockerImageTag: 1.10.28 dockerRepository: airbyte/source-google-search-console documentationUrl: https://docs.airbyte.com/integrations/sources/google-search-console externalDocumentationUrls: diff --git a/docs/integrations/sources/google-search-console.md b/docs/integrations/sources/google-search-console.md index 331126661b25..85735949331b 100644 --- a/docs/integrations/sources/google-search-console.md +++ b/docs/integrations/sources/google-search-console.md @@ -244,6 +244,7 @@ Google Search Console only retains data for websites from the last 16 months. An | Version | Date | Pull Request | Subject | |:------------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 1.10.28 | 2026-03-31 | [75699](https://github.com/airbytehq/airbyte/pull/75699) | Update dependencies | | 1.10.27 | 2026-03-30 | [75426](https://github.com/airbytehq/airbyte/pull/75426) | Guard numeric metric fields against complex types to prevent serialization failures and deadlocks | | 1.10.26 | 2026-03-24 | [74935](https://github.com/airbytehq/airbyte/pull/74935) | Update dependencies | | 1.10.25 | 2026-03-10 | [74685](https://github.com/airbytehq/airbyte/pull/74685) | Update dependencies | From 6132c22a91e44ab3ab610c646573cdb31312888b Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:40:26 +0000 Subject: [PATCH 138/379] =?UTF-8?q?deps(source-ubidots):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75698)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-ubidots/metadata.yaml | 4 ++-- docs/integrations/sources/ubidots.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-ubidots/metadata.yaml b/airbyte-integrations/connectors/source-ubidots/metadata.yaml index c966affe6919..7a6392387088 100644 --- a/airbyte-integrations/connectors/source-ubidots/metadata.yaml +++ b/airbyte-integrations/connectors/source-ubidots/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-ubidots connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 8614fab8-aa3e-4dbe-8728-6d6c8a1d3514 - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-ubidots githubIssueLabel: source-ubidots icon: icon.svg diff --git a/docs/integrations/sources/ubidots.md b/docs/integrations/sources/ubidots.md index c9e81fe2c347..38196afb99c3 100644 --- a/docs/integrations/sources/ubidots.md +++ b/docs/integrations/sources/ubidots.md @@ -24,6 +24,7 @@ The Ubidots Connector facilitates easy integration with the Ubidots IoT platform | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.49 | 2026-03-31 | [75698](https://github.com/airbytehq/airbyte/pull/75698) | Update dependencies | | 0.0.48 | 2026-03-17 | [74510](https://github.com/airbytehq/airbyte/pull/74510) | Update dependencies | | 0.0.47 | 2026-02-24 | [73915](https://github.com/airbytehq/airbyte/pull/73915) | Update dependencies | | 0.0.46 | 2026-02-10 | [73004](https://github.com/airbytehq/airbyte/pull/73004) | Update dependencies | From 8ba20ff0631969ca331af0b1fee9ac6b7ffe3502 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:40:32 +0000 Subject: [PATCH 139/379] =?UTF-8?q?deps(source-twelve-data):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75697)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-twelve-data/metadata.yaml | 4 ++-- docs/integrations/sources/twelve-data.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-twelve-data/metadata.yaml b/airbyte-integrations/connectors/source-twelve-data/metadata.yaml index fd0d04dd3553..86b54c5efa23 100644 --- a/airbyte-integrations/connectors/source-twelve-data/metadata.yaml +++ b/airbyte-integrations/connectors/source-twelve-data/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-twelve-data connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 162f084d-3a9f-42c0-8785-81aa18abf339 - dockerImageTag: 0.0.49 + dockerImageTag: 0.0.50 dockerRepository: airbyte/source-twelve-data githubIssueLabel: source-twelve-data icon: icon.svg diff --git a/docs/integrations/sources/twelve-data.md b/docs/integrations/sources/twelve-data.md index e94fbdb48473..dec338f56c94 100644 --- a/docs/integrations/sources/twelve-data.md +++ b/docs/integrations/sources/twelve-data.md @@ -44,6 +44,7 @@ Docs : https://twelvedata.com/docs | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.50 | 2026-03-31 | [75697](https://github.com/airbytehq/airbyte/pull/75697) | Update dependencies | | 0.0.49 | 2026-03-17 | [75049](https://github.com/airbytehq/airbyte/pull/75049) | Update dependencies | | 0.0.48 | 2026-02-24 | [73887](https://github.com/airbytehq/airbyte/pull/73887) | Update dependencies | | 0.0.47 | 2026-02-17 | [73525](https://github.com/airbytehq/airbyte/pull/73525) | Update dependencies | From 704eaf96815d503609f8781816eed5d9639eb8a7 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:40:40 +0000 Subject: [PATCH 140/379] =?UTF-8?q?deps(source-ip2whois):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75695)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> From 668cbcec454b5397f9f525aa23b15de949469abf Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:40:45 +0000 Subject: [PATCH 141/379] =?UTF-8?q?deps(source-campaign-monitor):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75694)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> From 7dcb681c320bf8718b77628e53182798980e1ef9 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:40:51 +0000 Subject: [PATCH 142/379] =?UTF-8?q?deps(source-jotform):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75693)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> From 94735f9eb59b4af0d4fa7551bdab697b04435dde Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:40:55 +0000 Subject: [PATCH 143/379] =?UTF-8?q?deps(source-capsule-crm):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75692)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> From c03096f9737a02642da2b61a0a67e13ccf1e8681 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:41:01 +0000 Subject: [PATCH 144/379] =?UTF-8?q?deps(source-gcs):=20=F0=9F=90=99=20upda?= =?UTF-8?q?te=20dependencies=20[2026-03-31]=20(#75690)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-gcs/metadata.yaml | 2 +- .../connectors/source-gcs/poetry.lock | 766 +++++++++--------- .../connectors/source-gcs/pyproject.toml | 2 +- docs/integrations/sources/gcs.md | 1 + 4 files changed, 386 insertions(+), 385 deletions(-) diff --git a/airbyte-integrations/connectors/source-gcs/metadata.yaml b/airbyte-integrations/connectors/source-gcs/metadata.yaml index 0e6001145364..453ad110f929 100644 --- a/airbyte-integrations/connectors/source-gcs/metadata.yaml +++ b/airbyte-integrations/connectors/source-gcs/metadata.yaml @@ -11,7 +11,7 @@ data: connectorSubtype: file connectorType: source definitionId: 2a8c41ae-8c23-4be0-a73f-2ab10ca1a820 - dockerImageTag: 0.10.10 + dockerImageTag: 0.10.11 dockerRepository: airbyte/source-gcs documentationUrl: https://docs.airbyte.com/integrations/sources/gcs githubIssueLabel: source-gcs diff --git a/airbyte-integrations/connectors/source-gcs/poetry.lock b/airbyte-integrations/connectors/source-gcs/poetry.lock index 4277a96c17a4..5fcbd0d6543a 100644 --- a/airbyte-integrations/connectors/source-gcs/poetry.lock +++ b/airbyte-integrations/connectors/source-gcs/poetry.lock @@ -2,13 +2,13 @@ [[package]] name = "airbyte-cdk" -version = "7.13.0" +version = "7.14.0" description = "A framework for writing Airbyte Connectors." optional = false python-versions = "<3.14,>=3.10" files = [ - {file = "airbyte_cdk-7.13.0-py3-none-any.whl", hash = "sha256:ede4018f0ce912102a7698daa6e1a793e0c8cd3f8c3456429d038951cca3a339"}, - {file = "airbyte_cdk-7.13.0.tar.gz", hash = "sha256:2b6cea3862509ab095beb19524dae78e2b24f3b356891e0a1e24f8854d8c124e"}, + {file = "airbyte_cdk-7.14.0-py3-none-any.whl", hash = "sha256:306d48d03eaf3c2a5ac46a806bc9b45c90fb1e36f57d6029e5b9e13c508a82c8"}, + {file = "airbyte_cdk-7.14.0.tar.gz", hash = "sha256:19948896aac82b1d47500742e2d1f3fb529984bdad07d484e38c49c9d56ace0a"}, ] [package.dependencies] @@ -344,43 +344,43 @@ pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} [[package]] name = "chardet" -version = "7.3.0" +version = "7.4.0.post2" description = "Universal character encoding detector" optional = false python-versions = ">=3.10" files = [ - {file = "chardet-7.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:015f9d697f796a5bb0ac4d19e0108fd6cc84d141521089d0385d2a00c5f5d74e"}, - {file = "chardet-7.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e464c2ec0be69ab6d5792c1acf354001b34e201efa2bee60ff4f7ded0e23f6a8"}, - {file = "chardet-7.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c296044993dab62281176c07d0ca2b6e865044e38944d3f6e4ad661e222f4db8"}, - {file = "chardet-7.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b69fd9685a7aada6e236a50bb93b51bd4fc08d29d1029492e64823a69c015f46"}, - {file = "chardet-7.3.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c88c464b5b65859984386c698b43ccfe88e96814f80433c2d5fdf40dc4b68bcb"}, - {file = "chardet-7.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:5dbfbaef7de55aee008de9b886a63e60e916016507ed7845c9b7bfe1357f4f54"}, - {file = "chardet-7.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b58eb6d6dea67fc3b578dd956dd6e92aafea383aa559ccea55265554ff062a3"}, - {file = "chardet-7.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:811029a7cf397ed32441aa134475f7047826fba496047a6afd7bba1da7fc4ab7"}, - {file = "chardet-7.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fef009cdb37225b1f6259ddc18c3017cd1edddd85d57823f1c46c53503da41a1"}, - {file = "chardet-7.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90a6249a455b8ecdb207a9f5a5eb46e1c21f2173eacb5e1603def61ed4784303"}, - {file = "chardet-7.3.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7193bcca96ffd87a7d6695056d3e875707b25eda588957756dd5c95d125fcb89"}, - {file = "chardet-7.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:ff4d81f5561f2382343dc922e533c017d52bc55125e50551c18034fffcdbd0cb"}, - {file = "chardet-7.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:04ef4b65c18afb298ac7c1326fbd83e1524250ceb7e61df67115a4a48e9e8e0e"}, - {file = "chardet-7.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7ed513fb0b35ebf663bd4f8be2d61af701202e98f77e6d8301d1a2c7d0f2985d"}, - {file = "chardet-7.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7ccec08ee572dfd7a9486835ceba06ef88fa3e15deb1b76130b5ba6012fbb0c0"}, - {file = "chardet-7.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e912948f27c0124da8ce8fcd5ed8fe3b5e06fe8c0ecb66dd95180edf1122a6c"}, - {file = "chardet-7.3.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7f3758c122aebb411eac37452c5774c56a5500147e1c24af0d460cb0d748fb48"}, - {file = "chardet-7.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:5276bc68736cf6d530ca2dc4ea1c2101d2b50015b09d48242615cc3818623574"}, - {file = "chardet-7.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:51a0ad2031bd10d24357d7e52de68abe29efb62b7aedf1bd9d1c593fd438cec5"}, - {file = "chardet-7.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:23d264962f680deec691308cc753685b4c5a69798a26e00ce4f4cf96d2e43fcb"}, - {file = "chardet-7.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:963e6cac79e3a4fc51c8517b8df03b3467550dd00d53e775059dce6e2fc0d0ca"}, - {file = "chardet-7.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:622206fdb0d274766559fa172e2d680d58cc5fc6a67015c21c36fec500e7bd50"}, - {file = "chardet-7.3.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:58388f412a76d1449c6ce4631edbd1b0087385ff00b6fb1f521879d8e8d99484"}, - {file = "chardet-7.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:340f4eccafa17cfc5a90af1fb8558dc791156f815f8d800d8ac2b1b9fb2b8103"}, - {file = "chardet-7.3.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:8267de33ade8a496cb441eb86dd08c803043870a66b4f55aa44c02e1dbdbf93e"}, - {file = "chardet-7.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f4ea1f94f17fce29600e1661f773048ee9ed90a9300f1226018987f7d5961019"}, - {file = "chardet-7.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:920b91e9436c4d546862143313f48d4e6e0dd8510114ae0c5b194ff8c878a6c8"}, - {file = "chardet-7.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:80139a006a598e2db83fe6eaf7ac29c2a30cc5d10f255a89a9c6b9c04f81d67f"}, - {file = "chardet-7.3.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:328a79efb197d6e9460ce33ebb8002a0bf85faa123d56aa1f75c21696ee70070"}, - {file = "chardet-7.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:aab48b166f8aa8b086c93147ed6427376b8db2d783aff3f787c1c0819f6486bb"}, - {file = "chardet-7.3.0-py3-none-any.whl", hash = "sha256:dc4726af6ee00ee386293c34d86ba1fe18e0bd70a74612f1486da217d6a01249"}, - {file = "chardet-7.3.0.tar.gz", hash = "sha256:e6bf602bb8a070524a19bac1cff2a10d62c71b09606f066251282870fa1466e5"}, + {file = "chardet-7.4.0.post2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:77170d229f3d7babbc36c5a33c361de1c01091f4564a33bcd7e0f59ee8609b2a"}, + {file = "chardet-7.4.0.post2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9be8a6ba814f65013e0e6d92a43e8fa50f42c8850c143fa74586baeac5fa1bcd"}, + {file = "chardet-7.4.0.post2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:28807a1209b7c2b79b24bdf9722b381e81da8104ae17fe2bd1e9f01c87fe9071"}, + {file = "chardet-7.4.0.post2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6ade174e3fe29f1f4abdb3cc47add0a98201452c43786cbf324b5e237a0c79fc"}, + {file = "chardet-7.4.0.post2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:335d9cedd5b5be4b8b39ec25b1c2e4498ac4e8658c9466b68b4417cf07c8c4ee"}, + {file = "chardet-7.4.0.post2-cp310-cp310-win_amd64.whl", hash = "sha256:cde31d2314b156404380aca8aa0bdf6395bc92998b25336076b8a588c267fb20"}, + {file = "chardet-7.4.0.post2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:90227bc83d06d16b548afe185e93eff8c740cb11ec51536366399b912e361b8d"}, + {file = "chardet-7.4.0.post2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:18cb15facd3a70042cb4d3b9a80dd2e9b8d78af90643f434047060e1f84dff06"}, + {file = "chardet-7.4.0.post2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e719bf17854051970938e260d2c589fe3fde3da0a681acdafd266e3bbf75c1af"}, + {file = "chardet-7.4.0.post2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24b8fcc1fe54936932f305522bc2f40a207ecbb38209fa24226eab7432531aef"}, + {file = "chardet-7.4.0.post2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2c748b2850c8376ef04b02b3f22e014da5edc961478c88ccc6b01d3eed9bc1e7"}, + {file = "chardet-7.4.0.post2-cp311-cp311-win_amd64.whl", hash = "sha256:a359eb4535aeabd3f61e599530c4c4d4855c31316e6fed7db619a9c58785ee38"}, + {file = "chardet-7.4.0.post2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7aced16fe8098019c7c513dd92e9ee3ad29fffac757fa7de13ff8f3a8607a344"}, + {file = "chardet-7.4.0.post2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dc6829803ba71cb427dffac03a948ae828c617710bbd5f97ae3b34ab18558414"}, + {file = "chardet-7.4.0.post2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:46659d38ba18e7c740f10a4c2edd0ef112e0322606ab2570cb8fd387954e0de9"}, + {file = "chardet-7.4.0.post2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5933289313b8cbfb0d07cf44583a2a6c7e31bffe5dcb7ebb6592825aa197d5b0"}, + {file = "chardet-7.4.0.post2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2b99b417fac30641429829666ee7331366e797863504260aa1b18bfc2020e4e3"}, + {file = "chardet-7.4.0.post2-cp312-cp312-win_amd64.whl", hash = "sha256:a07dc1257fef2685dfc5182229abccd3f9b1299006a5b4d43ac7bd252faa1118"}, + {file = "chardet-7.4.0.post2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9bdb9387e692dd53c837aa922f676e5ab51209895cd99b15d30c6004418e0d27"}, + {file = "chardet-7.4.0.post2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:422ac637f5a2a8b13151245591cb0fabdf9ec1427725f0560628cb5ad4fb1462"}, + {file = "chardet-7.4.0.post2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7d52b3f15249ba877030045900d179d44552c3c37dda487462be473ec67bed2f"}, + {file = "chardet-7.4.0.post2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccdfb13b4a727d3d944157c7f350c6d64630511a0ce39e37ffa5114e90f7d3a7"}, + {file = "chardet-7.4.0.post2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:daae5b0579e7e33adacb4722a62b540e6bec49944e081a859cb9a6a010713817"}, + {file = "chardet-7.4.0.post2-cp313-cp313-win_amd64.whl", hash = "sha256:6c448fe2d77e329cec421b95f844b75f8c9cb744e808ecc9124b6063ca6acb5e"}, + {file = "chardet-7.4.0.post2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:5862b17677f7e8fcee4e37fe641f01d30762e4b075ac37ce9584e4407896e2d9"}, + {file = "chardet-7.4.0.post2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:22d05c4b7e721d5330d99ef4a6f6233a9de58ae6f2275c21a098bedd778a6cb7"}, + {file = "chardet-7.4.0.post2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a035d407f762c21eb77069982425eb403e518dd758617aa43bf11d0d2203a1b6"}, + {file = "chardet-7.4.0.post2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2adfa7390e69cb5ed499b54978d31f6d476788d07d83da3426811181b7ca7682"}, + {file = "chardet-7.4.0.post2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2345f20ea67cdadddb778b2bc31e2defc2a85ae027931f9ad6ab84fd5d345320"}, + {file = "chardet-7.4.0.post2-cp314-cp314-win_amd64.whl", hash = "sha256:52602972d4815047cee262551bc383ab394aa145f5ca9ee10d0a53d27965882e"}, + {file = "chardet-7.4.0.post2-py3-none-any.whl", hash = "sha256:e0c9c6b5c296c0e5197bc8876fcc04d58a6ddfba18399e598ba353aba28b038e"}, + {file = "chardet-7.4.0.post2.tar.gz", hash = "sha256:21a6b5ca695252c03385dcfcc8b55c27907f1fe80838aa171b1ff4e356a1bb67"}, ] [[package]] @@ -767,13 +767,13 @@ typing-inspect = ">=0.4.0,<1" [[package]] name = "dateparser" -version = "1.3.0" +version = "1.4.0" description = "Date parsing library designed to parse dates from HTML pages" optional = false python-versions = ">=3.10" files = [ - {file = "dateparser-1.3.0-py3-none-any.whl", hash = "sha256:8dc678b0a526e103379f02ae44337d424bd366aac727d3c6cf52ce1b01efbb5a"}, - {file = "dateparser-1.3.0.tar.gz", hash = "sha256:5bccf5d1ec6785e5be71cc7ec80f014575a09b4923e762f850e57443bddbf1a5"}, + {file = "dateparser-1.4.0-py3-none-any.whl", hash = "sha256:7902b8e85d603494bf70a5a0b1decdddb2270b9c6e6b2bc8a57b93476c0df378"}, + {file = "dateparser-1.4.0.tar.gz", hash = "sha256:97a21840d5ecdf7630c584f673338a5afac5dfe84f647baf4d7e8df98f9354a4"}, ] [package.dependencies] @@ -961,18 +961,18 @@ files = [ [[package]] name = "google-api-core" -version = "2.30.0" +version = "2.30.1" description = "Google API client core library" optional = false python-versions = ">=3.9" files = [ - {file = "google_api_core-2.30.0-py3-none-any.whl", hash = "sha256:80be49ee937ff9aba0fd79a6eddfde35fe658b9953ab9b79c57dd7061afa8df5"}, - {file = "google_api_core-2.30.0.tar.gz", hash = "sha256:02edfa9fab31e17fc0befb5f161b3bf93c9096d99aed584625f38065c511ad9b"}, + {file = "google_api_core-2.30.1-py3-none-any.whl", hash = "sha256:3be893babbb54a89c6807b598383ddf212112130e3d24d06c681b5d18f082e08"}, + {file = "google_api_core-2.30.1.tar.gz", hash = "sha256:7304ef3bd7e77fd26320a36eeb75868f9339532bfea21694964f4765b37574ee"}, ] [package.dependencies] google-auth = ">=2.14.1,<3.0.0" -googleapis-common-protos = ">=1.56.3,<2.0.0" +googleapis-common-protos = ">=1.63.2,<2.0.0" grpcio = [ {version = ">=1.49.1,<2.0.0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, {version = ">=1.33.2,<2.0.0", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, @@ -1021,35 +1021,35 @@ urllib3 = ["packaging", "urllib3"] [[package]] name = "google-cloud-core" -version = "2.5.0" +version = "2.5.1" description = "Google Cloud API client core library" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "google_cloud_core-2.5.0-py3-none-any.whl", hash = "sha256:67d977b41ae6c7211ee830c7912e41003ea8194bff15ae7d72fd6f51e57acabc"}, - {file = "google_cloud_core-2.5.0.tar.gz", hash = "sha256:7c1b7ef5c92311717bd05301aa1a91ffbc565673d3b0b4163a52d8413a186963"}, + {file = "google_cloud_core-2.5.1-py3-none-any.whl", hash = "sha256:ea62cdf502c20e3e14be8a32c05ed02113d7bef454e40ff3fab6fe1ec9f1f4e7"}, + {file = "google_cloud_core-2.5.1.tar.gz", hash = "sha256:3dc94bdec9d05a31d9f355045ed0f369fbc0d8c665076c734f065d729800f811"}, ] [package.dependencies] -google-api-core = ">=1.31.6,<2.0.dev0 || >2.3.0,<3.0.0" -google-auth = ">=1.25.0,<3.0.0" +google-api-core = ">=2.11.0,<3.0.0" +google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0" [package.extras] grpc = ["grpcio (>=1.38.0,<2.0.0)", "grpcio (>=1.75.1,<2.0.0)", "grpcio-status (>=1.38.0,<2.0.0)"] [[package]] name = "google-cloud-secret-manager" -version = "2.26.0" +version = "2.27.0" description = "Google Cloud Secret Manager API client library" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "google_cloud_secret_manager-2.26.0-py3-none-any.whl", hash = "sha256:940a5447a6ec9951446fd1a0f22c81a4303fde164cd747aae152c5f5c8e6723e"}, - {file = "google_cloud_secret_manager-2.26.0.tar.gz", hash = "sha256:0d1d6f76327685a0ed78a4cf50f289e1bfbbe56026ed0affa98663b86d6d50d6"}, + {file = "google_cloud_secret_manager-2.27.0-py3-none-any.whl", hash = "sha256:e5540bece65a3ad720146f3b438973faf9315109b3ffa012a58711843047a3dc"}, + {file = "google_cloud_secret_manager-2.27.0.tar.gz", hash = "sha256:6af864c252bd3c11db7bb02b80cb0b14a8c9a33fc7ec4d6f245f33d8ce1f7cd1"}, ] [package.dependencies] -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0", extras = ["grpc"]} +google-api-core = {version = ">=2.11.0,<3.0.0", extras = ["grpc"]} google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0" grpc-google-iam-v1 = ">=0.14.0,<1.0.0" grpcio = ">=1.33.2,<2.0.0" @@ -1057,7 +1057,7 @@ proto-plus = [ {version = ">=1.25.0,<2.0.0", markers = "python_version >= \"3.13\""}, {version = ">=1.22.3,<2.0.0", markers = "python_version < \"3.13\""}, ] -protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0" +protobuf = ">=4.25.8,<8.0.0" [[package]] name = "google-cloud-storage" @@ -1125,13 +1125,13 @@ files = [ [[package]] name = "google-resumable-media" -version = "2.8.0" +version = "2.8.2" description = "Utilities for Google Media Downloads and Resumable Uploads" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "google_resumable_media-2.8.0-py3-none-any.whl", hash = "sha256:dd14a116af303845a8d932ddae161a26e86cc229645bc98b39f026f9b1717582"}, - {file = "google_resumable_media-2.8.0.tar.gz", hash = "sha256:f1157ed8b46994d60a1bc432544db62352043113684d4e030ee02e77ebe9a1ae"}, + {file = "google_resumable_media-2.8.2-py3-none-any.whl", hash = "sha256:82b6d8ccd11765268cdd2a2123f417ec806b8eef3000a9a38dfe3033da5fb220"}, + {file = "google_resumable_media-2.8.2.tar.gz", hash = "sha256:f3354a182ebd193ae3f42e3ef95e6c9b10f128320de23ac7637236713b1acd70"}, ] [package.dependencies] @@ -1143,18 +1143,18 @@ requests = ["requests (>=2.18.0,<3.0.0)"] [[package]] name = "googleapis-common-protos" -version = "1.73.0" +version = "1.73.1" description = "Common protobufs used in Google APIs" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "googleapis_common_protos-1.73.0-py3-none-any.whl", hash = "sha256:dfdaaa2e860f242046be561e6d6cb5c5f1541ae02cfbcb034371aadb2942b4e8"}, - {file = "googleapis_common_protos-1.73.0.tar.gz", hash = "sha256:778d07cd4fbeff84c6f7c72102f0daf98fa2bfd3fa8bea426edc545588da0b5a"}, + {file = "googleapis_common_protos-1.73.1-py3-none-any.whl", hash = "sha256:e51f09eb0a43a8602f5a915870972e6b4a394088415c79d79605a46d8e826ee8"}, + {file = "googleapis_common_protos-1.73.1.tar.gz", hash = "sha256:13114f0e9d2391756a0194c3a8131974ed7bffb06086569ba193364af59163b6"}, ] [package.dependencies] grpcio = {version = ">=1.44.0,<2.0.0", optional = true, markers = "extra == \"grpc\""} -protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0" +protobuf = ">=4.25.8,<8.0.0" [package.extras] grpc = ["grpcio (>=1.44.0,<2.0.0)"] @@ -1177,94 +1177,94 @@ protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4 [[package]] name = "grpcio" -version = "1.78.0" +version = "1.80.0" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.9" files = [ - {file = "grpcio-1.78.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:7cc47943d524ee0096f973e1081cb8f4f17a4615f2116882a5f1416e4cfe92b5"}, - {file = "grpcio-1.78.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:c3f293fdc675ccba4db5a561048cca627b5e7bd1c8a6973ffedabe7d116e22e2"}, - {file = "grpcio-1.78.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:10a9a644b5dd5aec3b82b5b0b90d41c0fa94c85ef42cb42cf78a23291ddb5e7d"}, - {file = "grpcio-1.78.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4c5533d03a6cbd7f56acfc9cfb44ea64f63d29091e40e44010d34178d392d7eb"}, - {file = "grpcio-1.78.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ff870aebe9a93a85283837801d35cd5f8814fe2ad01e606861a7fb47c762a2b7"}, - {file = "grpcio-1.78.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:391e93548644e6b2726f1bb84ed60048d4bcc424ce5e4af0843d28ca0b754fec"}, - {file = "grpcio-1.78.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:df2c8f3141f7cbd112a6ebbd760290b5849cda01884554f7c67acc14e7b1758a"}, - {file = "grpcio-1.78.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd8cb8026e5f5b50498a3c4f196f57f9db344dad829ffae16b82e4fdbaea2813"}, - {file = "grpcio-1.78.0-cp310-cp310-win32.whl", hash = "sha256:f8dff3d9777e5d2703a962ee5c286c239bf0ba173877cc68dc02c17d042e29de"}, - {file = "grpcio-1.78.0-cp310-cp310-win_amd64.whl", hash = "sha256:94f95cf5d532d0e717eed4fc1810e8e6eded04621342ec54c89a7c2f14b581bf"}, - {file = "grpcio-1.78.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:2777b783f6c13b92bd7b716667452c329eefd646bfb3f2e9dabea2e05dbd34f6"}, - {file = "grpcio-1.78.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:9dca934f24c732750389ce49d638069c3892ad065df86cb465b3fa3012b70c9e"}, - {file = "grpcio-1.78.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:459ab414b35f4496138d0ecd735fed26f1318af5e52cb1efbc82a09f0d5aa911"}, - {file = "grpcio-1.78.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:082653eecbdf290e6e3e2c276ab2c54b9e7c299e07f4221872380312d8cf395e"}, - {file = "grpcio-1.78.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85f93781028ec63f383f6bc90db785a016319c561cc11151fbb7b34e0d012303"}, - {file = "grpcio-1.78.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f12857d24d98441af6a1d5c87442d624411db486f7ba12550b07788f74b67b04"}, - {file = "grpcio-1.78.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5397fff416b79e4b284959642a4e95ac4b0f1ece82c9993658e0e477d40551ec"}, - {file = "grpcio-1.78.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fbe6e89c7ffb48518384068321621b2a69cab509f58e40e4399fdd378fa6d074"}, - {file = "grpcio-1.78.0-cp311-cp311-win32.whl", hash = "sha256:6092beabe1966a3229f599d7088b38dfc8ffa1608b5b5cdda31e591e6500f856"}, - {file = "grpcio-1.78.0-cp311-cp311-win_amd64.whl", hash = "sha256:1afa62af6e23f88629f2b29ec9e52ec7c65a7176c1e0a83292b93c76ca882558"}, - {file = "grpcio-1.78.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:f9ab915a267fc47c7e88c387a3a28325b58c898e23d4995f765728f4e3dedb97"}, - {file = "grpcio-1.78.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3f8904a8165ab21e07e58bf3e30a73f4dffc7a1e0dbc32d51c61b5360d26f43e"}, - {file = "grpcio-1.78.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:859b13906ce098c0b493af92142ad051bf64c7870fa58a123911c88606714996"}, - {file = "grpcio-1.78.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b2342d87af32790f934a79c3112641e7b27d63c261b8b4395350dad43eff1dc7"}, - {file = "grpcio-1.78.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:12a771591ae40bc65ba67048fa52ef4f0e6db8279e595fd349f9dfddeef571f9"}, - {file = "grpcio-1.78.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:185dea0d5260cbb2d224c507bf2a5444d5abbb1fa3594c1ed7e4c709d5eb8383"}, - {file = "grpcio-1.78.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:51b13f9aed9d59ee389ad666b8c2214cc87b5de258fa712f9ab05f922e3896c6"}, - {file = "grpcio-1.78.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fd5f135b1bd58ab088930b3c613455796dfa0393626a6972663ccdda5b4ac6ce"}, - {file = "grpcio-1.78.0-cp312-cp312-win32.whl", hash = "sha256:94309f498bcc07e5a7d16089ab984d42ad96af1d94b5a4eb966a266d9fcabf68"}, - {file = "grpcio-1.78.0-cp312-cp312-win_amd64.whl", hash = "sha256:9566fe4ababbb2610c39190791e5b829869351d14369603702e890ef3ad2d06e"}, - {file = "grpcio-1.78.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:ce3a90455492bf8bfa38e56fbbe1dbd4f872a3d8eeaf7337dc3b1c8aa28c271b"}, - {file = "grpcio-1.78.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:2bf5e2e163b356978b23652c4818ce4759d40f4712ee9ec5a83c4be6f8c23a3a"}, - {file = "grpcio-1.78.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8f2ac84905d12918e4e55a16da17939eb63e433dc11b677267c35568aa63fc84"}, - {file = "grpcio-1.78.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b58f37edab4a3881bc6c9bca52670610e0c9ca14e2ea3cf9debf185b870457fb"}, - {file = "grpcio-1.78.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:735e38e176a88ce41840c21bb49098ab66177c64c82426e24e0082500cc68af5"}, - {file = "grpcio-1.78.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2045397e63a7a0ee7957c25f7dbb36ddc110e0cfb418403d110c0a7a68a844e9"}, - {file = "grpcio-1.78.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a9f136fbafe7ccf4ac7e8e0c28b31066e810be52d6e344ef954a3a70234e1702"}, - {file = "grpcio-1.78.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:748b6138585379c737adc08aeffd21222abbda1a86a0dca2a39682feb9196c20"}, - {file = "grpcio-1.78.0-cp313-cp313-win32.whl", hash = "sha256:271c73e6e5676afe4fc52907686670c7cea22ab2310b76a59b678403ed40d670"}, - {file = "grpcio-1.78.0-cp313-cp313-win_amd64.whl", hash = "sha256:f2d4e43ee362adfc05994ed479334d5a451ab7bc3f3fee1b796b8ca66895acb4"}, - {file = "grpcio-1.78.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:e87cbc002b6f440482b3519e36e1313eb5443e9e9e73d6a52d43bd2004fcfd8e"}, - {file = "grpcio-1.78.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:c41bc64626db62e72afec66b0c8a0da76491510015417c127bfc53b2fe6d7f7f"}, - {file = "grpcio-1.78.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8dfffba826efcf366b1e3ccc37e67afe676f290e13a3b48d31a46739f80a8724"}, - {file = "grpcio-1.78.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:74be1268d1439eaaf552c698cdb11cd594f0c49295ae6bb72c34ee31abbe611b"}, - {file = "grpcio-1.78.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be63c88b32e6c0f1429f1398ca5c09bc64b0d80950c8bb7807d7d7fb36fb84c7"}, - {file = "grpcio-1.78.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:3c586ac70e855c721bda8f548d38c3ca66ac791dc49b66a8281a1f99db85e452"}, - {file = "grpcio-1.78.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:35eb275bf1751d2ffbd8f57cdbc46058e857cf3971041521b78b7db94bdaf127"}, - {file = "grpcio-1.78.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:207db540302c884b8848036b80db352a832b99dfdf41db1eb554c2c2c7800f65"}, - {file = "grpcio-1.78.0-cp314-cp314-win32.whl", hash = "sha256:57bab6deef2f4f1ca76cc04565df38dc5713ae6c17de690721bdf30cb1e0545c"}, - {file = "grpcio-1.78.0-cp314-cp314-win_amd64.whl", hash = "sha256:dce09d6116df20a96acfdbf85e4866258c3758180e8c49845d6ba8248b6d0bbb"}, - {file = "grpcio-1.78.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:86f85dd7c947baa707078a236288a289044836d4b640962018ceb9cd1f899af5"}, - {file = "grpcio-1.78.0-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:de8cb00d1483a412a06394b8303feec5dcb3b55f81d83aa216dbb6a0b86a94f5"}, - {file = "grpcio-1.78.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e888474dee2f59ff68130f8a397792d8cb8e17e6b3434339657ba4ee90845a8c"}, - {file = "grpcio-1.78.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:86ce2371bfd7f212cf60d8517e5e854475c2c43ce14aa910e136ace72c6db6c1"}, - {file = "grpcio-1.78.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b0c689c02947d636bc7fab3e30cc3a3445cca99c834dfb77cd4a6cabfc1c5597"}, - {file = "grpcio-1.78.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ce7599575eeb25c0f4dc1be59cada6219f3b56176f799627f44088b21381a28a"}, - {file = "grpcio-1.78.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:684083fd383e9dc04c794adb838d4faea08b291ce81f64ecd08e4577c7398adf"}, - {file = "grpcio-1.78.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ab399ef5e3cd2a721b1038a0f3021001f19c5ab279f145e1146bb0b9f1b2b12c"}, - {file = "grpcio-1.78.0-cp39-cp39-win32.whl", hash = "sha256:f3d6379493e18ad4d39537a82371c5281e153e963cecb13f953ebac155756525"}, - {file = "grpcio-1.78.0-cp39-cp39-win_amd64.whl", hash = "sha256:5361a0630a7fdb58a6a97638ab70e1dae2893c4d08d7aba64ded28bb9e7a29df"}, - {file = "grpcio-1.78.0.tar.gz", hash = "sha256:7382b95189546f375c174f53a5fa873cef91c4b8005faa05cc5b3beea9c4f1c5"}, + {file = "grpcio-1.80.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:886457a7768e408cdce226ad1ca67d2958917d306523a0e21e1a2fdaa75c9c9c"}, + {file = "grpcio-1.80.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:7b641fc3f1dc647bfd80bd713addc68f6d145956f64677e56d9ebafc0bd72388"}, + {file = "grpcio-1.80.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:33eb763f18f006dc7fee1e69831d38d23f5eccd15b2e0f92a13ee1d9242e5e02"}, + {file = "grpcio-1.80.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:52d143637e3872633fc7dd7c3c6a1c84e396b359f3a72e215f8bf69fd82084fc"}, + {file = "grpcio-1.80.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c51bf8ac4575af2e0678bccfb07e47321fc7acb5049b4482832c5c195e04e13a"}, + {file = "grpcio-1.80.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:50a9871536d71c4fba24ee856abc03a87764570f0c457dd8db0b4018f379fed9"}, + {file = "grpcio-1.80.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a72d84ad0514db063e21887fbacd1fd7acb4d494a564cae22227cd45c7fbf199"}, + {file = "grpcio-1.80.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f7691a6788ad9196872f95716df5bc643ebba13c97140b7a5ee5c8e75d1dea81"}, + {file = "grpcio-1.80.0-cp310-cp310-win32.whl", hash = "sha256:46c2390b59d67f84e882694d489f5b45707c657832d7934859ceb8c33f467069"}, + {file = "grpcio-1.80.0-cp310-cp310-win_amd64.whl", hash = "sha256:dc053420fc75749c961e2a4c906398d7c15725d36ccc04ae6d16093167223b58"}, + {file = "grpcio-1.80.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:dfab85db094068ff42e2a3563f60ab3dddcc9d6488a35abf0132daec13209c8a"}, + {file = "grpcio-1.80.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:5c07e82e822e1161354e32da2662f741a4944ea955f9f580ec8fb409dd6f6060"}, + {file = "grpcio-1.80.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba0915d51fd4ced2db5ff719f84e270afe0e2d4c45a7bdb1e8d036e4502928c2"}, + {file = "grpcio-1.80.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:3cb8130ba457d2aa09fa6b7c3ed6b6e4e6a2685fce63cb803d479576c4d80e21"}, + {file = "grpcio-1.80.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:09e5e478b3d14afd23f12e49e8b44c8684ac3c5f08561c43a5b9691c54d136ab"}, + {file = "grpcio-1.80.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:00168469238b022500e486c1c33916acf2f2a9b2c022202cf8a1885d2e3073c1"}, + {file = "grpcio-1.80.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8502122a3cc1714038e39a0b071acb1207ca7844208d5ea0d091317555ee7106"}, + {file = "grpcio-1.80.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ce1794f4ea6cc3ca29463f42d665c32ba1b964b48958a66497917fe9069f26e6"}, + {file = "grpcio-1.80.0-cp311-cp311-win32.whl", hash = "sha256:51b4a7189b0bef2aa30adce3c78f09c83526cf3dddb24c6a96555e3b97340440"}, + {file = "grpcio-1.80.0-cp311-cp311-win_amd64.whl", hash = "sha256:02e64bb0bb2da14d947a49e6f120a75e947250aebe65f9629b62bb1f5c14e6e9"}, + {file = "grpcio-1.80.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:c624cc9f1008361014378c9d776de7182b11fe8b2e5a81bc69f23a295f2a1ad0"}, + {file = "grpcio-1.80.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:f49eddcac43c3bf350c0385366a58f36bed8cc2c0ec35ef7b74b49e56552c0c2"}, + {file = "grpcio-1.80.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d334591df610ab94714048e0d5b4f3dd5ad1bee74dfec11eee344220077a79de"}, + {file = "grpcio-1.80.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0cb517eb1d0d0aaf1d87af7cc5b801d686557c1d88b2619f5e31fab3c2315921"}, + {file = "grpcio-1.80.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4e78c4ac0d97dc2e569b2f4bcbbb447491167cb358d1a389fc4af71ab6f70411"}, + {file = "grpcio-1.80.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2ed770b4c06984f3b47eb0517b1c69ad0b84ef3f40128f51448433be904634cd"}, + {file = "grpcio-1.80.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:256507e2f524092f1473071a05e65a5b10d84b82e3ff24c5b571513cfaa61e2f"}, + {file = "grpcio-1.80.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a6284a5d907c37db53350645567c522be314bac859a64a7a5ca63b77bb7958f"}, + {file = "grpcio-1.80.0-cp312-cp312-win32.whl", hash = "sha256:c71309cfce2f22be26aa4a847357c502db6c621f1a49825ae98aa0907595b193"}, + {file = "grpcio-1.80.0-cp312-cp312-win_amd64.whl", hash = "sha256:9fe648599c0e37594c4809d81a9e77bd138cc82eb8baa71b6a86af65426723ff"}, + {file = "grpcio-1.80.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:e9e408fc016dffd20661f0126c53d8a31c2821b5c13c5d67a0f5ed5de93319ad"}, + {file = "grpcio-1.80.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:92d787312e613754d4d8b9ca6d3297e69994a7912a32fa38c4c4e01c272974b0"}, + {file = "grpcio-1.80.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8ac393b58aa16991a2f1144ec578084d544038c12242da3a215966b512904d0f"}, + {file = "grpcio-1.80.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:68e5851ac4b9afe07e7f84483803ad167852570d65326b34d54ca560bfa53fb6"}, + {file = "grpcio-1.80.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:873ff5d17d68992ef6605330127425d2fc4e77e612fa3c3e0ed4e668685e3140"}, + {file = "grpcio-1.80.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2bea16af2750fd0a899bf1abd9022244418b55d1f37da2202249ba4ba673838d"}, + {file = "grpcio-1.80.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba0db34f7e1d803a878284cd70e4c63cb6ae2510ba51937bf8f45ba997cefcf7"}, + {file = "grpcio-1.80.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8eb613f02d34721f1acf3626dfdb3545bd3c8505b0e52bf8b5710a28d02e8aa7"}, + {file = "grpcio-1.80.0-cp313-cp313-win32.whl", hash = "sha256:93b6f823810720912fd131f561f91f5fed0fda372b6b7028a2681b8194d5d294"}, + {file = "grpcio-1.80.0-cp313-cp313-win_amd64.whl", hash = "sha256:e172cf795a3ba5246d3529e4d34c53db70e888fa582a8ffebd2e6e48bc0cba50"}, + {file = "grpcio-1.80.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:3d4147a97c8344d065d01bbf8b6acec2cf86fb0400d40696c8bdad34a64ffc0e"}, + {file = "grpcio-1.80.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:d8e11f167935b3eb089ac9038e1a063e6d7dbe995c0bb4a661e614583352e76f"}, + {file = "grpcio-1.80.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f14b618fc30de822681ee986cfdcc2d9327229dc4c98aed16896761cacd468b9"}, + {file = "grpcio-1.80.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4ed39fbdcf9b87370f6e8df4e39ca7b38b3e5e9d1b0013c7b6be9639d6578d14"}, + {file = "grpcio-1.80.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2dcc70e9f0ba987526e8e8603a610fb4f460e42899e74e7a518bf3c68fe1bf05"}, + {file = "grpcio-1.80.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:448c884b668b868562b1bda833c5fce6272d26e1926ec46747cda05741d302c1"}, + {file = "grpcio-1.80.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a1dc80fe55685b4a543555e6eef975303b36c8db1023b1599b094b92aa77965f"}, + {file = "grpcio-1.80.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:31b9ac4ad1aa28ffee5503821fafd09e4da0a261ce1c1281c6c8da0423c83b6e"}, + {file = "grpcio-1.80.0-cp314-cp314-win32.whl", hash = "sha256:367ce30ba67d05e0592470428f0ec1c31714cab9ef19b8f2e37be1f4c7d32fae"}, + {file = "grpcio-1.80.0-cp314-cp314-win_amd64.whl", hash = "sha256:3b01e1f5464c583d2f567b2e46ff0d516ef979978f72091fd81f5ab7fa6e2e7f"}, + {file = "grpcio-1.80.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:aacdfb4ed3eb919ca997504d27e03d5dba403c85130b8ed450308590a738f7a4"}, + {file = "grpcio-1.80.0-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:a361c20ec1ccd3c3953d20fb6d7b4125093bdd10dff44c5e2bbb39e58917cedc"}, + {file = "grpcio-1.80.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:43168871f170d1e4ed16ae03d10cd21efa29f190e710a624cee7e5ae07da6f4f"}, + {file = "grpcio-1.80.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1b97cd29a8eda100b559b455331c487a80915b6ea6bd91cf3e89836c4ee8d957"}, + {file = "grpcio-1.80.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bac1d573dfa84ce59a5547073e28fa7326d53352adda6912e362da0b917fcef4"}, + {file = "grpcio-1.80.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4560cf0e86514595dbbd330cd65b7afad4b5c4b8c4905c041cfffa138d45e6fd"}, + {file = "grpcio-1.80.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ec0a592e926071b4abad50c1495cd0d0d513324b3ff5e7267067c33ba27506e4"}, + {file = "grpcio-1.80.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:deb10a1528473c11f72a0939eed36d83e847d7cbb63e8cc5611fb7a912d38614"}, + {file = "grpcio-1.80.0-cp39-cp39-win32.whl", hash = "sha256:627fb7312171cdc52828bd6fac8d7028ff2a64b89f1957b6f3416caa2218d141"}, + {file = "grpcio-1.80.0-cp39-cp39-win_amd64.whl", hash = "sha256:05d55e1798756282cddd52d56c896b3e7d673e3a8798c2f1cd05ba249a3bb4de"}, + {file = "grpcio-1.80.0.tar.gz", hash = "sha256:29aca15edd0688c22ba01d7cc01cb000d72b2033f4a3c72a81a19b56fd143257"}, ] [package.dependencies] typing-extensions = ">=4.12,<5.0" [package.extras] -protobuf = ["grpcio-tools (>=1.78.0)"] +protobuf = ["grpcio-tools (>=1.80.0)"] [[package]] name = "grpcio-status" -version = "1.78.0" +version = "1.80.0" description = "Status proto mapping for gRPC" optional = false python-versions = ">=3.9" files = [ - {file = "grpcio_status-1.78.0-py3-none-any.whl", hash = "sha256:b492b693d4bf27b47a6c32590701724f1d3b9444b36491878fb71f6208857f34"}, - {file = "grpcio_status-1.78.0.tar.gz", hash = "sha256:a34cfd28101bfea84b5aa0f936b4b423019e9213882907166af6b3bddc59e189"}, + {file = "grpcio_status-1.80.0-py3-none-any.whl", hash = "sha256:4b56990363af50dbf2c2ebb80f1967185c07d87aa25aa2bea45ddb75fc181dbe"}, + {file = "grpcio_status-1.80.0.tar.gz", hash = "sha256:df73802a4c89a3ea88aa2aff971e886fccce162bc2e6511408b3d67a144381cd"}, ] [package.dependencies] googleapis-common-protos = ">=1.5.5" -grpcio = ">=1.78.0" +grpcio = ">=1.80.0" protobuf = ">=6.31.1,<7.0.0" [[package]] @@ -1817,83 +1817,83 @@ files = [ [[package]] name = "numpy" -version = "2.4.3" +version = "2.4.4" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.11" files = [ - {file = "numpy-2.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:33b3bf58ee84b172c067f56aeadc7ee9ab6de69c5e800ab5b10295d54c581adb"}, - {file = "numpy-2.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8ba7b51e71c05aa1f9bc3641463cd82308eab40ce0d5c7e1fd4038cbf9938147"}, - {file = "numpy-2.4.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:a1988292870c7cb9d0ebb4cc96b4d447513a9644801de54606dc7aabf2b7d920"}, - {file = "numpy-2.4.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:23b46bb6d8ecb68b58c09944483c135ae5f0e9b8d8858ece5e4ead783771d2a9"}, - {file = "numpy-2.4.3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a016db5c5dba78fa8fe9f5d80d6708f9c42ab087a739803c0ac83a43d686a470"}, - {file = "numpy-2.4.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:715de7f82e192e8cae5a507a347d97ad17598f8e026152ca97233e3666daaa71"}, - {file = "numpy-2.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2ddb7919366ee468342b91dea2352824c25b55814a987847b6c52003a7c97f15"}, - {file = "numpy-2.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a315e5234d88067f2d97e1f2ef670a7569df445d55400f1e33d117418d008d52"}, - {file = "numpy-2.4.3-cp311-cp311-win32.whl", hash = "sha256:2b3f8d2c4589b1a2028d2a770b0fc4d1f332fb5e01521f4de3199a896d158ddd"}, - {file = "numpy-2.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:77e76d932c49a75617c6d13464e41203cd410956614d0a0e999b25e9e8d27eec"}, - {file = "numpy-2.4.3-cp311-cp311-win_arm64.whl", hash = "sha256:eb610595dd91560905c132c709412b512135a60f1851ccbd2c959e136431ff67"}, - {file = "numpy-2.4.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:61b0cbabbb6126c8df63b9a3a0c4b1f44ebca5e12ff6997b80fcf267fb3150ef"}, - {file = "numpy-2.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7395e69ff32526710748f92cd8c9849b361830968ea3e24a676f272653e8983e"}, - {file = "numpy-2.4.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:abdce0f71dcb4a00e4e77f3faf05e4616ceccfe72ccaa07f47ee79cda3b7b0f4"}, - {file = "numpy-2.4.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:48da3a4ee1336454b07497ff7ec83903efa5505792c4e6d9bf83d99dc07a1e18"}, - {file = "numpy-2.4.3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:32e3bef222ad6b052280311d1d60db8e259e4947052c3ae7dd6817451fc8a4c5"}, - {file = "numpy-2.4.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e7dd01a46700b1967487141a66ac1a3cf0dd8ebf1f08db37d46389401512ca97"}, - {file = "numpy-2.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:76f0f283506c28b12bba319c0fab98217e9f9b54e6160e9c79e9f7348ba32e9c"}, - {file = "numpy-2.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:737f630a337364665aba3b5a77e56a68cc42d350edd010c345d65a3efa3addcc"}, - {file = "numpy-2.4.3-cp312-cp312-win32.whl", hash = "sha256:26952e18d82a1dbbc2f008d402021baa8d6fc8e84347a2072a25e08b46d698b9"}, - {file = "numpy-2.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:65f3c2455188f09678355f5cae1f959a06b778bc66d535da07bf2ef20cd319d5"}, - {file = "numpy-2.4.3-cp312-cp312-win_arm64.whl", hash = "sha256:2abad5c7fef172b3377502bde47892439bae394a71bc329f31df0fd829b41a9e"}, - {file = "numpy-2.4.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b346845443716c8e542d54112966383b448f4a3ba5c66409771b8c0889485dd3"}, - {file = "numpy-2.4.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2629289168f4897a3c4e23dc98d6f1731f0fc0fe52fb9db19f974041e4cc12b9"}, - {file = "numpy-2.4.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:bb2e3cf95854233799013779216c57e153c1ee67a0bf92138acca0e429aefaee"}, - {file = "numpy-2.4.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:7f3408ff897f8ab07a07fbe2823d7aee6ff644c097cc1f90382511fe982f647f"}, - {file = "numpy-2.4.3-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:decb0eb8a53c3b009b0962378065589685d66b23467ef5dac16cbe818afde27f"}, - {file = "numpy-2.4.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5f51900414fc9204a0e0da158ba2ac52b75656e7dce7e77fb9f84bfa343b4cc"}, - {file = "numpy-2.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6bd06731541f89cdc01b261ba2c9e037f1543df7472517836b78dfb15bd6e476"}, - {file = "numpy-2.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:22654fe6be0e5206f553a9250762c653d3698e46686eee53b399ab90da59bd92"}, - {file = "numpy-2.4.3-cp313-cp313-win32.whl", hash = "sha256:d71e379452a2f670ccb689ec801b1218cd3983e253105d6e83780967e899d687"}, - {file = "numpy-2.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:0a60e17a14d640f49146cb38e3f105f571318db7826d9b6fef7e4dce758faecd"}, - {file = "numpy-2.4.3-cp313-cp313-win_arm64.whl", hash = "sha256:c9619741e9da2059cd9c3f206110b97583c7152c1dc9f8aafd4beb450ac1c89d"}, - {file = "numpy-2.4.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7aa4e54f6469300ebca1d9eb80acd5253cdfa36f2c03d79a35883687da430875"}, - {file = "numpy-2.4.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d1b90d840b25874cf5cd20c219af10bac3667db3876d9a495609273ebe679070"}, - {file = "numpy-2.4.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a749547700de0a20a6718293396ec237bb38218049cfce788e08fcb716e8cf73"}, - {file = "numpy-2.4.3-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94f3c4a151a2e529adf49c1d54f0f57ff8f9b233ee4d44af623a81553ab86368"}, - {file = "numpy-2.4.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22c31dc07025123aedf7f2db9e91783df13f1776dc52c6b22c620870dc0fab22"}, - {file = "numpy-2.4.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:148d59127ac95979d6f07e4d460f934ebdd6eed641db9c0db6c73026f2b2101a"}, - {file = "numpy-2.4.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a97cbf7e905c435865c2d939af3d93f99d18eaaa3cabe4256f4304fb51604349"}, - {file = "numpy-2.4.3-cp313-cp313t-win32.whl", hash = "sha256:be3b8487d725a77acccc9924f65fd8bce9af7fac8c9820df1049424a2115af6c"}, - {file = "numpy-2.4.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1ec84fd7c8e652b0f4aaaf2e6e9cc8eaa9b1b80a537e06b2e3a2fb176eedcb26"}, - {file = "numpy-2.4.3-cp313-cp313t-win_arm64.whl", hash = "sha256:120df8c0a81ebbf5b9020c91439fccd85f5e018a927a39f624845be194a2be02"}, - {file = "numpy-2.4.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:5884ce5c7acfae1e4e1b6fde43797d10aa506074d25b531b4f54bde33c0c31d4"}, - {file = "numpy-2.4.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:297837823f5bc572c5f9379b0c9f3a3365f08492cbdc33bcc3af174372ebb168"}, - {file = "numpy-2.4.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:a111698b4a3f8dcbe54c64a7708f049355abd603e619013c346553c1fd4ca90b"}, - {file = "numpy-2.4.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:4bd4741a6a676770e0e97fe9ab2e51de01183df3dcbcec591d26d331a40de950"}, - {file = "numpy-2.4.3-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:54f29b877279d51e210e0c80709ee14ccbbad647810e8f3d375561c45ef613dd"}, - {file = "numpy-2.4.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:679f2a834bae9020f81534671c56fd0cc76dd7e5182f57131478e23d0dc59e24"}, - {file = "numpy-2.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d84f0f881cb2225c2dfd7f78a10a5645d487a496c6668d6cc39f0f114164f3d0"}, - {file = "numpy-2.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d213c7e6e8d211888cc359bab7199670a00f5b82c0978b9d1c75baf1eddbeac0"}, - {file = "numpy-2.4.3-cp314-cp314-win32.whl", hash = "sha256:52077feedeff7c76ed7c9f1a0428558e50825347b7545bbb8523da2cd55c547a"}, - {file = "numpy-2.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:0448e7f9caefb34b4b7dd2b77f21e8906e5d6f0365ad525f9f4f530b13df2afc"}, - {file = "numpy-2.4.3-cp314-cp314-win_arm64.whl", hash = "sha256:b44fd60341c4d9783039598efadd03617fa28d041fc37d22b62d08f2027fa0e7"}, - {file = "numpy-2.4.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0a195f4216be9305a73c0e91c9b026a35f2161237cf1c6de9b681637772ea657"}, - {file = "numpy-2.4.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:cd32fbacb9fd1bf041bf8e89e4576b6f00b895f06d00914820ae06a616bdfef7"}, - {file = "numpy-2.4.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:2e03c05abaee1f672e9d67bc858f300b5ccba1c21397211e8d77d98350972093"}, - {file = "numpy-2.4.3-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7d1ce23cce91fcea443320a9d0ece9b9305d4368875bab09538f7a5b4131938a"}, - {file = "numpy-2.4.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c59020932feb24ed49ffd03704fbab89f22aa9c0d4b180ff45542fe8918f5611"}, - {file = "numpy-2.4.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9684823a78a6cd6ad7511fc5e25b07947d1d5b5e2812c93fe99d7d4195130720"}, - {file = "numpy-2.4.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0200b25c687033316fb39f0ff4e3e690e8957a2c3c8d22499891ec58c37a3eb5"}, - {file = "numpy-2.4.3-cp314-cp314t-win32.whl", hash = "sha256:5e10da9e93247e554bb1d22f8edc51847ddd7dde52d85ce31024c1b4312bfba0"}, - {file = "numpy-2.4.3-cp314-cp314t-win_amd64.whl", hash = "sha256:45f003dbdffb997a03da2d1d0cb41fbd24a87507fb41605c0420a3db5bd4667b"}, - {file = "numpy-2.4.3-cp314-cp314t-win_arm64.whl", hash = "sha256:4d382735cecd7bcf090172489a525cd7d4087bc331f7df9f60ddc9a296cf208e"}, - {file = "numpy-2.4.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c6b124bfcafb9e8d3ed09130dbee44848c20b3e758b6bbf006e641778927c028"}, - {file = "numpy-2.4.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:76dbb9d4e43c16cf9aa711fcd8de1e2eeb27539dcefb60a1d5e9f12fae1d1ed8"}, - {file = "numpy-2.4.3-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:29363fbfa6f8ee855d7569c96ce524845e3d726d6c19b29eceec7dd555dab152"}, - {file = "numpy-2.4.3-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:bc71942c789ef415a37f0d4eab90341425a00d538cd0642445d30b41023d3395"}, - {file = "numpy-2.4.3-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7e58765ad74dcebd3ef0208a5078fba32dc8ec3578fe84a604432950cd043d79"}, - {file = "numpy-2.4.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e236dbda4e1d319d681afcbb136c0c4a8e0f1a5c58ceec2adebb547357fe857"}, - {file = "numpy-2.4.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:4b42639cdde6d24e732ff823a3fa5b701d8acad89c4142bc1d0bd6dc85200ba5"}, - {file = "numpy-2.4.3.tar.gz", hash = "sha256:483a201202b73495f00dbc83796c6ae63137a9bdade074f7648b3e32613412dd"}, + {file = "numpy-2.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db"}, + {file = "numpy-2.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0"}, + {file = "numpy-2.4.4-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015"}, + {file = "numpy-2.4.4-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40"}, + {file = "numpy-2.4.4-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d"}, + {file = "numpy-2.4.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502"}, + {file = "numpy-2.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd"}, + {file = "numpy-2.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5"}, + {file = "numpy-2.4.4-cp311-cp311-win32.whl", hash = "sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e"}, + {file = "numpy-2.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e"}, + {file = "numpy-2.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e"}, + {file = "numpy-2.4.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b"}, + {file = "numpy-2.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e"}, + {file = "numpy-2.4.4-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842"}, + {file = "numpy-2.4.4-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8"}, + {file = "numpy-2.4.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121"}, + {file = "numpy-2.4.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e"}, + {file = "numpy-2.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44"}, + {file = "numpy-2.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d"}, + {file = "numpy-2.4.4-cp312-cp312-win32.whl", hash = "sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827"}, + {file = "numpy-2.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a"}, + {file = "numpy-2.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec"}, + {file = "numpy-2.4.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50"}, + {file = "numpy-2.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115"}, + {file = "numpy-2.4.4-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af"}, + {file = "numpy-2.4.4-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c"}, + {file = "numpy-2.4.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103"}, + {file = "numpy-2.4.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83"}, + {file = "numpy-2.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed"}, + {file = "numpy-2.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959"}, + {file = "numpy-2.4.4-cp313-cp313-win32.whl", hash = "sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed"}, + {file = "numpy-2.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf"}, + {file = "numpy-2.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d"}, + {file = "numpy-2.4.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5"}, + {file = "numpy-2.4.4-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7"}, + {file = "numpy-2.4.4-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93"}, + {file = "numpy-2.4.4-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e"}, + {file = "numpy-2.4.4-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40"}, + {file = "numpy-2.4.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e"}, + {file = "numpy-2.4.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392"}, + {file = "numpy-2.4.4-cp313-cp313t-win32.whl", hash = "sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008"}, + {file = "numpy-2.4.4-cp313-cp313t-win_amd64.whl", hash = "sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8"}, + {file = "numpy-2.4.4-cp313-cp313t-win_arm64.whl", hash = "sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233"}, + {file = "numpy-2.4.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0"}, + {file = "numpy-2.4.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a"}, + {file = "numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a"}, + {file = "numpy-2.4.4-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b"}, + {file = "numpy-2.4.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a"}, + {file = "numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d"}, + {file = "numpy-2.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252"}, + {file = "numpy-2.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f"}, + {file = "numpy-2.4.4-cp314-cp314-win32.whl", hash = "sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc"}, + {file = "numpy-2.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74"}, + {file = "numpy-2.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb"}, + {file = "numpy-2.4.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e"}, + {file = "numpy-2.4.4-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113"}, + {file = "numpy-2.4.4-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d"}, + {file = "numpy-2.4.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d"}, + {file = "numpy-2.4.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f"}, + {file = "numpy-2.4.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0"}, + {file = "numpy-2.4.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150"}, + {file = "numpy-2.4.4-cp314-cp314t-win32.whl", hash = "sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871"}, + {file = "numpy-2.4.4-cp314-cp314t-win_amd64.whl", hash = "sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e"}, + {file = "numpy-2.4.4-cp314-cp314t-win_arm64.whl", hash = "sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7"}, + {file = "numpy-2.4.4-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4"}, + {file = "numpy-2.4.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e"}, + {file = "numpy-2.4.4-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c"}, + {file = "numpy-2.4.4-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3"}, + {file = "numpy-2.4.4-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7"}, + {file = "numpy-2.4.4-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f"}, + {file = "numpy-2.4.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119"}, + {file = "numpy-2.4.4.tar.gz", hash = "sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0"}, ] [[package]] @@ -2260,17 +2260,17 @@ testing = ["coverage", "pytest", "pytest-benchmark"] [[package]] name = "proto-plus" -version = "1.27.1" +version = "1.27.2" description = "Beautiful, Pythonic protocol buffers" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "proto_plus-1.27.1-py3-none-any.whl", hash = "sha256:e4643061f3a4d0de092d62aa4ad09fa4756b2cbb89d4627f3985018216f9fefc"}, - {file = "proto_plus-1.27.1.tar.gz", hash = "sha256:912a7460446625b792f6448bade9e55cd4e41e6ac10e27009ef71a7f317fa147"}, + {file = "proto_plus-1.27.2-py3-none-any.whl", hash = "sha256:6432f75893d3b9e70b9c412f1d2f03f65b11fb164b793d14ae2ca01821d22718"}, + {file = "proto_plus-1.27.2.tar.gz", hash = "sha256:b2adde53adadf75737c44d3dcb0104fde65250dfc83ad59168b4aa3e574b6a24"}, ] [package.dependencies] -protobuf = ">=3.19.0,<7.0.0" +protobuf = ">=4.25.8,<8.0.0" [package.extras] testing = ["google-api-core (>=1.31.5)"] @@ -2540,13 +2540,13 @@ typing-extensions = ">=4.14.1" [[package]] name = "pygments" -version = "2.19.2" +version = "2.20.0" description = "Pygments is a syntax highlighting package written in Python." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, - {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, + {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}, + {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}, ] [package.extras] @@ -3083,147 +3083,147 @@ typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} [[package]] name = "regex" -version = "2026.2.28" +version = "2026.3.32" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.10" files = [ - {file = "regex-2026.2.28-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fc48c500838be6882b32748f60a15229d2dea96e59ef341eaa96ec83538f498d"}, - {file = "regex-2026.2.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2afa673660928d0b63d84353c6c08a8a476ddfc4a47e11742949d182e6863ce8"}, - {file = "regex-2026.2.28-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7ab218076eb0944549e7fe74cf0e2b83a82edb27e81cc87411f76240865e04d5"}, - {file = "regex-2026.2.28-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94d63db12e45a9b9f064bfe4800cefefc7e5f182052e4c1b774d46a40ab1d9bb"}, - {file = "regex-2026.2.28-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:195237dc327858a7721bf8b0bbbef797554bc13563c3591e91cd0767bacbe359"}, - {file = "regex-2026.2.28-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b387a0d092dac157fb026d737dde35ff3e49ef27f285343e7c6401851239df27"}, - {file = "regex-2026.2.28-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3935174fa4d9f70525a4367aaff3cb8bc0548129d114260c29d9dfa4a5b41692"}, - {file = "regex-2026.2.28-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2b2b23587b26496ff5fd40df4278becdf386813ec00dc3533fa43a4cf0e2ad3c"}, - {file = "regex-2026.2.28-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3b24bd7e9d85dc7c6a8bd2aa14ecd234274a0248335a02adeb25448aecdd420d"}, - {file = "regex-2026.2.28-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bd477d5f79920338107f04aa645f094032d9e3030cc55be581df3d1ef61aa318"}, - {file = "regex-2026.2.28-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:b49eb78048c6354f49e91e4b77da21257fecb92256b6d599ae44403cab30b05b"}, - {file = "regex-2026.2.28-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:a25c7701e4f7a70021db9aaf4a4a0a67033c6318752146e03d1b94d32006217e"}, - {file = "regex-2026.2.28-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:9dd450db6458387167e033cfa80887a34c99c81d26da1bf8b0b41bf8c9cac88e"}, - {file = "regex-2026.2.28-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2954379dd20752e82d22accf3ff465311cbb2bac6c1f92c4afd400e1757f7451"}, - {file = "regex-2026.2.28-cp310-cp310-win32.whl", hash = "sha256:1f8b17be5c27a684ea6759983c13506bd77bfc7c0347dff41b18ce5ddd2ee09a"}, - {file = "regex-2026.2.28-cp310-cp310-win_amd64.whl", hash = "sha256:dd8847c4978bc3c7e6c826fb745f5570e518b8459ac2892151ce6627c7bc00d5"}, - {file = "regex-2026.2.28-cp310-cp310-win_arm64.whl", hash = "sha256:73cdcdbba8028167ea81490c7f45280113e41db2c7afb65a276f4711fa3bcbff"}, - {file = "regex-2026.2.28-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e621fb7c8dc147419b28e1702f58a0177ff8308a76fa295c71f3e7827849f5d9"}, - {file = "regex-2026.2.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0d5bef2031cbf38757a0b0bc4298bb4824b6332d28edc16b39247228fbdbad97"}, - {file = "regex-2026.2.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bcb399ed84eabf4282587ba151f2732ad8168e66f1d3f85b1d038868fe547703"}, - {file = "regex-2026.2.28-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c1b34dfa72f826f535b20712afa9bb3ba580020e834f3c69866c5bddbf10098"}, - {file = "regex-2026.2.28-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:851fa70df44325e1e4cdb79c5e676e91a78147b1b543db2aec8734d2add30ec2"}, - {file = "regex-2026.2.28-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:516604edd17b1c2c3e579cf4e9b25a53bf8fa6e7cedddf1127804d3e0140ca64"}, - {file = "regex-2026.2.28-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e7ce83654d1ab701cb619285a18a8e5a889c1216d746ddc710c914ca5fd71022"}, - {file = "regex-2026.2.28-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f2791948f7c70bb9335a9102df45e93d428f4b8128020d85920223925d73b9e1"}, - {file = "regex-2026.2.28-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:03a83cc26aa2acda6b8b9dfe748cf9e84cbd390c424a1de34fdcef58961a297a"}, - {file = "regex-2026.2.28-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ec6f5674c5dc836994f50f1186dd1fafde4be0666aae201ae2fcc3d29d8adf27"}, - {file = "regex-2026.2.28-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:50c2fc924749543e0eacc93ada6aeeb3ea5f6715825624baa0dccaec771668ae"}, - {file = "regex-2026.2.28-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ba55c50f408fb5c346a3a02d2ce0ebc839784e24f7c9684fde328ff063c3cdea"}, - {file = "regex-2026.2.28-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:edb1b1b3a5576c56f08ac46f108c40333f222ebfd5cf63afdfa3aab0791ebe5b"}, - {file = "regex-2026.2.28-cp311-cp311-win32.whl", hash = "sha256:948c12ef30ecedb128903c2c2678b339746eb7c689c5c21957c4a23950c96d15"}, - {file = "regex-2026.2.28-cp311-cp311-win_amd64.whl", hash = "sha256:fd63453f10d29097cc3dc62d070746523973fb5aa1c66d25f8558bebd47fed61"}, - {file = "regex-2026.2.28-cp311-cp311-win_arm64.whl", hash = "sha256:00f2b8d9615aa165fdff0a13f1a92049bfad555ee91e20d246a51aa0b556c60a"}, - {file = "regex-2026.2.28-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fcf26c3c6d0da98fada8ae4ef0aa1c3405a431c0a77eb17306d38a89b02adcd7"}, - {file = "regex-2026.2.28-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:02473c954af35dd2defeb07e44182f5705b30ea3f351a7cbffa9177beb14da5d"}, - {file = "regex-2026.2.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9b65d33a17101569f86d9c5966a8b1d7fbf8afdda5a8aa219301b0a80f58cf7d"}, - {file = "regex-2026.2.28-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e71dcecaa113eebcc96622c17692672c2d104b1d71ddf7adeda90da7ddeb26fc"}, - {file = "regex-2026.2.28-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:481df4623fa4969c8b11f3433ed7d5e3dc9cec0f008356c3212b3933fb77e3d8"}, - {file = "regex-2026.2.28-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:64e7c6ad614573e0640f271e811a408d79a9e1fe62a46adb602f598df42a818d"}, - {file = "regex-2026.2.28-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6b08a06976ff4fb0d83077022fde3eca06c55432bb997d8c0495b9a4e9872f4"}, - {file = "regex-2026.2.28-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:864cdd1a2ef5716b0ab468af40139e62ede1b3a53386b375ec0786bb6783fc05"}, - {file = "regex-2026.2.28-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:511f7419f7afab475fd4d639d4aedfc54205bcb0800066753ef68a59f0f330b5"}, - {file = "regex-2026.2.28-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b42f7466e32bf15a961cf09f35fa6323cc72e64d3d2c990b10de1274a5da0a59"}, - {file = "regex-2026.2.28-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8710d61737b0c0ce6836b1da7109f20d495e49b3809f30e27e9560be67a257bf"}, - {file = "regex-2026.2.28-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4390c365fd2d45278f45afd4673cb90f7285f5701607e3ad4274df08e36140ae"}, - {file = "regex-2026.2.28-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cb3b1db8ff6c7b8bf838ab05583ea15230cb2f678e569ab0e3a24d1e8320940b"}, - {file = "regex-2026.2.28-cp312-cp312-win32.whl", hash = "sha256:f8ed9a5d4612df9d4de15878f0bc6aa7a268afbe5af21a3fdd97fa19516e978c"}, - {file = "regex-2026.2.28-cp312-cp312-win_amd64.whl", hash = "sha256:01d65fd24206c8e1e97e2e31b286c59009636c022eb5d003f52760b0f42155d4"}, - {file = "regex-2026.2.28-cp312-cp312-win_arm64.whl", hash = "sha256:c0b5ccbb8ffb433939d248707d4a8b31993cb76ab1a0187ca886bf50e96df952"}, - {file = "regex-2026.2.28-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6d63a07e5ec8ce7184452cb00c41c37b49e67dc4f73b2955b5b8e782ea970784"}, - {file = "regex-2026.2.28-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e59bc8f30414d283ae8ee1617b13d8112e7135cb92830f0ec3688cb29152585a"}, - {file = "regex-2026.2.28-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:de0cf053139f96219ccfabb4a8dd2d217c8c82cb206c91d9f109f3f552d6b43d"}, - {file = "regex-2026.2.28-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb4db2f17e6484904f986c5a657cec85574c76b5c5e61c7aae9ffa1bc6224f95"}, - {file = "regex-2026.2.28-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:52b017b35ac2214d0db5f4f90e303634dc44e4aba4bd6235a27f97ecbe5b0472"}, - {file = "regex-2026.2.28-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:69fc560ccbf08a09dc9b52ab69cacfae51e0ed80dc5693078bdc97db2f91ae96"}, - {file = "regex-2026.2.28-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e61eea47230eba62a31f3e8a0e3164d0f37ef9f40529fb2c79361bc6b53d2a92"}, - {file = "regex-2026.2.28-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4f5c0b182ad4269e7381b7c27fdb0408399881f7a92a4624fd5487f2971dfc11"}, - {file = "regex-2026.2.28-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:96f6269a2882fbb0ee76967116b83679dc628e68eaea44e90884b8d53d833881"}, - {file = "regex-2026.2.28-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b5acd4b6a95f37c3c3828e5d053a7d4edaedb85de551db0153754924cb7c83e3"}, - {file = "regex-2026.2.28-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2234059cfe33d9813a3677ef7667999caea9eeaa83fef98eb6ce15c6cf9e0215"}, - {file = "regex-2026.2.28-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:c15af43c72a7fb0c97cbc66fa36a43546eddc5c06a662b64a0cbf30d6ac40944"}, - {file = "regex-2026.2.28-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9185cc63359862a6e80fe97f696e04b0ad9a11c4ac0a4a927f979f611bfe3768"}, - {file = "regex-2026.2.28-cp313-cp313-win32.whl", hash = "sha256:fb66e5245db9652abd7196ace599b04d9c0e4aa7c8f0e2803938377835780081"}, - {file = "regex-2026.2.28-cp313-cp313-win_amd64.whl", hash = "sha256:71a911098be38c859ceb3f9a9ce43f4ed9f4c6720ad8684a066ea246b76ad9ff"}, - {file = "regex-2026.2.28-cp313-cp313-win_arm64.whl", hash = "sha256:39bb5727650b9a0275c6a6690f9bb3fe693a7e6cc5c3155b1240aedf8926423e"}, - {file = "regex-2026.2.28-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:97054c55db06ab020342cc0d35d6f62a465fa7662871190175f1ad6c655c028f"}, - {file = "regex-2026.2.28-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0d25a10811de831c2baa6aef3c0be91622f44dd8d31dd12e69f6398efb15e48b"}, - {file = "regex-2026.2.28-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d6cfe798d8da41bb1862ed6e0cba14003d387c3c0c4a5d45591076ae9f0ce2f8"}, - {file = "regex-2026.2.28-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fd0ce43e71d825b7c0661f9c54d4d74bd97c56c3fd102a8985bcfea48236bacb"}, - {file = "regex-2026.2.28-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00945d007fd74a9084d2ab79b695b595c6b7ba3698972fadd43e23230c6979c1"}, - {file = "regex-2026.2.28-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bec23c11cbbf09a4df32fe50d57cbdd777bc442269b6e39a1775654f1c95dee2"}, - {file = "regex-2026.2.28-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5cdcc17d935c8f9d3f4db5c2ebe2640c332e3822ad5d23c2f8e0228e6947943a"}, - {file = "regex-2026.2.28-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a448af01e3d8031c89c5d902040b124a5e921a25c4e5e07a861ca591ce429341"}, - {file = "regex-2026.2.28-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:10d28e19bd4888e4abf43bd3925f3c134c52fdf7259219003588a42e24c2aa25"}, - {file = "regex-2026.2.28-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:99985a2c277dcb9ccb63f937451af5d65177af1efdeb8173ac55b61095a0a05c"}, - {file = "regex-2026.2.28-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:e1e7b24cb3ae9953a560c563045d1ba56ee4749fbd05cf21ba571069bd7be81b"}, - {file = "regex-2026.2.28-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:d8511a01d0e4ee1992eb3ba19e09bc1866fe03f05129c3aec3fdc4cbc77aad3f"}, - {file = "regex-2026.2.28-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:aaffaecffcd2479ce87aa1e74076c221700b7c804e48e98e62500ee748f0f550"}, - {file = "regex-2026.2.28-cp313-cp313t-win32.whl", hash = "sha256:ef77bdde9c9eba3f7fa5b58084b29bbcc74bcf55fdbeaa67c102a35b5bd7e7cc"}, - {file = "regex-2026.2.28-cp313-cp313t-win_amd64.whl", hash = "sha256:98adf340100cbe6fbaf8e6dc75e28f2c191b1be50ffefe292fb0e6f6eefdb0d8"}, - {file = "regex-2026.2.28-cp313-cp313t-win_arm64.whl", hash = "sha256:2fb950ac1d88e6b6a9414381f403797b236f9fa17e1eee07683af72b1634207b"}, - {file = "regex-2026.2.28-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:78454178c7df31372ea737996fb7f36b3c2c92cccc641d251e072478afb4babc"}, - {file = "regex-2026.2.28-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:5d10303dd18cedfd4d095543998404df656088240bcfd3cd20a8f95b861f74bd"}, - {file = "regex-2026.2.28-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:19a9c9e0a8f24f39d575a6a854d516b48ffe4cbdcb9de55cb0570a032556ecff"}, - {file = "regex-2026.2.28-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09500be324f49b470d907b3ef8af9afe857f5cca486f853853f7945ddbf75911"}, - {file = "regex-2026.2.28-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fb1c4ff62277d87a7335f2c1ea4e0387b8f2b3ad88a64efd9943906aafad4f33"}, - {file = "regex-2026.2.28-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b8b3f1be1738feadc69f62daa250c933e85c6f34fa378f54a7ff43807c1b9117"}, - {file = "regex-2026.2.28-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc8ed8c3f41c27acb83f7b6a9eb727a73fc6663441890c5cb3426a5f6a91ce7d"}, - {file = "regex-2026.2.28-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa539be029844c0ce1114762d2952ab6cfdd7c7c9bd72e0db26b94c3c36dcc5a"}, - {file = "regex-2026.2.28-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7900157786428a79615a8264dac1f12c9b02957c473c8110c6b1f972dcecaddf"}, - {file = "regex-2026.2.28-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:0b1d2b07614d95fa2bf8a63fd1e98bd8fa2b4848dc91b1efbc8ba219fdd73952"}, - {file = "regex-2026.2.28-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:b389c61aa28a79c2e0527ac36da579869c2e235a5b208a12c5b5318cda2501d8"}, - {file = "regex-2026.2.28-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f467cb602f03fbd1ab1908f68b53c649ce393fde056628dc8c7e634dab6bfc07"}, - {file = "regex-2026.2.28-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e8c8cb2deba42f5ec1ede46374e990f8adc5e6456a57ac1a261b19be6f28e4e6"}, - {file = "regex-2026.2.28-cp314-cp314-win32.whl", hash = "sha256:9036b400b20e4858d56d117108d7813ed07bb7803e3eed766675862131135ca6"}, - {file = "regex-2026.2.28-cp314-cp314-win_amd64.whl", hash = "sha256:1d367257cd86c1cbb97ea94e77b373a0bbc2224976e247f173d19e8f18b4afa7"}, - {file = "regex-2026.2.28-cp314-cp314-win_arm64.whl", hash = "sha256:5e68192bb3a1d6fb2836da24aa494e413ea65853a21505e142e5b1064a595f3d"}, - {file = "regex-2026.2.28-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:a5dac14d0872eeb35260a8e30bac07ddf22adc1e3a0635b52b02e180d17c9c7e"}, - {file = "regex-2026.2.28-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ec0c608b7a7465ffadb344ed7c987ff2f11ee03f6a130b569aa74d8a70e8333c"}, - {file = "regex-2026.2.28-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c7815afb0ca45456613fdaf60ea9c993715511c8d53a83bc468305cbc0ee23c7"}, - {file = "regex-2026.2.28-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b059e71ec363968671693a78c5053bd9cb2fe410f9b8e4657e88377ebd603a2e"}, - {file = "regex-2026.2.28-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b8cf76f1a29f0e99dcfd7aef1551a9827588aae5a737fe31442021165f1920dc"}, - {file = "regex-2026.2.28-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:180e08a435a0319e6a4821c3468da18dc7001987e1c17ae1335488dfe7518dd8"}, - {file = "regex-2026.2.28-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1e496956106fd59ba6322a8ea17141a27c5040e5ee8f9433ae92d4e5204462a0"}, - {file = "regex-2026.2.28-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bba2b18d70eeb7b79950f12f633beeecd923f7c9ad6f6bae28e59b4cb3ab046b"}, - {file = "regex-2026.2.28-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6db7bfae0f8a2793ff1f7021468ea55e2699d0790eb58ee6ab36ae43aa00bc5b"}, - {file = "regex-2026.2.28-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:d0b02e8b7e5874b48ae0f077ecca61c1a6a9f9895e9c6dfb191b55b242862033"}, - {file = "regex-2026.2.28-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:25b6eb660c5cf4b8c3407a1ed462abba26a926cc9965e164268a3267bcc06a43"}, - {file = "regex-2026.2.28-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:5a932ea8ad5d0430351ff9c76c8db34db0d9f53c1d78f06022a21f4e290c5c18"}, - {file = "regex-2026.2.28-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1c2c95e1a2b0f89d01e821ff4de1be4b5d73d1f4b0bf679fa27c1ad8d2327f1a"}, - {file = "regex-2026.2.28-cp314-cp314t-win32.whl", hash = "sha256:bbb882061f742eb5d46f2f1bd5304055be0a66b783576de3d7eef1bed4778a6e"}, - {file = "regex-2026.2.28-cp314-cp314t-win_amd64.whl", hash = "sha256:6591f281cb44dc13de9585b552cec6fc6cf47fb2fe7a48892295ee9bc4a612f9"}, - {file = "regex-2026.2.28-cp314-cp314t-win_arm64.whl", hash = "sha256:dee50f1be42222f89767b64b283283ef963189da0dda4a515aa54a5563c62dec"}, - {file = "regex-2026.2.28.tar.gz", hash = "sha256:a729e47d418ea11d03469f321aaf67cdee8954cde3ff2cf8403ab87951ad10f2"}, + {file = "regex-2026.3.32-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:462a041d2160090553572f6bb0be417ab9bb912a08de54cb692829c871ee88c1"}, + {file = "regex-2026.3.32-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c3c6f6b027d10f84bfe65049028892b5740878edd9eae5fea0d1710b09b1d257"}, + {file = "regex-2026.3.32-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:879ae91f2928a13f01a55cfa168acedd2b02b11b4cd8b5bb9223e8cde777ca52"}, + {file = "regex-2026.3.32-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:887a9fa74418d74d645281ee0edcf60694053bd1bc2ebc49eb5e66bfffc6d107"}, + {file = "regex-2026.3.32-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d571f0b2eec3513734ea31a16ce0f7840c0b85a98e7edfa0e328ed144f9ef78f"}, + {file = "regex-2026.3.32-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6ada7bd5bb6511d12177a7b00416ce55caee49fbf8c268f26b909497b534cacb"}, + {file = "regex-2026.3.32-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:918db4e34a7ef3d0beee913fa54b34231cc3424676f1c19bdb85f01828d3cd37"}, + {file = "regex-2026.3.32-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:69a847a6ffaa86e8af7b9e7037606e05a6f663deec516ad851e8e05d9908d16a"}, + {file = "regex-2026.3.32-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2c8d402ea3dfe674288fe3962016affd33b5b27213d2b5db1823ffa4de524c57"}, + {file = "regex-2026.3.32-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d6b39a2cc5625bbc4fda18919a891eab9aab934eecf83660a90ce20c53621a9a"}, + {file = "regex-2026.3.32-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f7cc00089b4c21847852c0ad76fb3680f9833b855a0d30bcec94211c435bff6b"}, + {file = "regex-2026.3.32-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:fd03e38068faeef937cc6761a250a4aaa015564bd0d61481fefcf15586d31825"}, + {file = "regex-2026.3.32-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e006ea703d5c0f3d112b51ba18af73b58209b954acfe3d8da42eacc9a00e4be6"}, + {file = "regex-2026.3.32-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6980ceb5c1049d4878632f08ba0bf7234c30e741b0dc9081da0f86eca13189d3"}, + {file = "regex-2026.3.32-cp310-cp310-win32.whl", hash = "sha256:6128dd0793a87287ea1d8bf16b4250dd96316c464ee15953d5b98875a284d41e"}, + {file = "regex-2026.3.32-cp310-cp310-win_amd64.whl", hash = "sha256:5aa78c857c1731bdd9863923ffadc816d823edf475c7db6d230c28b53b7bdb5e"}, + {file = "regex-2026.3.32-cp310-cp310-win_arm64.whl", hash = "sha256:34c905a721ddee0f84c99e3e3b59dd4a5564a6fe338222bc89dd4d4df166115c"}, + {file = "regex-2026.3.32-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d7855f5e59fcf91d0c9f4a51dc5d8847813832a2230c3e8e35912ccf20baaa2"}, + {file = "regex-2026.3.32-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:18eb45f711e942c27dbed4109830bd070d8d618e008d0db39705f3f57070a4c6"}, + {file = "regex-2026.3.32-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed3b8281c5d0944d939c82db4ec2300409dd69ee087f7a75a94f2e301e855fb4"}, + {file = "regex-2026.3.32-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ad5c53f2e8fcae9144009435ebe3d9832003508cf8935c04542a1b3b8deefa15"}, + {file = "regex-2026.3.32-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:70c634e39c5cda0da05c93d6747fdc957599f7743543662b6dbabdd8d3ba8a96"}, + {file = "regex-2026.3.32-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1e0f6648fd48f4c73d801c55ab976cd602e2da87de99c07bff005b131f269c6a"}, + {file = "regex-2026.3.32-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5e0fdb5744caf1036dec5510f543164f2144cb64932251f6dfd42fa872b7f9c"}, + {file = "regex-2026.3.32-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dab4178a0bc1ef13178832b12db7bc7f562e8f028b2b5be186e370090dc50652"}, + {file = "regex-2026.3.32-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f95bd07f301135771559101c060f558e2cf896c7df00bec050ca7f93bf11585a"}, + {file = "regex-2026.3.32-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2dcca2bceb823c9cc610e57b86a265d7ffc30e9fe98548c609eba8bd3c0c2488"}, + {file = "regex-2026.3.32-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:567b57eb987547a23306444e4f6f85d4314f83e65c71d320d898aa7550550443"}, + {file = "regex-2026.3.32-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:b6acb765e7c1f2fa08ac9057a33595e26104d7d67046becae184a8f100932dd9"}, + {file = "regex-2026.3.32-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c1ed17104d1be7f807fdec35ec99777168dd793a09510d753f8710590ba54cdd"}, + {file = "regex-2026.3.32-cp311-cp311-win32.whl", hash = "sha256:c60f1de066eb5a0fd8ee5974de4194bb1c2e7692941458807162ffbc39887303"}, + {file = "regex-2026.3.32-cp311-cp311-win_amd64.whl", hash = "sha256:8fe14e24124ef41220e5992a0f09432f890037df6f93fd3d6b7a0feff2db16b2"}, + {file = "regex-2026.3.32-cp311-cp311-win_arm64.whl", hash = "sha256:ded4fc0edf3de792850cb8b04bbf3c5bd725eeaf9df4c27aad510f6eed9c4e19"}, + {file = "regex-2026.3.32-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ad8d372587e659940568afd009afeb72be939c769c552c9b28773d0337251391"}, + {file = "regex-2026.3.32-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3f5747501b69299c6b0b047853771e4ed390510bada68cb16da9c9c2078343f7"}, + {file = "regex-2026.3.32-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:db976be51375bca900e008941639448d148c655c9545071965d0571ecc04f5d0"}, + {file = "regex-2026.3.32-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:66a5083c3ffe5a5a95f8281ea47a88072d4f24001d562d1d9d28d4cdc005fec5"}, + {file = "regex-2026.3.32-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e83ce8008b48762be296f1401f19afd9ea29f3d035d1974e0cecb74e9afbd1df"}, + {file = "regex-2026.3.32-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3aa21bad31db904e0b9055e12c8282df62d43169c4a9d2929407060066ebc74"}, + {file = "regex-2026.3.32-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f54840bea73541652f1170dc63402a5b776fc851ad36a842da9e5163c1f504a0"}, + {file = "regex-2026.3.32-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2ffbadc647325dd4e3118269bda93ded1eb5f5b0c3b7ba79a3da9fbd04f248e9"}, + {file = "regex-2026.3.32-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:66d3126afe7eac41759cd5f0b3b246598086e88e70527c0d68c9e615b81771c4"}, + {file = "regex-2026.3.32-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f785f44a44702dea89b28bce5bc82552490694ce4e144e21a4f0545e364d2150"}, + {file = "regex-2026.3.32-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:b7836aa13721dbdef658aebd11f60d00de633a95726521860fe1f6be75fa225a"}, + {file = "regex-2026.3.32-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5336b1506142eb0f23c96fb4a34b37c4fefd4fed2a7042069f3c8058efe17855"}, + {file = "regex-2026.3.32-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b56993a7aeb4140c4770f4f7965c9e5af4f024457d06e23c01b0d47501cb18ed"}, + {file = "regex-2026.3.32-cp312-cp312-win32.whl", hash = "sha256:d363660f9ef8c734495598d2f3e527fb41f745c73159dc0d743402f049fb6836"}, + {file = "regex-2026.3.32-cp312-cp312-win_amd64.whl", hash = "sha256:c9f261ad3cd97257dc1d9355bfbaa7dd703e06574bffa0fa8fe1e31da915ee38"}, + {file = "regex-2026.3.32-cp312-cp312-win_arm64.whl", hash = "sha256:89e50667e7e8c0e7903e4d644a2764fffe9a3a5d6578f72ab7a7b4205bf204b7"}, + {file = "regex-2026.3.32-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c6d9c6e783b348f719b6118bb3f187b2e138e3112576c9679eb458cc8b2e164b"}, + {file = "regex-2026.3.32-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0f21ae18dfd15752cdd98d03cbd7a3640be826bfd58482a93f730dbd24d7b9fb"}, + {file = "regex-2026.3.32-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:844d88509c968dd44b30daeefac72b038b1bf31ac372d5106358ab01d393c48b"}, + {file = "regex-2026.3.32-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8fc918cd003ba0d066bf0003deb05a259baaaab4dc9bd4f1207bbbe64224857a"}, + {file = "regex-2026.3.32-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bbc458a292aee57d572075f22c035fa32969cdb7987d454e3e34d45a40a0a8b4"}, + {file = "regex-2026.3.32-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:987cdfcfb97a249abc3601ad53c7de5c370529f1981e4c8c46793e4a1e1bfe8e"}, + {file = "regex-2026.3.32-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5d88fa37ba5e8a80ca8d956b9ea03805cfa460223ac94b7d4854ee5e30f3173"}, + {file = "regex-2026.3.32-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4d082be64e51671dd5ee1c208c92da2ddda0f2f20d8ef387e57634f7e97b6aae"}, + {file = "regex-2026.3.32-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c1d7fa44aece1fa02b8927441614c96520253a5cad6a96994e3a81e060feed55"}, + {file = "regex-2026.3.32-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d478a2ca902b6ef28ffc9521e5f0f728d036abe35c0b250ee8ae78cfe7c5e44e"}, + {file = "regex-2026.3.32-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2820d2231885e97aff0fcf230a19ebd5d2b5b8a1ba338c20deb34f16db1c7897"}, + {file = "regex-2026.3.32-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc8ced733d6cd9af5e412f256a32f7c61cd2d7371280a65c689939ac4572499f"}, + {file = "regex-2026.3.32-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:847087abe98b3c1ebf1eb49d6ef320dbba75a83ee4f83c94704580f1df007dd4"}, + {file = "regex-2026.3.32-cp313-cp313-win32.whl", hash = "sha256:d21a07edddb3e0ca12a8b8712abc8452481c3d3db19ae87fc94e9842d005964b"}, + {file = "regex-2026.3.32-cp313-cp313-win_amd64.whl", hash = "sha256:3c054e39a9f85a3d76c62a1d50c626c5e9306964eaa675c53f61ff7ec1204bbb"}, + {file = "regex-2026.3.32-cp313-cp313-win_arm64.whl", hash = "sha256:b2e9c2ea2e93223579308263f359eab8837dc340530b860cb59b713651889f14"}, + {file = "regex-2026.3.32-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:5d86e3fb08c94f084a625c8dc2132a79a3a111c8bf6e2bc59351fa61753c2f6e"}, + {file = "regex-2026.3.32-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b6f366a5ef66a2df4d9e68035cfe9f0eb8473cdfb922c37fac1d169b468607b0"}, + {file = "regex-2026.3.32-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b8fca73e16c49dd972ce3a88278dfa5b93bf91ddef332a46e9443abe21ca2f7c"}, + {file = "regex-2026.3.32-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b953d9d496d19786f4d46e6ba4b386c6e493e81e40f9c5392332458183b0599d"}, + {file = "regex-2026.3.32-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b565f25171e04d4fad950d1fa837133e3af6ea6f509d96166eed745eb0cf63bc"}, + {file = "regex-2026.3.32-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f28eac18a8733a124444643a66ac96fef2c0ad65f50034e0a043b90333dc677f"}, + {file = "regex-2026.3.32-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7cdd508664430dd51b8888deb6c5b416d8de046b2e11837254378d31febe4a98"}, + {file = "regex-2026.3.32-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5c35d097f509cf7e40d20d5bee548d35d6049b36eb9965e8d43e4659923405b9"}, + {file = "regex-2026.3.32-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:85c9b0c131427470a6423baa0a9330be6fd8c3630cc3ee6fdee03360724cbec5"}, + {file = "regex-2026.3.32-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:e50af656c15e2723eeb7279c0837e07accc594b95ec18b86821a4d44b51b24bf"}, + {file = "regex-2026.3.32-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:4bc32b4dbdb4f9f300cf9f38f8ea2ce9511a068ffaa45ac1373ee7a943f1d810"}, + {file = "regex-2026.3.32-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e3e5d1802cba785210a4a800e63fcee7a228649a880f3bf7f2aadccb151a834b"}, + {file = "regex-2026.3.32-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ef250a3f5e93182193f5c927c5e9575b2cb14b80d03e258bc0b89cc5de076b60"}, + {file = "regex-2026.3.32-cp313-cp313t-win32.whl", hash = "sha256:9cf7036dfa2370ccc8651521fcbb40391974841119e9982fa312b552929e6c85"}, + {file = "regex-2026.3.32-cp313-cp313t-win_amd64.whl", hash = "sha256:c940e00e8d3d10932c929d4b8657c2ea47d2560f31874c3e174c0d3488e8b865"}, + {file = "regex-2026.3.32-cp313-cp313t-win_arm64.whl", hash = "sha256:ace48c5e157c1e58b7de633c5e257285ce85e567ac500c833349c363b3df69d4"}, + {file = "regex-2026.3.32-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:a416ee898ecbc5d8b283223b4cf4d560f93244f6f7615c1bd67359744b00c166"}, + {file = "regex-2026.3.32-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d76d62909bfb14521c3f7cfd5b94c0c75ec94b0a11f647d2f604998962ec7b6c"}, + {file = "regex-2026.3.32-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:631f7d95c83f42bccfe18946a38ad27ff6b6717fb4807e60cf24860b5eb277fc"}, + {file = "regex-2026.3.32-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:12917c6c6813ffcdfb11680a04e4d63c5532b88cf089f844721c5f41f41a63ad"}, + {file = "regex-2026.3.32-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3e221b615f83b15887636fcb90ed21f1a19541366f8b7ba14ba1ad8304f4ded4"}, + {file = "regex-2026.3.32-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4f9ae4755fa90f1dc2d0d393d572ebc134c0fe30fcfc0ab7e67c1db15f192041"}, + {file = "regex-2026.3.32-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a094e9dcafedfb9d333db5cf880304946683f43a6582bb86688f123335122929"}, + {file = "regex-2026.3.32-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c1cecea3e477af105f32ef2119b8d895f297492e41d317e60d474bc4bffd62ff"}, + {file = "regex-2026.3.32-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f26262900edd16272b6360014495e8d68379c6c6e95983f9b7b322dc928a1194"}, + {file = "regex-2026.3.32-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:1cb22fa9ee6a0acb22fc9aecce5f9995fe4d2426ed849357d499d62608fbd7f9"}, + {file = "regex-2026.3.32-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:9b9118a78e031a2e4709cd2fcc3028432e89b718db70073a8da574c249b5b249"}, + {file = "regex-2026.3.32-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:b193ed199848aa96618cd5959c1582a0bf23cd698b0b900cb0ffe81b02c8659c"}, + {file = "regex-2026.3.32-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:10fb2aaae1aaadf7d43c9f3c2450404253697bf8b9ce360bd5418d1d16292298"}, + {file = "regex-2026.3.32-cp314-cp314-win32.whl", hash = "sha256:110ba4920721374d16c4c8ea7ce27b09546d43e16aea1d7f43681b5b8f80ba61"}, + {file = "regex-2026.3.32-cp314-cp314-win_amd64.whl", hash = "sha256:245667ad430745bae6a1e41081872d25819d86fbd9e0eec485ba00d9f78ad43d"}, + {file = "regex-2026.3.32-cp314-cp314-win_arm64.whl", hash = "sha256:1ca02ff0ef33e9d8276a1fcd6d90ff6ea055a32c9149c0050b5b67e26c6d2c51"}, + {file = "regex-2026.3.32-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:51fb7e26f91f9091fd8ec6a946f99b15d3bc3667cb5ddc73dd6cb2222dd4a1cc"}, + {file = "regex-2026.3.32-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:51a93452034d671b0e21b883d48ea66c5d6a05620ee16a9d3f229e828568f3f0"}, + {file = "regex-2026.3.32-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:03c2ebd15ff51e7b13bb3dc28dd5ac18cd39e59ebb40430b14ae1a19e833cff1"}, + {file = "regex-2026.3.32-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5bf2f3c2c5bd8360d335c7dcd4a9006cf1dabae063ee2558ee1b07bbc8a20d88"}, + {file = "regex-2026.3.32-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8a4a3189a99ecdd1c13f42513ab3fc7fa8311b38ba7596dd98537acb8cd9acc3"}, + {file = "regex-2026.3.32-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3c0bbfbd38506e1ea96a85da6782577f06239cb9fcf9696f1ea537c980c0680b"}, + {file = "regex-2026.3.32-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8aaf8ee8f34b677f90742ca089b9c83d64bdc410528767273c816a863ed57327"}, + {file = "regex-2026.3.32-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3ea568832eca219c2be1721afa073c1c9eb8f98a9733fdedd0a9747639fc22a5"}, + {file = "regex-2026.3.32-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e4c8fa46aad1a11ae2f8fcd1c90b9d55e18925829ac0d98c5bb107f93351745"}, + {file = "regex-2026.3.32-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0cec365d44835b043d7b3266487797639d07d621bec9dc0ea224b00775797cc1"}, + {file = "regex-2026.3.32-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:09e26cad1544d856da85881ad292797289e4406338afe98163f3db9f7fac816c"}, + {file = "regex-2026.3.32-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:6062c4ef581a3e9e503dccf4e1b7f2d33fdc1c13ad510b287741ac73bc4c6b27"}, + {file = "regex-2026.3.32-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88ebc0783907468f17fca3d7821b30f9c21865a721144eb498cb0ff99a67bcac"}, + {file = "regex-2026.3.32-cp314-cp314t-win32.whl", hash = "sha256:e480d3dac06c89bc2e0fd87524cc38c546ac8b4a38177650745e64acbbcfdeba"}, + {file = "regex-2026.3.32-cp314-cp314t-win_amd64.whl", hash = "sha256:67015a8162d413af9e3309d9a24e385816666fbf09e48e3ec43342c8536f7df6"}, + {file = "regex-2026.3.32-cp314-cp314t-win_arm64.whl", hash = "sha256:1a6ac1ed758902e664e0d95c1ee5991aa6fb355423f378ed184c6ec47a1ec0e9"}, + {file = "regex-2026.3.32.tar.gz", hash = "sha256:f1574566457161678297a116fa5d1556c5a4159d64c5ff7c760e7c564bf66f16"}, ] [[package]] name = "requests" -version = "2.32.5" +version = "2.33.1" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" files = [ - {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"}, - {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"}, + {file = "requests-2.33.1-py3-none-any.whl", hash = "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a"}, + {file = "requests-2.33.1.tar.gz", hash = "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517"}, ] [package.dependencies] -certifi = ">=2017.4.17" +certifi = ">=2023.5.7" charset_normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" +urllib3 = ">=1.26,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<8)"] [[package]] name = "requests-cache" @@ -3575,58 +3575,58 @@ widechars = ["wcwidth"] [[package]] name = "tomli" -version = "2.4.0" +version = "2.4.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" files = [ - {file = "tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867"}, - {file = "tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9"}, - {file = "tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95"}, - {file = "tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76"}, - {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d"}, - {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576"}, - {file = "tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a"}, - {file = "tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa"}, - {file = "tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614"}, - {file = "tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1"}, - {file = "tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8"}, - {file = "tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a"}, - {file = "tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1"}, - {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b"}, - {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51"}, - {file = "tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729"}, - {file = "tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da"}, - {file = "tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3"}, - {file = "tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0"}, - {file = "tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e"}, - {file = "tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4"}, - {file = "tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e"}, - {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c"}, - {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f"}, - {file = "tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86"}, - {file = "tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87"}, - {file = "tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132"}, - {file = "tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6"}, - {file = "tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc"}, - {file = "tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66"}, - {file = "tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d"}, - {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702"}, - {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8"}, - {file = "tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776"}, - {file = "tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475"}, - {file = "tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2"}, - {file = "tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9"}, - {file = "tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0"}, - {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df"}, - {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d"}, - {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f"}, - {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b"}, - {file = "tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087"}, - {file = "tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd"}, - {file = "tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4"}, - {file = "tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a"}, - {file = "tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c"}, + {file = "tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30"}, + {file = "tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a"}, + {file = "tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076"}, + {file = "tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9"}, + {file = "tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c"}, + {file = "tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc"}, + {file = "tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049"}, + {file = "tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e"}, + {file = "tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece"}, + {file = "tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a"}, + {file = "tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085"}, + {file = "tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9"}, + {file = "tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5"}, + {file = "tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585"}, + {file = "tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1"}, + {file = "tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917"}, + {file = "tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9"}, + {file = "tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257"}, + {file = "tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54"}, + {file = "tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a"}, + {file = "tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897"}, + {file = "tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f"}, + {file = "tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d"}, + {file = "tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5"}, + {file = "tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd"}, + {file = "tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36"}, + {file = "tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd"}, + {file = "tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf"}, + {file = "tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac"}, + {file = "tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662"}, + {file = "tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853"}, + {file = "tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15"}, + {file = "tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba"}, + {file = "tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6"}, + {file = "tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7"}, + {file = "tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232"}, + {file = "tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4"}, + {file = "tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c"}, + {file = "tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d"}, + {file = "tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41"}, + {file = "tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c"}, + {file = "tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f"}, + {file = "tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8"}, + {file = "tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26"}, + {file = "tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396"}, + {file = "tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe"}, + {file = "tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f"}, ] [[package]] diff --git a/airbyte-integrations/connectors/source-gcs/pyproject.toml b/airbyte-integrations/connectors/source-gcs/pyproject.toml index 9fcd85eaa74a..9d51e78cde41 100644 --- a/airbyte-integrations/connectors/source-gcs/pyproject.toml +++ b/airbyte-integrations/connectors/source-gcs/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "0.10.10" +version = "0.10.11" name = "source-gcs" description = "Source implementation for Gcs." authors = [ "Airbyte ",] diff --git a/docs/integrations/sources/gcs.md b/docs/integrations/sources/gcs.md index c61f6ae9fa35..54c01cb4d2cb 100644 --- a/docs/integrations/sources/gcs.md +++ b/docs/integrations/sources/gcs.md @@ -236,6 +236,7 @@ Google Cloud Storage (GCS) supports following file formats: | Version | Date | Pull Request | Subject | |:-----------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0.10.11 | 2026-03-31 | [75690](https://github.com/airbytehq/airbyte/pull/75690) | Update dependencies | | 0.10.10 | 2026-03-24 | [75390](https://github.com/airbytehq/airbyte/pull/75390) | Update dependencies | | 0.10.9 | 2026-03-19 | [74779](https://github.com/airbytehq/airbyte/pull/74779) | Fix ZIP file detection for files with compound extensions (e.g. `.csv.zip`) | | 0.10.8 | 2026-03-18 | [74781](https://github.com/airbytehq/airbyte/pull/74781) | Fix records quadratic duplication | From 429e97ccce7d6edb83973ab59c3d0a742b55be5b Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:41:06 +0000 Subject: [PATCH 145/379] =?UTF-8?q?deps(source-buildkite):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75689)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-buildkite/metadata.yaml | 4 ++-- docs/integrations/sources/buildkite.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-buildkite/metadata.yaml b/airbyte-integrations/connectors/source-buildkite/metadata.yaml index 0e3aaffb0770..15b7d9d38329 100644 --- a/airbyte-integrations/connectors/source-buildkite/metadata.yaml +++ b/airbyte-integrations/connectors/source-buildkite/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-buildkite connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 9b0d6e72-5c85-40a3-af88-3a8f7c65746f - dockerImageTag: 0.0.42 + dockerImageTag: 0.0.43 dockerRepository: airbyte/source-buildkite githubIssueLabel: source-buildkite icon: icon.svg diff --git a/docs/integrations/sources/buildkite.md b/docs/integrations/sources/buildkite.md index 564a55ee3549..dd408215b5fe 100644 --- a/docs/integrations/sources/buildkite.md +++ b/docs/integrations/sources/buildkite.md @@ -38,6 +38,7 @@ Visit `https://buildkite.com/user/api-access-tokens` for getting your bearer tok | Version | Date | Pull Request | Subject | |---------| ------------ | --- | ---------------- | +| 0.0.43 | 2026-03-31 | [75689](https://github.com/airbytehq/airbyte/pull/75689) | Update dependencies | | 0.0.42 | 2026-03-24 | [75324](https://github.com/airbytehq/airbyte/pull/75324) | Update dependencies | | 0.0.41 | 2026-03-10 | [74622](https://github.com/airbytehq/airbyte/pull/74622) | Update dependencies | | 0.0.40 | 2026-03-03 | [74213](https://github.com/airbytehq/airbyte/pull/74213) | Update dependencies | From 326adaf59662b86eea17fe6d638ab660b6e39474 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:41:12 +0000 Subject: [PATCH 146/379] =?UTF-8?q?deps(source-fulcrum):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75688)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-fulcrum/metadata.yaml | 4 ++-- docs/integrations/sources/fulcrum.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-fulcrum/metadata.yaml b/airbyte-integrations/connectors/source-fulcrum/metadata.yaml index 011e4f482f8b..74a94fc2dee5 100644 --- a/airbyte-integrations/connectors/source-fulcrum/metadata.yaml +++ b/airbyte-integrations/connectors/source-fulcrum/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-fulcrum connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 1028d4dc-005b-484b-9164-5a81e0dbac19 - dockerImageTag: 0.0.49 + dockerImageTag: 0.0.50 dockerRepository: airbyte/source-fulcrum githubIssueLabel: source-fulcrum icon: icon.svg diff --git a/docs/integrations/sources/fulcrum.md b/docs/integrations/sources/fulcrum.md index 7ba958c2c1f9..098c416d325a 100644 --- a/docs/integrations/sources/fulcrum.md +++ b/docs/integrations/sources/fulcrum.md @@ -36,6 +36,7 @@ Airbyte connector for Fulcrum would enable seamless data extraction from the Ful | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.50 | 2026-03-31 | [75688](https://github.com/airbytehq/airbyte/pull/75688) | Update dependencies | | 0.0.49 | 2026-03-17 | [74955](https://github.com/airbytehq/airbyte/pull/74955) | Update dependencies | | 0.0.48 | 2026-02-24 | [73762](https://github.com/airbytehq/airbyte/pull/73762) | Update dependencies | | 0.0.47 | 2026-02-10 | [73065](https://github.com/airbytehq/airbyte/pull/73065) | Update dependencies | From 86cb7f91f2c3274b55e7471d48ba53bc2de59be1 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:41:17 +0000 Subject: [PATCH 147/379] =?UTF-8?q?deps(source-bugsnag):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75687)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-bugsnag/metadata.yaml | 4 ++-- docs/integrations/sources/bugsnag.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-bugsnag/metadata.yaml b/airbyte-integrations/connectors/source-bugsnag/metadata.yaml index 8a8f99e761f9..e96fed65c663 100644 --- a/airbyte-integrations/connectors/source-bugsnag/metadata.yaml +++ b/airbyte-integrations/connectors/source-bugsnag/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-bugsnag connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: fa6c7629-0556-4b29-9f2c-7f6f4e54e997 - dockerImageTag: 0.0.44 + dockerImageTag: 0.0.45 dockerRepository: airbyte/source-bugsnag githubIssueLabel: source-bugsnag icon: icon.svg diff --git a/docs/integrations/sources/bugsnag.md b/docs/integrations/sources/bugsnag.md index 3eb32cf9e7c4..fe6304f53631 100644 --- a/docs/integrations/sources/bugsnag.md +++ b/docs/integrations/sources/bugsnag.md @@ -34,6 +34,7 @@ You need to generate the `auth_token` to get started. Personal Auth Tokens can b | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.45 | 2026-03-31 | [75687](https://github.com/airbytehq/airbyte/pull/75687) | Update dependencies | | 0.0.44 | 2026-03-24 | [74937](https://github.com/airbytehq/airbyte/pull/74937) | Update dependencies | | 0.0.43 | 2026-03-10 | [74607](https://github.com/airbytehq/airbyte/pull/74607) | Update dependencies | | 0.0.42 | 2026-03-03 | [73792](https://github.com/airbytehq/airbyte/pull/73792) | Update dependencies | From 680837f85d0f728d1259bbf1ab9b8e841cc32208 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:41:23 +0000 Subject: [PATCH 148/379] =?UTF-8?q?deps(source-buzzsprout):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75686)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-buzzsprout/metadata.yaml | 4 ++-- docs/integrations/sources/buzzsprout.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-buzzsprout/metadata.yaml b/airbyte-integrations/connectors/source-buzzsprout/metadata.yaml index e778e912cd20..19e5920afdbf 100644 --- a/airbyte-integrations/connectors/source-buzzsprout/metadata.yaml +++ b/airbyte-integrations/connectors/source-buzzsprout/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-buzzsprout connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 6ad23bfc-cb11-4faa-a243-f9ccdb0145cc - dockerImageTag: 0.0.44 + dockerImageTag: 0.0.45 dockerRepository: airbyte/source-buzzsprout githubIssueLabel: source-buzzsprout icon: icon.svg diff --git a/docs/integrations/sources/buzzsprout.md b/docs/integrations/sources/buzzsprout.md index f0e4daebe76a..08cf39ec0e47 100644 --- a/docs/integrations/sources/buzzsprout.md +++ b/docs/integrations/sources/buzzsprout.md @@ -30,6 +30,7 @@ Visit `https://github.com/buzzsprout/buzzsprout-api/tree/master?tab=readme-ov-fi | Version | Date | Pull Request | Subject | | ------------------ | ------------ | --- | ---------------- | +| 0.0.45 | 2026-03-31 | [75686](https://github.com/airbytehq/airbyte/pull/75686) | Update dependencies | | 0.0.44 | 2026-03-24 | [75320](https://github.com/airbytehq/airbyte/pull/75320) | Update dependencies | | 0.0.43 | 2026-03-10 | [74633](https://github.com/airbytehq/airbyte/pull/74633) | Update dependencies | | 0.0.42 | 2026-03-03 | [74216](https://github.com/airbytehq/airbyte/pull/74216) | Update dependencies | From a5aa7c664901905523df58aae6ec28f7cd2c10d1 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:41:28 +0000 Subject: [PATCH 149/379] =?UTF-8?q?deps(source-jobnimbus):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75685)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-jobnimbus/metadata.yaml | 4 ++-- docs/integrations/sources/jobnimbus.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-jobnimbus/metadata.yaml b/airbyte-integrations/connectors/source-jobnimbus/metadata.yaml index 00ebfe885d0a..ce748bd585b6 100644 --- a/airbyte-integrations/connectors/source-jobnimbus/metadata.yaml +++ b/airbyte-integrations/connectors/source-jobnimbus/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-jobnimbus connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 0b98589b-ccee-40fd-9e9d-28d94087b4e1 - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-jobnimbus githubIssueLabel: source-jobnimbus icon: icon.svg diff --git a/docs/integrations/sources/jobnimbus.md b/docs/integrations/sources/jobnimbus.md index 4364d2bbaa52..85a8b7bc50ec 100644 --- a/docs/integrations/sources/jobnimbus.md +++ b/docs/integrations/sources/jobnimbus.md @@ -23,6 +23,7 @@ The JobNimbus Airbyte connector enables seamless integration between JobNimbus, | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.48 | 2026-03-31 | [75685](https://github.com/airbytehq/airbyte/pull/75685) | Update dependencies | | 0.0.47 | 2026-03-24 | [75346](https://github.com/airbytehq/airbyte/pull/75346) | Update dependencies | | 0.0.46 | 2026-03-10 | [74494](https://github.com/airbytehq/airbyte/pull/74494) | Update dependencies | | 0.0.45 | 2026-02-24 | [73896](https://github.com/airbytehq/airbyte/pull/73896) | Update dependencies | From ae17e0a179ef461b42701224eb39dc8652842517 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:41:34 +0000 Subject: [PATCH 150/379] =?UTF-8?q?deps(source-cal-com):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75684)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-cal-com/metadata.yaml | 4 ++-- docs/integrations/sources/cal-com.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-cal-com/metadata.yaml b/airbyte-integrations/connectors/source-cal-com/metadata.yaml index 985c3b2e7419..b924ccb5e179 100644 --- a/airbyte-integrations/connectors/source-cal-com/metadata.yaml +++ b/airbyte-integrations/connectors/source-cal-com/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-cal-com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 3db8a652-88f7-41ee-91a3-2f745322d9ae - dockerImageTag: 0.0.45 + dockerImageTag: 0.0.46 dockerRepository: airbyte/source-cal-com githubIssueLabel: source-cal-com icon: icon.svg diff --git a/docs/integrations/sources/cal-com.md b/docs/integrations/sources/cal-com.md index 92e065db3744..e04bd08265a5 100644 --- a/docs/integrations/sources/cal-com.md +++ b/docs/integrations/sources/cal-com.md @@ -25,6 +25,7 @@ The Cal.com connector enables seamless data synchronization between Cal.com’s | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.46 | 2026-03-31 | [75684](https://github.com/airbytehq/airbyte/pull/75684) | Update dependencies | | 0.0.45 | 2026-03-17 | [74941](https://github.com/airbytehq/airbyte/pull/74941) | Update dependencies | | 0.0.44 | 2026-03-10 | [74603](https://github.com/airbytehq/airbyte/pull/74603) | Update dependencies | | 0.0.43 | 2026-02-03 | [72081](https://github.com/airbytehq/airbyte/pull/72081) | Update dependencies | From d859a1e1ebcec2ac595066ea2defa91752e1eb0f Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:41:40 +0000 Subject: [PATCH 151/379] =?UTF-8?q?deps(source-jamf-pro):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75682)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-jamf-pro/metadata.yaml | 4 ++-- docs/integrations/sources/jamf-pro.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-jamf-pro/metadata.yaml b/airbyte-integrations/connectors/source-jamf-pro/metadata.yaml index 621db3ec7dcc..ee18882a6425 100644 --- a/airbyte-integrations/connectors/source-jamf-pro/metadata.yaml +++ b/airbyte-integrations/connectors/source-jamf-pro/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-jamf-pro connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: b3342a5d-2c62-4ac7-8145-d0403dd3b7ec - dockerImageTag: 0.0.31 + dockerImageTag: 0.0.32 dockerRepository: airbyte/source-jamf-pro githubIssueLabel: source-jamf-pro icon: icon.svg diff --git a/docs/integrations/sources/jamf-pro.md b/docs/integrations/sources/jamf-pro.md index 9979d216e0ae..9418aa7612ad 100644 --- a/docs/integrations/sources/jamf-pro.md +++ b/docs/integrations/sources/jamf-pro.md @@ -21,6 +21,7 @@ Mobile device management | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.32 | 2026-03-31 | [75682](https://github.com/airbytehq/airbyte/pull/75682) | Update dependencies | | 0.0.31 | 2026-03-17 | [75078](https://github.com/airbytehq/airbyte/pull/75078) | Update dependencies | | 0.0.30 | 2026-03-10 | [74506](https://github.com/airbytehq/airbyte/pull/74506) | Update dependencies | | 0.0.29 | 2026-03-03 | [74175](https://github.com/airbytehq/airbyte/pull/74175) | Update dependencies | From 2568a7481f08ba20455be847653f063b7dd96873 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:41:44 +0000 Subject: [PATCH 152/379] =?UTF-8?q?deps(source-google-analytics-data-api):?= =?UTF-8?q?=20=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#7567?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-google-analytics-data-api/metadata.yaml | 4 ++-- docs/integrations/sources/google-analytics-data-api.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-google-analytics-data-api/metadata.yaml b/airbyte-integrations/connectors/source-google-analytics-data-api/metadata.yaml index 4a717ac99a0c..ef94a635ed1c 100644 --- a/airbyte-integrations/connectors/source-google-analytics-data-api/metadata.yaml +++ b/airbyte-integrations/connectors/source-google-analytics-data-api/metadata.yaml @@ -8,11 +8,11 @@ data: - www.googleapis.com - analyticsdata.googleapis.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 3cc2eafd-84aa-4dca-93af-322d9dfeec1a - dockerImageTag: 2.9.27 + dockerImageTag: 2.9.28 dockerRepository: airbyte/source-google-analytics-data-api documentationUrl: https://docs.airbyte.com/integrations/sources/google-analytics-data-api externalDocumentationUrls: diff --git a/docs/integrations/sources/google-analytics-data-api.md b/docs/integrations/sources/google-analytics-data-api.md index 8b20f369305c..044f2a0373a9 100644 --- a/docs/integrations/sources/google-analytics-data-api.md +++ b/docs/integrations/sources/google-analytics-data-api.md @@ -280,6 +280,7 @@ The Google Analytics connector is subject to Google Analytics Data API quotas. P | Version | Date | Pull Request | Subject | |:---------------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 2.9.28 | 2026-03-31 | [75678](https://github.com/airbytehq/airbyte/pull/75678) | Update dependencies | | 2.9.27 | 2026-03-24 | [74568](https://github.com/airbytehq/airbyte/pull/74568) | Update dependencies | | 2.9.26 | 2026-02-25 | [73632](https://github.com/airbytehq/airbyte/pull/73632) | fix(source-google-analytics-data-api): use GA4 today keyword for timezone-correct end dates (AI-Triage PR) | | 2.9.25 | 2026-02-24 | [73750](https://github.com/airbytehq/airbyte/pull/73750) | Update dependencies | From b7c9ea67af1435341c615a8afc1b5f1f52eec1e3 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:41:57 +0000 Subject: [PATCH 153/379] =?UTF-8?q?deps(source-google-drive):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75368)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../source-google-drive/metadata.yaml | 2 +- .../source-google-drive/poetry.lock | 869 +++++++++--------- .../source-google-drive/pyproject.toml | 2 +- docs/integrations/sources/google-drive.md | 1 + 4 files changed, 440 insertions(+), 434 deletions(-) diff --git a/airbyte-integrations/connectors/source-google-drive/metadata.yaml b/airbyte-integrations/connectors/source-google-drive/metadata.yaml index 2f944d29691c..70e249259973 100644 --- a/airbyte-integrations/connectors/source-google-drive/metadata.yaml +++ b/airbyte-integrations/connectors/source-google-drive/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: file connectorType: source definitionId: 9f8dda77-1048-4368-815b-269bf54ee9b8 - dockerImageTag: 0.5.12 + dockerImageTag: 0.5.13 dockerRepository: airbyte/source-google-drive githubIssueLabel: source-google-drive icon: google-drive.svg diff --git a/airbyte-integrations/connectors/source-google-drive/poetry.lock b/airbyte-integrations/connectors/source-google-drive/poetry.lock index 172945feb2d1..fecc1f7077d0 100644 --- a/airbyte-integrations/connectors/source-google-drive/poetry.lock +++ b/airbyte-integrations/connectors/source-google-drive/poetry.lock @@ -2,13 +2,13 @@ [[package]] name = "airbyte-cdk" -version = "7.13.0" +version = "7.14.0" description = "A framework for writing Airbyte Connectors." optional = false python-versions = "<3.14,>=3.10" files = [ - {file = "airbyte_cdk-7.13.0-py3-none-any.whl", hash = "sha256:ede4018f0ce912102a7698daa6e1a793e0c8cd3f8c3456429d038951cca3a339"}, - {file = "airbyte_cdk-7.13.0.tar.gz", hash = "sha256:2b6cea3862509ab095beb19524dae78e2b24f3b356891e0a1e24f8854d8c124e"}, + {file = "airbyte_cdk-7.14.0-py3-none-any.whl", hash = "sha256:306d48d03eaf3c2a5ac46a806bc9b45c90fb1e36f57d6029e5b9e13c508a82c8"}, + {file = "airbyte_cdk-7.14.0.tar.gz", hash = "sha256:19948896aac82b1d47500742e2d1f3fb529984bdad07d484e38c49c9d56ace0a"}, ] [package.dependencies] @@ -118,13 +118,13 @@ files = [ [[package]] name = "attrs" -version = "25.4.0" +version = "26.1.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.9" files = [ - {file = "attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373"}, - {file = "attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11"}, + {file = "attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309"}, + {file = "attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32"}, ] [[package]] @@ -344,38 +344,43 @@ pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} [[package]] name = "chardet" -version = "7.1.0" +version = "7.4.0.post2" description = "Universal character encoding detector" optional = false python-versions = ">=3.10" files = [ - {file = "chardet-7.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dff284d0661563e82d235f79f1d410c526b15ef8d50adc0446cba8162db68d22"}, - {file = "chardet-7.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:00c3182f739ae7715641e8c08e0ee8ae21b5db6402b883264aa04511edf428b9"}, - {file = "chardet-7.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18afc27681cd9f583fac47282179f8b73f37b1cab171a528e8af89e7e4562b32"}, - {file = "chardet-7.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20b73403b7a21487e31b2810ea9d7182ce5e301a8ebe847b49d91ec6022e214a"}, - {file = "chardet-7.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:97cdd7a016fbb451a4dc26b3b1173960b3c0071bbe46a46d6b70027a517170ff"}, - {file = "chardet-7.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:70adef4a036d39d9b5f6c2702f773118a9985c0dff23b650e1045f20e33c9467"}, - {file = "chardet-7.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e067ee79709ccf9caa5732419df2dbef476bd9b9658ffc929d45cf13fc91ed7"}, - {file = "chardet-7.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb2a9b4052be006b87a985dbdbb00ab35b4b1b66d2751b0ee12680f8f4e90406"}, - {file = "chardet-7.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49b5edd762751735704d1fec38665ee219da28c66f2a4921d615b12be389735b"}, - {file = "chardet-7.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:a02197831a4304eed360559e0ffc58deccc9cdda9f9315c6e7ad978f7d8617d3"}, - {file = "chardet-7.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:43c1e3cba6c41d8958ee4acdab94c151dbe256d7ef8df4ae032dc62a892f294f"}, - {file = "chardet-7.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1a3c22672c9502af99e0433b47421d0d72c8803efce2cd4a91a3ae1ab5972243"}, - {file = "chardet-7.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fdfc42dfc44ccd569b84fe6a1fdea1df66dc0c48461bc3899dea5efea8d507f6"}, - {file = "chardet-7.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e096d9c211050fff40e22748e1d09d0cec8348fc13ee6e2e0a1da079345b8a86"}, - {file = "chardet-7.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:a6492bebaba8882afb3e14c786fb69ed767326b6f514b8e093dcdf6e2a094d33"}, - {file = "chardet-7.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cc8c7520a9736da766f5794bbabb1c6cdfe446676429a5cf691af878631a80bf"}, - {file = "chardet-7.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6f806f325825325e0682226269a2a4859993344cccca14f2463855d4f5a93272"}, - {file = "chardet-7.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bacc8f862998c59e9ee7fe4960538300d1cc3fe2c293b9cc99bbbc7bf3bedf51"}, - {file = "chardet-7.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d17822fc94467b7951adebd897cb01c0e37ac694be18d2cbd2b676d61df4f"}, - {file = "chardet-7.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:b951107b254cdc766e52f4b8339dcfa97c7b45ca9f5509075308db2497e7f3af"}, - {file = "chardet-7.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:619d7ef3187ff1691525a7fdbe8c30f5a519885e1de82f6f57e26a29866bf11b"}, - {file = "chardet-7.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:96e7fe0770cd77361bec21a1dd8524e77aaa567577fa8372368d5fa8dd0ef00b"}, - {file = "chardet-7.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bbd4fccf1cf6d92fdd75a1827a478672abb5685e61e92ce863d9380b18cb813f"}, - {file = "chardet-7.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5d86d349f768e6d35f6804013f6643d880ec877b94c453fa40a3fd10d16ddb48"}, - {file = "chardet-7.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:38be4c07e016dac37fb6060094f3a720200e3e49dc14f55924a1c230eeffa59f"}, - {file = "chardet-7.1.0-py3-none-any.whl", hash = "sha256:7f677725333bf53f84b7f57458f44669a8a5eb2ac4092ac699cdfa9b1af08a5f"}, - {file = "chardet-7.1.0.tar.gz", hash = "sha256:8f47bc4accac17bd9accbb4acc1d563acc024a783806c0a43c3a583f5285690b"}, + {file = "chardet-7.4.0.post2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:77170d229f3d7babbc36c5a33c361de1c01091f4564a33bcd7e0f59ee8609b2a"}, + {file = "chardet-7.4.0.post2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9be8a6ba814f65013e0e6d92a43e8fa50f42c8850c143fa74586baeac5fa1bcd"}, + {file = "chardet-7.4.0.post2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:28807a1209b7c2b79b24bdf9722b381e81da8104ae17fe2bd1e9f01c87fe9071"}, + {file = "chardet-7.4.0.post2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6ade174e3fe29f1f4abdb3cc47add0a98201452c43786cbf324b5e237a0c79fc"}, + {file = "chardet-7.4.0.post2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:335d9cedd5b5be4b8b39ec25b1c2e4498ac4e8658c9466b68b4417cf07c8c4ee"}, + {file = "chardet-7.4.0.post2-cp310-cp310-win_amd64.whl", hash = "sha256:cde31d2314b156404380aca8aa0bdf6395bc92998b25336076b8a588c267fb20"}, + {file = "chardet-7.4.0.post2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:90227bc83d06d16b548afe185e93eff8c740cb11ec51536366399b912e361b8d"}, + {file = "chardet-7.4.0.post2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:18cb15facd3a70042cb4d3b9a80dd2e9b8d78af90643f434047060e1f84dff06"}, + {file = "chardet-7.4.0.post2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e719bf17854051970938e260d2c589fe3fde3da0a681acdafd266e3bbf75c1af"}, + {file = "chardet-7.4.0.post2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24b8fcc1fe54936932f305522bc2f40a207ecbb38209fa24226eab7432531aef"}, + {file = "chardet-7.4.0.post2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2c748b2850c8376ef04b02b3f22e014da5edc961478c88ccc6b01d3eed9bc1e7"}, + {file = "chardet-7.4.0.post2-cp311-cp311-win_amd64.whl", hash = "sha256:a359eb4535aeabd3f61e599530c4c4d4855c31316e6fed7db619a9c58785ee38"}, + {file = "chardet-7.4.0.post2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7aced16fe8098019c7c513dd92e9ee3ad29fffac757fa7de13ff8f3a8607a344"}, + {file = "chardet-7.4.0.post2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dc6829803ba71cb427dffac03a948ae828c617710bbd5f97ae3b34ab18558414"}, + {file = "chardet-7.4.0.post2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:46659d38ba18e7c740f10a4c2edd0ef112e0322606ab2570cb8fd387954e0de9"}, + {file = "chardet-7.4.0.post2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5933289313b8cbfb0d07cf44583a2a6c7e31bffe5dcb7ebb6592825aa197d5b0"}, + {file = "chardet-7.4.0.post2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2b99b417fac30641429829666ee7331366e797863504260aa1b18bfc2020e4e3"}, + {file = "chardet-7.4.0.post2-cp312-cp312-win_amd64.whl", hash = "sha256:a07dc1257fef2685dfc5182229abccd3f9b1299006a5b4d43ac7bd252faa1118"}, + {file = "chardet-7.4.0.post2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9bdb9387e692dd53c837aa922f676e5ab51209895cd99b15d30c6004418e0d27"}, + {file = "chardet-7.4.0.post2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:422ac637f5a2a8b13151245591cb0fabdf9ec1427725f0560628cb5ad4fb1462"}, + {file = "chardet-7.4.0.post2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7d52b3f15249ba877030045900d179d44552c3c37dda487462be473ec67bed2f"}, + {file = "chardet-7.4.0.post2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccdfb13b4a727d3d944157c7f350c6d64630511a0ce39e37ffa5114e90f7d3a7"}, + {file = "chardet-7.4.0.post2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:daae5b0579e7e33adacb4722a62b540e6bec49944e081a859cb9a6a010713817"}, + {file = "chardet-7.4.0.post2-cp313-cp313-win_amd64.whl", hash = "sha256:6c448fe2d77e329cec421b95f844b75f8c9cb744e808ecc9124b6063ca6acb5e"}, + {file = "chardet-7.4.0.post2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:5862b17677f7e8fcee4e37fe641f01d30762e4b075ac37ce9584e4407896e2d9"}, + {file = "chardet-7.4.0.post2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:22d05c4b7e721d5330d99ef4a6f6233a9de58ae6f2275c21a098bedd778a6cb7"}, + {file = "chardet-7.4.0.post2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a035d407f762c21eb77069982425eb403e518dd758617aa43bf11d0d2203a1b6"}, + {file = "chardet-7.4.0.post2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2adfa7390e69cb5ed499b54978d31f6d476788d07d83da3426811181b7ca7682"}, + {file = "chardet-7.4.0.post2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2345f20ea67cdadddb778b2bc31e2defc2a85ae027931f9ad6ab84fd5d345320"}, + {file = "chardet-7.4.0.post2-cp314-cp314-win_amd64.whl", hash = "sha256:52602972d4815047cee262551bc383ab394aa145f5ca9ee10d0a53d27965882e"}, + {file = "chardet-7.4.0.post2-py3-none-any.whl", hash = "sha256:e0c9c6b5c296c0e5197bc8876fcc04d58a6ddfba18399e598ba353aba28b038e"}, + {file = "chardet-7.4.0.post2.tar.gz", hash = "sha256:21a6b5ca695252c03385dcfcc8b55c27907f1fe80838aa171b1ff4e356a1bb67"}, ] [[package]] @@ -762,13 +767,13 @@ typing-inspect = ">=0.4.0,<1" [[package]] name = "dateparser" -version = "1.3.0" +version = "1.4.0" description = "Date parsing library designed to parse dates from HTML pages" optional = false python-versions = ">=3.10" files = [ - {file = "dateparser-1.3.0-py3-none-any.whl", hash = "sha256:8dc678b0a526e103379f02ae44337d424bd366aac727d3c6cf52ce1b01efbb5a"}, - {file = "dateparser-1.3.0.tar.gz", hash = "sha256:5bccf5d1ec6785e5be71cc7ec80f014575a09b4923e762f850e57443bddbf1a5"}, + {file = "dateparser-1.4.0-py3-none-any.whl", hash = "sha256:7902b8e85d603494bf70a5a0b1decdddb2270b9c6e6b2bc8a57b93476c0df378"}, + {file = "dateparser-1.4.0.tar.gz", hash = "sha256:97a21840d5ecdf7630c584f673338a5afac5dfe84f647baf4d7e8df98f9354a4"}, ] [package.dependencies] @@ -934,18 +939,18 @@ files = [ [[package]] name = "google-api-core" -version = "2.30.0" +version = "2.30.1" description = "Google API client core library" optional = false python-versions = ">=3.9" files = [ - {file = "google_api_core-2.30.0-py3-none-any.whl", hash = "sha256:80be49ee937ff9aba0fd79a6eddfde35fe658b9953ab9b79c57dd7061afa8df5"}, - {file = "google_api_core-2.30.0.tar.gz", hash = "sha256:02edfa9fab31e17fc0befb5f161b3bf93c9096d99aed584625f38065c511ad9b"}, + {file = "google_api_core-2.30.1-py3-none-any.whl", hash = "sha256:3be893babbb54a89c6807b598383ddf212112130e3d24d06c681b5d18f082e08"}, + {file = "google_api_core-2.30.1.tar.gz", hash = "sha256:7304ef3bd7e77fd26320a36eeb75868f9339532bfea21694964f4765b37574ee"}, ] [package.dependencies] google-auth = ">=2.14.1,<3.0.0" -googleapis-common-protos = ">=1.56.3,<2.0.0" +googleapis-common-protos = ">=1.63.2,<2.0.0" grpcio = [ {version = ">=1.49.1,<2.0.0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, {version = ">=1.33.2,<2.0.0", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, @@ -1060,17 +1065,17 @@ tool = ["click (>=6.0.0)"] [[package]] name = "google-cloud-secret-manager" -version = "2.26.0" +version = "2.27.0" description = "Google Cloud Secret Manager API client library" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "google_cloud_secret_manager-2.26.0-py3-none-any.whl", hash = "sha256:940a5447a6ec9951446fd1a0f22c81a4303fde164cd747aae152c5f5c8e6723e"}, - {file = "google_cloud_secret_manager-2.26.0.tar.gz", hash = "sha256:0d1d6f76327685a0ed78a4cf50f289e1bfbbe56026ed0affa98663b86d6d50d6"}, + {file = "google_cloud_secret_manager-2.27.0-py3-none-any.whl", hash = "sha256:e5540bece65a3ad720146f3b438973faf9315109b3ffa012a58711843047a3dc"}, + {file = "google_cloud_secret_manager-2.27.0.tar.gz", hash = "sha256:6af864c252bd3c11db7bb02b80cb0b14a8c9a33fc7ec4d6f245f33d8ce1f7cd1"}, ] [package.dependencies] -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0", extras = ["grpc"]} +google-api-core = {version = ">=2.11.0,<3.0.0", extras = ["grpc"]} google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0" grpc-google-iam-v1 = ">=0.14.0,<1.0.0" grpcio = ">=1.33.2,<2.0.0" @@ -1078,22 +1083,22 @@ proto-plus = [ {version = ">=1.25.0,<2.0.0", markers = "python_version >= \"3.13\""}, {version = ">=1.22.3,<2.0.0", markers = "python_version < \"3.13\""}, ] -protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0" +protobuf = ">=4.25.8,<8.0.0" [[package]] name = "googleapis-common-protos" -version = "1.73.0" +version = "1.73.1" description = "Common protobufs used in Google APIs" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "googleapis_common_protos-1.73.0-py3-none-any.whl", hash = "sha256:dfdaaa2e860f242046be561e6d6cb5c5f1541ae02cfbcb034371aadb2942b4e8"}, - {file = "googleapis_common_protos-1.73.0.tar.gz", hash = "sha256:778d07cd4fbeff84c6f7c72102f0daf98fa2bfd3fa8bea426edc545588da0b5a"}, + {file = "googleapis_common_protos-1.73.1-py3-none-any.whl", hash = "sha256:e51f09eb0a43a8602f5a915870972e6b4a394088415c79d79605a46d8e826ee8"}, + {file = "googleapis_common_protos-1.73.1.tar.gz", hash = "sha256:13114f0e9d2391756a0194c3a8131974ed7bffb06086569ba193364af59163b6"}, ] [package.dependencies] grpcio = {version = ">=1.44.0,<2.0.0", optional = true, markers = "extra == \"grpc\""} -protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0" +protobuf = ">=4.25.8,<8.0.0" [package.extras] grpc = ["grpcio (>=1.44.0,<2.0.0)"] @@ -1116,94 +1121,94 @@ protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4 [[package]] name = "grpcio" -version = "1.78.0" +version = "1.80.0" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.9" files = [ - {file = "grpcio-1.78.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:7cc47943d524ee0096f973e1081cb8f4f17a4615f2116882a5f1416e4cfe92b5"}, - {file = "grpcio-1.78.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:c3f293fdc675ccba4db5a561048cca627b5e7bd1c8a6973ffedabe7d116e22e2"}, - {file = "grpcio-1.78.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:10a9a644b5dd5aec3b82b5b0b90d41c0fa94c85ef42cb42cf78a23291ddb5e7d"}, - {file = "grpcio-1.78.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4c5533d03a6cbd7f56acfc9cfb44ea64f63d29091e40e44010d34178d392d7eb"}, - {file = "grpcio-1.78.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ff870aebe9a93a85283837801d35cd5f8814fe2ad01e606861a7fb47c762a2b7"}, - {file = "grpcio-1.78.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:391e93548644e6b2726f1bb84ed60048d4bcc424ce5e4af0843d28ca0b754fec"}, - {file = "grpcio-1.78.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:df2c8f3141f7cbd112a6ebbd760290b5849cda01884554f7c67acc14e7b1758a"}, - {file = "grpcio-1.78.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd8cb8026e5f5b50498a3c4f196f57f9db344dad829ffae16b82e4fdbaea2813"}, - {file = "grpcio-1.78.0-cp310-cp310-win32.whl", hash = "sha256:f8dff3d9777e5d2703a962ee5c286c239bf0ba173877cc68dc02c17d042e29de"}, - {file = "grpcio-1.78.0-cp310-cp310-win_amd64.whl", hash = "sha256:94f95cf5d532d0e717eed4fc1810e8e6eded04621342ec54c89a7c2f14b581bf"}, - {file = "grpcio-1.78.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:2777b783f6c13b92bd7b716667452c329eefd646bfb3f2e9dabea2e05dbd34f6"}, - {file = "grpcio-1.78.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:9dca934f24c732750389ce49d638069c3892ad065df86cb465b3fa3012b70c9e"}, - {file = "grpcio-1.78.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:459ab414b35f4496138d0ecd735fed26f1318af5e52cb1efbc82a09f0d5aa911"}, - {file = "grpcio-1.78.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:082653eecbdf290e6e3e2c276ab2c54b9e7c299e07f4221872380312d8cf395e"}, - {file = "grpcio-1.78.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85f93781028ec63f383f6bc90db785a016319c561cc11151fbb7b34e0d012303"}, - {file = "grpcio-1.78.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f12857d24d98441af6a1d5c87442d624411db486f7ba12550b07788f74b67b04"}, - {file = "grpcio-1.78.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5397fff416b79e4b284959642a4e95ac4b0f1ece82c9993658e0e477d40551ec"}, - {file = "grpcio-1.78.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fbe6e89c7ffb48518384068321621b2a69cab509f58e40e4399fdd378fa6d074"}, - {file = "grpcio-1.78.0-cp311-cp311-win32.whl", hash = "sha256:6092beabe1966a3229f599d7088b38dfc8ffa1608b5b5cdda31e591e6500f856"}, - {file = "grpcio-1.78.0-cp311-cp311-win_amd64.whl", hash = "sha256:1afa62af6e23f88629f2b29ec9e52ec7c65a7176c1e0a83292b93c76ca882558"}, - {file = "grpcio-1.78.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:f9ab915a267fc47c7e88c387a3a28325b58c898e23d4995f765728f4e3dedb97"}, - {file = "grpcio-1.78.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3f8904a8165ab21e07e58bf3e30a73f4dffc7a1e0dbc32d51c61b5360d26f43e"}, - {file = "grpcio-1.78.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:859b13906ce098c0b493af92142ad051bf64c7870fa58a123911c88606714996"}, - {file = "grpcio-1.78.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b2342d87af32790f934a79c3112641e7b27d63c261b8b4395350dad43eff1dc7"}, - {file = "grpcio-1.78.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:12a771591ae40bc65ba67048fa52ef4f0e6db8279e595fd349f9dfddeef571f9"}, - {file = "grpcio-1.78.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:185dea0d5260cbb2d224c507bf2a5444d5abbb1fa3594c1ed7e4c709d5eb8383"}, - {file = "grpcio-1.78.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:51b13f9aed9d59ee389ad666b8c2214cc87b5de258fa712f9ab05f922e3896c6"}, - {file = "grpcio-1.78.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fd5f135b1bd58ab088930b3c613455796dfa0393626a6972663ccdda5b4ac6ce"}, - {file = "grpcio-1.78.0-cp312-cp312-win32.whl", hash = "sha256:94309f498bcc07e5a7d16089ab984d42ad96af1d94b5a4eb966a266d9fcabf68"}, - {file = "grpcio-1.78.0-cp312-cp312-win_amd64.whl", hash = "sha256:9566fe4ababbb2610c39190791e5b829869351d14369603702e890ef3ad2d06e"}, - {file = "grpcio-1.78.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:ce3a90455492bf8bfa38e56fbbe1dbd4f872a3d8eeaf7337dc3b1c8aa28c271b"}, - {file = "grpcio-1.78.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:2bf5e2e163b356978b23652c4818ce4759d40f4712ee9ec5a83c4be6f8c23a3a"}, - {file = "grpcio-1.78.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8f2ac84905d12918e4e55a16da17939eb63e433dc11b677267c35568aa63fc84"}, - {file = "grpcio-1.78.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b58f37edab4a3881bc6c9bca52670610e0c9ca14e2ea3cf9debf185b870457fb"}, - {file = "grpcio-1.78.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:735e38e176a88ce41840c21bb49098ab66177c64c82426e24e0082500cc68af5"}, - {file = "grpcio-1.78.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2045397e63a7a0ee7957c25f7dbb36ddc110e0cfb418403d110c0a7a68a844e9"}, - {file = "grpcio-1.78.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a9f136fbafe7ccf4ac7e8e0c28b31066e810be52d6e344ef954a3a70234e1702"}, - {file = "grpcio-1.78.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:748b6138585379c737adc08aeffd21222abbda1a86a0dca2a39682feb9196c20"}, - {file = "grpcio-1.78.0-cp313-cp313-win32.whl", hash = "sha256:271c73e6e5676afe4fc52907686670c7cea22ab2310b76a59b678403ed40d670"}, - {file = "grpcio-1.78.0-cp313-cp313-win_amd64.whl", hash = "sha256:f2d4e43ee362adfc05994ed479334d5a451ab7bc3f3fee1b796b8ca66895acb4"}, - {file = "grpcio-1.78.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:e87cbc002b6f440482b3519e36e1313eb5443e9e9e73d6a52d43bd2004fcfd8e"}, - {file = "grpcio-1.78.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:c41bc64626db62e72afec66b0c8a0da76491510015417c127bfc53b2fe6d7f7f"}, - {file = "grpcio-1.78.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8dfffba826efcf366b1e3ccc37e67afe676f290e13a3b48d31a46739f80a8724"}, - {file = "grpcio-1.78.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:74be1268d1439eaaf552c698cdb11cd594f0c49295ae6bb72c34ee31abbe611b"}, - {file = "grpcio-1.78.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be63c88b32e6c0f1429f1398ca5c09bc64b0d80950c8bb7807d7d7fb36fb84c7"}, - {file = "grpcio-1.78.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:3c586ac70e855c721bda8f548d38c3ca66ac791dc49b66a8281a1f99db85e452"}, - {file = "grpcio-1.78.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:35eb275bf1751d2ffbd8f57cdbc46058e857cf3971041521b78b7db94bdaf127"}, - {file = "grpcio-1.78.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:207db540302c884b8848036b80db352a832b99dfdf41db1eb554c2c2c7800f65"}, - {file = "grpcio-1.78.0-cp314-cp314-win32.whl", hash = "sha256:57bab6deef2f4f1ca76cc04565df38dc5713ae6c17de690721bdf30cb1e0545c"}, - {file = "grpcio-1.78.0-cp314-cp314-win_amd64.whl", hash = "sha256:dce09d6116df20a96acfdbf85e4866258c3758180e8c49845d6ba8248b6d0bbb"}, - {file = "grpcio-1.78.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:86f85dd7c947baa707078a236288a289044836d4b640962018ceb9cd1f899af5"}, - {file = "grpcio-1.78.0-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:de8cb00d1483a412a06394b8303feec5dcb3b55f81d83aa216dbb6a0b86a94f5"}, - {file = "grpcio-1.78.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e888474dee2f59ff68130f8a397792d8cb8e17e6b3434339657ba4ee90845a8c"}, - {file = "grpcio-1.78.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:86ce2371bfd7f212cf60d8517e5e854475c2c43ce14aa910e136ace72c6db6c1"}, - {file = "grpcio-1.78.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b0c689c02947d636bc7fab3e30cc3a3445cca99c834dfb77cd4a6cabfc1c5597"}, - {file = "grpcio-1.78.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ce7599575eeb25c0f4dc1be59cada6219f3b56176f799627f44088b21381a28a"}, - {file = "grpcio-1.78.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:684083fd383e9dc04c794adb838d4faea08b291ce81f64ecd08e4577c7398adf"}, - {file = "grpcio-1.78.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ab399ef5e3cd2a721b1038a0f3021001f19c5ab279f145e1146bb0b9f1b2b12c"}, - {file = "grpcio-1.78.0-cp39-cp39-win32.whl", hash = "sha256:f3d6379493e18ad4d39537a82371c5281e153e963cecb13f953ebac155756525"}, - {file = "grpcio-1.78.0-cp39-cp39-win_amd64.whl", hash = "sha256:5361a0630a7fdb58a6a97638ab70e1dae2893c4d08d7aba64ded28bb9e7a29df"}, - {file = "grpcio-1.78.0.tar.gz", hash = "sha256:7382b95189546f375c174f53a5fa873cef91c4b8005faa05cc5b3beea9c4f1c5"}, + {file = "grpcio-1.80.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:886457a7768e408cdce226ad1ca67d2958917d306523a0e21e1a2fdaa75c9c9c"}, + {file = "grpcio-1.80.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:7b641fc3f1dc647bfd80bd713addc68f6d145956f64677e56d9ebafc0bd72388"}, + {file = "grpcio-1.80.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:33eb763f18f006dc7fee1e69831d38d23f5eccd15b2e0f92a13ee1d9242e5e02"}, + {file = "grpcio-1.80.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:52d143637e3872633fc7dd7c3c6a1c84e396b359f3a72e215f8bf69fd82084fc"}, + {file = "grpcio-1.80.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c51bf8ac4575af2e0678bccfb07e47321fc7acb5049b4482832c5c195e04e13a"}, + {file = "grpcio-1.80.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:50a9871536d71c4fba24ee856abc03a87764570f0c457dd8db0b4018f379fed9"}, + {file = "grpcio-1.80.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a72d84ad0514db063e21887fbacd1fd7acb4d494a564cae22227cd45c7fbf199"}, + {file = "grpcio-1.80.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f7691a6788ad9196872f95716df5bc643ebba13c97140b7a5ee5c8e75d1dea81"}, + {file = "grpcio-1.80.0-cp310-cp310-win32.whl", hash = "sha256:46c2390b59d67f84e882694d489f5b45707c657832d7934859ceb8c33f467069"}, + {file = "grpcio-1.80.0-cp310-cp310-win_amd64.whl", hash = "sha256:dc053420fc75749c961e2a4c906398d7c15725d36ccc04ae6d16093167223b58"}, + {file = "grpcio-1.80.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:dfab85db094068ff42e2a3563f60ab3dddcc9d6488a35abf0132daec13209c8a"}, + {file = "grpcio-1.80.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:5c07e82e822e1161354e32da2662f741a4944ea955f9f580ec8fb409dd6f6060"}, + {file = "grpcio-1.80.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba0915d51fd4ced2db5ff719f84e270afe0e2d4c45a7bdb1e8d036e4502928c2"}, + {file = "grpcio-1.80.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:3cb8130ba457d2aa09fa6b7c3ed6b6e4e6a2685fce63cb803d479576c4d80e21"}, + {file = "grpcio-1.80.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:09e5e478b3d14afd23f12e49e8b44c8684ac3c5f08561c43a5b9691c54d136ab"}, + {file = "grpcio-1.80.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:00168469238b022500e486c1c33916acf2f2a9b2c022202cf8a1885d2e3073c1"}, + {file = "grpcio-1.80.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8502122a3cc1714038e39a0b071acb1207ca7844208d5ea0d091317555ee7106"}, + {file = "grpcio-1.80.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ce1794f4ea6cc3ca29463f42d665c32ba1b964b48958a66497917fe9069f26e6"}, + {file = "grpcio-1.80.0-cp311-cp311-win32.whl", hash = "sha256:51b4a7189b0bef2aa30adce3c78f09c83526cf3dddb24c6a96555e3b97340440"}, + {file = "grpcio-1.80.0-cp311-cp311-win_amd64.whl", hash = "sha256:02e64bb0bb2da14d947a49e6f120a75e947250aebe65f9629b62bb1f5c14e6e9"}, + {file = "grpcio-1.80.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:c624cc9f1008361014378c9d776de7182b11fe8b2e5a81bc69f23a295f2a1ad0"}, + {file = "grpcio-1.80.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:f49eddcac43c3bf350c0385366a58f36bed8cc2c0ec35ef7b74b49e56552c0c2"}, + {file = "grpcio-1.80.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d334591df610ab94714048e0d5b4f3dd5ad1bee74dfec11eee344220077a79de"}, + {file = "grpcio-1.80.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0cb517eb1d0d0aaf1d87af7cc5b801d686557c1d88b2619f5e31fab3c2315921"}, + {file = "grpcio-1.80.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4e78c4ac0d97dc2e569b2f4bcbbb447491167cb358d1a389fc4af71ab6f70411"}, + {file = "grpcio-1.80.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2ed770b4c06984f3b47eb0517b1c69ad0b84ef3f40128f51448433be904634cd"}, + {file = "grpcio-1.80.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:256507e2f524092f1473071a05e65a5b10d84b82e3ff24c5b571513cfaa61e2f"}, + {file = "grpcio-1.80.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a6284a5d907c37db53350645567c522be314bac859a64a7a5ca63b77bb7958f"}, + {file = "grpcio-1.80.0-cp312-cp312-win32.whl", hash = "sha256:c71309cfce2f22be26aa4a847357c502db6c621f1a49825ae98aa0907595b193"}, + {file = "grpcio-1.80.0-cp312-cp312-win_amd64.whl", hash = "sha256:9fe648599c0e37594c4809d81a9e77bd138cc82eb8baa71b6a86af65426723ff"}, + {file = "grpcio-1.80.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:e9e408fc016dffd20661f0126c53d8a31c2821b5c13c5d67a0f5ed5de93319ad"}, + {file = "grpcio-1.80.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:92d787312e613754d4d8b9ca6d3297e69994a7912a32fa38c4c4e01c272974b0"}, + {file = "grpcio-1.80.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8ac393b58aa16991a2f1144ec578084d544038c12242da3a215966b512904d0f"}, + {file = "grpcio-1.80.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:68e5851ac4b9afe07e7f84483803ad167852570d65326b34d54ca560bfa53fb6"}, + {file = "grpcio-1.80.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:873ff5d17d68992ef6605330127425d2fc4e77e612fa3c3e0ed4e668685e3140"}, + {file = "grpcio-1.80.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2bea16af2750fd0a899bf1abd9022244418b55d1f37da2202249ba4ba673838d"}, + {file = "grpcio-1.80.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba0db34f7e1d803a878284cd70e4c63cb6ae2510ba51937bf8f45ba997cefcf7"}, + {file = "grpcio-1.80.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8eb613f02d34721f1acf3626dfdb3545bd3c8505b0e52bf8b5710a28d02e8aa7"}, + {file = "grpcio-1.80.0-cp313-cp313-win32.whl", hash = "sha256:93b6f823810720912fd131f561f91f5fed0fda372b6b7028a2681b8194d5d294"}, + {file = "grpcio-1.80.0-cp313-cp313-win_amd64.whl", hash = "sha256:e172cf795a3ba5246d3529e4d34c53db70e888fa582a8ffebd2e6e48bc0cba50"}, + {file = "grpcio-1.80.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:3d4147a97c8344d065d01bbf8b6acec2cf86fb0400d40696c8bdad34a64ffc0e"}, + {file = "grpcio-1.80.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:d8e11f167935b3eb089ac9038e1a063e6d7dbe995c0bb4a661e614583352e76f"}, + {file = "grpcio-1.80.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f14b618fc30de822681ee986cfdcc2d9327229dc4c98aed16896761cacd468b9"}, + {file = "grpcio-1.80.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4ed39fbdcf9b87370f6e8df4e39ca7b38b3e5e9d1b0013c7b6be9639d6578d14"}, + {file = "grpcio-1.80.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2dcc70e9f0ba987526e8e8603a610fb4f460e42899e74e7a518bf3c68fe1bf05"}, + {file = "grpcio-1.80.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:448c884b668b868562b1bda833c5fce6272d26e1926ec46747cda05741d302c1"}, + {file = "grpcio-1.80.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a1dc80fe55685b4a543555e6eef975303b36c8db1023b1599b094b92aa77965f"}, + {file = "grpcio-1.80.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:31b9ac4ad1aa28ffee5503821fafd09e4da0a261ce1c1281c6c8da0423c83b6e"}, + {file = "grpcio-1.80.0-cp314-cp314-win32.whl", hash = "sha256:367ce30ba67d05e0592470428f0ec1c31714cab9ef19b8f2e37be1f4c7d32fae"}, + {file = "grpcio-1.80.0-cp314-cp314-win_amd64.whl", hash = "sha256:3b01e1f5464c583d2f567b2e46ff0d516ef979978f72091fd81f5ab7fa6e2e7f"}, + {file = "grpcio-1.80.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:aacdfb4ed3eb919ca997504d27e03d5dba403c85130b8ed450308590a738f7a4"}, + {file = "grpcio-1.80.0-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:a361c20ec1ccd3c3953d20fb6d7b4125093bdd10dff44c5e2bbb39e58917cedc"}, + {file = "grpcio-1.80.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:43168871f170d1e4ed16ae03d10cd21efa29f190e710a624cee7e5ae07da6f4f"}, + {file = "grpcio-1.80.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1b97cd29a8eda100b559b455331c487a80915b6ea6bd91cf3e89836c4ee8d957"}, + {file = "grpcio-1.80.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bac1d573dfa84ce59a5547073e28fa7326d53352adda6912e362da0b917fcef4"}, + {file = "grpcio-1.80.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4560cf0e86514595dbbd330cd65b7afad4b5c4b8c4905c041cfffa138d45e6fd"}, + {file = "grpcio-1.80.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ec0a592e926071b4abad50c1495cd0d0d513324b3ff5e7267067c33ba27506e4"}, + {file = "grpcio-1.80.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:deb10a1528473c11f72a0939eed36d83e847d7cbb63e8cc5611fb7a912d38614"}, + {file = "grpcio-1.80.0-cp39-cp39-win32.whl", hash = "sha256:627fb7312171cdc52828bd6fac8d7028ff2a64b89f1957b6f3416caa2218d141"}, + {file = "grpcio-1.80.0-cp39-cp39-win_amd64.whl", hash = "sha256:05d55e1798756282cddd52d56c896b3e7d673e3a8798c2f1cd05ba249a3bb4de"}, + {file = "grpcio-1.80.0.tar.gz", hash = "sha256:29aca15edd0688c22ba01d7cc01cb000d72b2033f4a3c72a81a19b56fd143257"}, ] [package.dependencies] typing-extensions = ">=4.12,<5.0" [package.extras] -protobuf = ["grpcio-tools (>=1.78.0)"] +protobuf = ["grpcio-tools (>=1.80.0)"] [[package]] name = "grpcio-status" -version = "1.78.0" +version = "1.80.0" description = "Status proto mapping for gRPC" optional = false python-versions = ">=3.9" files = [ - {file = "grpcio_status-1.78.0-py3-none-any.whl", hash = "sha256:b492b693d4bf27b47a6c32590701724f1d3b9444b36491878fb71f6208857f34"}, - {file = "grpcio_status-1.78.0.tar.gz", hash = "sha256:a34cfd28101bfea84b5aa0f936b4b423019e9213882907166af6b3bddc59e189"}, + {file = "grpcio_status-1.80.0-py3-none-any.whl", hash = "sha256:4b56990363af50dbf2c2ebb80f1967185c07d87aa25aa2bea45ddb75fc181dbe"}, + {file = "grpcio_status-1.80.0.tar.gz", hash = "sha256:df73802a4c89a3ea88aa2aff971e886fccce162bc2e6511408b3d67a144381cd"}, ] [package.dependencies] googleapis-common-protos = ">=1.5.5" -grpcio = ">=1.78.0" +grpcio = ">=1.80.0" protobuf = ">=6.31.1,<7.0.0" [[package]] @@ -1770,83 +1775,83 @@ files = [ [[package]] name = "numpy" -version = "2.4.3" +version = "2.4.4" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.11" files = [ - {file = "numpy-2.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:33b3bf58ee84b172c067f56aeadc7ee9ab6de69c5e800ab5b10295d54c581adb"}, - {file = "numpy-2.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8ba7b51e71c05aa1f9bc3641463cd82308eab40ce0d5c7e1fd4038cbf9938147"}, - {file = "numpy-2.4.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:a1988292870c7cb9d0ebb4cc96b4d447513a9644801de54606dc7aabf2b7d920"}, - {file = "numpy-2.4.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:23b46bb6d8ecb68b58c09944483c135ae5f0e9b8d8858ece5e4ead783771d2a9"}, - {file = "numpy-2.4.3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a016db5c5dba78fa8fe9f5d80d6708f9c42ab087a739803c0ac83a43d686a470"}, - {file = "numpy-2.4.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:715de7f82e192e8cae5a507a347d97ad17598f8e026152ca97233e3666daaa71"}, - {file = "numpy-2.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2ddb7919366ee468342b91dea2352824c25b55814a987847b6c52003a7c97f15"}, - {file = "numpy-2.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a315e5234d88067f2d97e1f2ef670a7569df445d55400f1e33d117418d008d52"}, - {file = "numpy-2.4.3-cp311-cp311-win32.whl", hash = "sha256:2b3f8d2c4589b1a2028d2a770b0fc4d1f332fb5e01521f4de3199a896d158ddd"}, - {file = "numpy-2.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:77e76d932c49a75617c6d13464e41203cd410956614d0a0e999b25e9e8d27eec"}, - {file = "numpy-2.4.3-cp311-cp311-win_arm64.whl", hash = "sha256:eb610595dd91560905c132c709412b512135a60f1851ccbd2c959e136431ff67"}, - {file = "numpy-2.4.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:61b0cbabbb6126c8df63b9a3a0c4b1f44ebca5e12ff6997b80fcf267fb3150ef"}, - {file = "numpy-2.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7395e69ff32526710748f92cd8c9849b361830968ea3e24a676f272653e8983e"}, - {file = "numpy-2.4.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:abdce0f71dcb4a00e4e77f3faf05e4616ceccfe72ccaa07f47ee79cda3b7b0f4"}, - {file = "numpy-2.4.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:48da3a4ee1336454b07497ff7ec83903efa5505792c4e6d9bf83d99dc07a1e18"}, - {file = "numpy-2.4.3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:32e3bef222ad6b052280311d1d60db8e259e4947052c3ae7dd6817451fc8a4c5"}, - {file = "numpy-2.4.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e7dd01a46700b1967487141a66ac1a3cf0dd8ebf1f08db37d46389401512ca97"}, - {file = "numpy-2.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:76f0f283506c28b12bba319c0fab98217e9f9b54e6160e9c79e9f7348ba32e9c"}, - {file = "numpy-2.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:737f630a337364665aba3b5a77e56a68cc42d350edd010c345d65a3efa3addcc"}, - {file = "numpy-2.4.3-cp312-cp312-win32.whl", hash = "sha256:26952e18d82a1dbbc2f008d402021baa8d6fc8e84347a2072a25e08b46d698b9"}, - {file = "numpy-2.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:65f3c2455188f09678355f5cae1f959a06b778bc66d535da07bf2ef20cd319d5"}, - {file = "numpy-2.4.3-cp312-cp312-win_arm64.whl", hash = "sha256:2abad5c7fef172b3377502bde47892439bae394a71bc329f31df0fd829b41a9e"}, - {file = "numpy-2.4.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b346845443716c8e542d54112966383b448f4a3ba5c66409771b8c0889485dd3"}, - {file = "numpy-2.4.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2629289168f4897a3c4e23dc98d6f1731f0fc0fe52fb9db19f974041e4cc12b9"}, - {file = "numpy-2.4.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:bb2e3cf95854233799013779216c57e153c1ee67a0bf92138acca0e429aefaee"}, - {file = "numpy-2.4.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:7f3408ff897f8ab07a07fbe2823d7aee6ff644c097cc1f90382511fe982f647f"}, - {file = "numpy-2.4.3-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:decb0eb8a53c3b009b0962378065589685d66b23467ef5dac16cbe818afde27f"}, - {file = "numpy-2.4.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5f51900414fc9204a0e0da158ba2ac52b75656e7dce7e77fb9f84bfa343b4cc"}, - {file = "numpy-2.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6bd06731541f89cdc01b261ba2c9e037f1543df7472517836b78dfb15bd6e476"}, - {file = "numpy-2.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:22654fe6be0e5206f553a9250762c653d3698e46686eee53b399ab90da59bd92"}, - {file = "numpy-2.4.3-cp313-cp313-win32.whl", hash = "sha256:d71e379452a2f670ccb689ec801b1218cd3983e253105d6e83780967e899d687"}, - {file = "numpy-2.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:0a60e17a14d640f49146cb38e3f105f571318db7826d9b6fef7e4dce758faecd"}, - {file = "numpy-2.4.3-cp313-cp313-win_arm64.whl", hash = "sha256:c9619741e9da2059cd9c3f206110b97583c7152c1dc9f8aafd4beb450ac1c89d"}, - {file = "numpy-2.4.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7aa4e54f6469300ebca1d9eb80acd5253cdfa36f2c03d79a35883687da430875"}, - {file = "numpy-2.4.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d1b90d840b25874cf5cd20c219af10bac3667db3876d9a495609273ebe679070"}, - {file = "numpy-2.4.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a749547700de0a20a6718293396ec237bb38218049cfce788e08fcb716e8cf73"}, - {file = "numpy-2.4.3-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94f3c4a151a2e529adf49c1d54f0f57ff8f9b233ee4d44af623a81553ab86368"}, - {file = "numpy-2.4.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22c31dc07025123aedf7f2db9e91783df13f1776dc52c6b22c620870dc0fab22"}, - {file = "numpy-2.4.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:148d59127ac95979d6f07e4d460f934ebdd6eed641db9c0db6c73026f2b2101a"}, - {file = "numpy-2.4.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a97cbf7e905c435865c2d939af3d93f99d18eaaa3cabe4256f4304fb51604349"}, - {file = "numpy-2.4.3-cp313-cp313t-win32.whl", hash = "sha256:be3b8487d725a77acccc9924f65fd8bce9af7fac8c9820df1049424a2115af6c"}, - {file = "numpy-2.4.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1ec84fd7c8e652b0f4aaaf2e6e9cc8eaa9b1b80a537e06b2e3a2fb176eedcb26"}, - {file = "numpy-2.4.3-cp313-cp313t-win_arm64.whl", hash = "sha256:120df8c0a81ebbf5b9020c91439fccd85f5e018a927a39f624845be194a2be02"}, - {file = "numpy-2.4.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:5884ce5c7acfae1e4e1b6fde43797d10aa506074d25b531b4f54bde33c0c31d4"}, - {file = "numpy-2.4.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:297837823f5bc572c5f9379b0c9f3a3365f08492cbdc33bcc3af174372ebb168"}, - {file = "numpy-2.4.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:a111698b4a3f8dcbe54c64a7708f049355abd603e619013c346553c1fd4ca90b"}, - {file = "numpy-2.4.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:4bd4741a6a676770e0e97fe9ab2e51de01183df3dcbcec591d26d331a40de950"}, - {file = "numpy-2.4.3-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:54f29b877279d51e210e0c80709ee14ccbbad647810e8f3d375561c45ef613dd"}, - {file = "numpy-2.4.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:679f2a834bae9020f81534671c56fd0cc76dd7e5182f57131478e23d0dc59e24"}, - {file = "numpy-2.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d84f0f881cb2225c2dfd7f78a10a5645d487a496c6668d6cc39f0f114164f3d0"}, - {file = "numpy-2.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d213c7e6e8d211888cc359bab7199670a00f5b82c0978b9d1c75baf1eddbeac0"}, - {file = "numpy-2.4.3-cp314-cp314-win32.whl", hash = "sha256:52077feedeff7c76ed7c9f1a0428558e50825347b7545bbb8523da2cd55c547a"}, - {file = "numpy-2.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:0448e7f9caefb34b4b7dd2b77f21e8906e5d6f0365ad525f9f4f530b13df2afc"}, - {file = "numpy-2.4.3-cp314-cp314-win_arm64.whl", hash = "sha256:b44fd60341c4d9783039598efadd03617fa28d041fc37d22b62d08f2027fa0e7"}, - {file = "numpy-2.4.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0a195f4216be9305a73c0e91c9b026a35f2161237cf1c6de9b681637772ea657"}, - {file = "numpy-2.4.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:cd32fbacb9fd1bf041bf8e89e4576b6f00b895f06d00914820ae06a616bdfef7"}, - {file = "numpy-2.4.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:2e03c05abaee1f672e9d67bc858f300b5ccba1c21397211e8d77d98350972093"}, - {file = "numpy-2.4.3-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7d1ce23cce91fcea443320a9d0ece9b9305d4368875bab09538f7a5b4131938a"}, - {file = "numpy-2.4.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c59020932feb24ed49ffd03704fbab89f22aa9c0d4b180ff45542fe8918f5611"}, - {file = "numpy-2.4.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9684823a78a6cd6ad7511fc5e25b07947d1d5b5e2812c93fe99d7d4195130720"}, - {file = "numpy-2.4.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0200b25c687033316fb39f0ff4e3e690e8957a2c3c8d22499891ec58c37a3eb5"}, - {file = "numpy-2.4.3-cp314-cp314t-win32.whl", hash = "sha256:5e10da9e93247e554bb1d22f8edc51847ddd7dde52d85ce31024c1b4312bfba0"}, - {file = "numpy-2.4.3-cp314-cp314t-win_amd64.whl", hash = "sha256:45f003dbdffb997a03da2d1d0cb41fbd24a87507fb41605c0420a3db5bd4667b"}, - {file = "numpy-2.4.3-cp314-cp314t-win_arm64.whl", hash = "sha256:4d382735cecd7bcf090172489a525cd7d4087bc331f7df9f60ddc9a296cf208e"}, - {file = "numpy-2.4.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c6b124bfcafb9e8d3ed09130dbee44848c20b3e758b6bbf006e641778927c028"}, - {file = "numpy-2.4.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:76dbb9d4e43c16cf9aa711fcd8de1e2eeb27539dcefb60a1d5e9f12fae1d1ed8"}, - {file = "numpy-2.4.3-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:29363fbfa6f8ee855d7569c96ce524845e3d726d6c19b29eceec7dd555dab152"}, - {file = "numpy-2.4.3-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:bc71942c789ef415a37f0d4eab90341425a00d538cd0642445d30b41023d3395"}, - {file = "numpy-2.4.3-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7e58765ad74dcebd3ef0208a5078fba32dc8ec3578fe84a604432950cd043d79"}, - {file = "numpy-2.4.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e236dbda4e1d319d681afcbb136c0c4a8e0f1a5c58ceec2adebb547357fe857"}, - {file = "numpy-2.4.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:4b42639cdde6d24e732ff823a3fa5b701d8acad89c4142bc1d0bd6dc85200ba5"}, - {file = "numpy-2.4.3.tar.gz", hash = "sha256:483a201202b73495f00dbc83796c6ae63137a9bdade074f7648b3e32613412dd"}, + {file = "numpy-2.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db"}, + {file = "numpy-2.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0"}, + {file = "numpy-2.4.4-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015"}, + {file = "numpy-2.4.4-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40"}, + {file = "numpy-2.4.4-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d"}, + {file = "numpy-2.4.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502"}, + {file = "numpy-2.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd"}, + {file = "numpy-2.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5"}, + {file = "numpy-2.4.4-cp311-cp311-win32.whl", hash = "sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e"}, + {file = "numpy-2.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e"}, + {file = "numpy-2.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e"}, + {file = "numpy-2.4.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b"}, + {file = "numpy-2.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e"}, + {file = "numpy-2.4.4-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842"}, + {file = "numpy-2.4.4-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8"}, + {file = "numpy-2.4.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121"}, + {file = "numpy-2.4.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e"}, + {file = "numpy-2.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44"}, + {file = "numpy-2.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d"}, + {file = "numpy-2.4.4-cp312-cp312-win32.whl", hash = "sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827"}, + {file = "numpy-2.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a"}, + {file = "numpy-2.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec"}, + {file = "numpy-2.4.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50"}, + {file = "numpy-2.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115"}, + {file = "numpy-2.4.4-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af"}, + {file = "numpy-2.4.4-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c"}, + {file = "numpy-2.4.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103"}, + {file = "numpy-2.4.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83"}, + {file = "numpy-2.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed"}, + {file = "numpy-2.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959"}, + {file = "numpy-2.4.4-cp313-cp313-win32.whl", hash = "sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed"}, + {file = "numpy-2.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf"}, + {file = "numpy-2.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d"}, + {file = "numpy-2.4.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5"}, + {file = "numpy-2.4.4-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7"}, + {file = "numpy-2.4.4-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93"}, + {file = "numpy-2.4.4-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e"}, + {file = "numpy-2.4.4-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40"}, + {file = "numpy-2.4.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e"}, + {file = "numpy-2.4.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392"}, + {file = "numpy-2.4.4-cp313-cp313t-win32.whl", hash = "sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008"}, + {file = "numpy-2.4.4-cp313-cp313t-win_amd64.whl", hash = "sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8"}, + {file = "numpy-2.4.4-cp313-cp313t-win_arm64.whl", hash = "sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233"}, + {file = "numpy-2.4.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0"}, + {file = "numpy-2.4.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a"}, + {file = "numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a"}, + {file = "numpy-2.4.4-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b"}, + {file = "numpy-2.4.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a"}, + {file = "numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d"}, + {file = "numpy-2.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252"}, + {file = "numpy-2.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f"}, + {file = "numpy-2.4.4-cp314-cp314-win32.whl", hash = "sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc"}, + {file = "numpy-2.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74"}, + {file = "numpy-2.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb"}, + {file = "numpy-2.4.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e"}, + {file = "numpy-2.4.4-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113"}, + {file = "numpy-2.4.4-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d"}, + {file = "numpy-2.4.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d"}, + {file = "numpy-2.4.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f"}, + {file = "numpy-2.4.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0"}, + {file = "numpy-2.4.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150"}, + {file = "numpy-2.4.4-cp314-cp314t-win32.whl", hash = "sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871"}, + {file = "numpy-2.4.4-cp314-cp314t-win_amd64.whl", hash = "sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e"}, + {file = "numpy-2.4.4-cp314-cp314t-win_arm64.whl", hash = "sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7"}, + {file = "numpy-2.4.4-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4"}, + {file = "numpy-2.4.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e"}, + {file = "numpy-2.4.4-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c"}, + {file = "numpy-2.4.4-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3"}, + {file = "numpy-2.4.4-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7"}, + {file = "numpy-2.4.4-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f"}, + {file = "numpy-2.4.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119"}, + {file = "numpy-2.4.4.tar.gz", hash = "sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0"}, ] [[package]] @@ -2229,38 +2234,38 @@ testing = ["coverage", "pytest", "pytest-benchmark"] [[package]] name = "proto-plus" -version = "1.27.1" +version = "1.27.2" description = "Beautiful, Pythonic protocol buffers" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "proto_plus-1.27.1-py3-none-any.whl", hash = "sha256:e4643061f3a4d0de092d62aa4ad09fa4756b2cbb89d4627f3985018216f9fefc"}, - {file = "proto_plus-1.27.1.tar.gz", hash = "sha256:912a7460446625b792f6448bade9e55cd4e41e6ac10e27009ef71a7f317fa147"}, + {file = "proto_plus-1.27.2-py3-none-any.whl", hash = "sha256:6432f75893d3b9e70b9c412f1d2f03f65b11fb164b793d14ae2ca01821d22718"}, + {file = "proto_plus-1.27.2.tar.gz", hash = "sha256:b2adde53adadf75737c44d3dcb0104fde65250dfc83ad59168b4aa3e574b6a24"}, ] [package.dependencies] -protobuf = ">=3.19.0,<7.0.0" +protobuf = ">=4.25.8,<8.0.0" [package.extras] testing = ["google-api-core (>=1.31.5)"] [[package]] name = "protobuf" -version = "6.33.5" +version = "6.33.6" description = "" optional = false python-versions = ">=3.9" files = [ - {file = "protobuf-6.33.5-cp310-abi3-win32.whl", hash = "sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b"}, - {file = "protobuf-6.33.5-cp310-abi3-win_amd64.whl", hash = "sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c"}, - {file = "protobuf-6.33.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5"}, - {file = "protobuf-6.33.5-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190"}, - {file = "protobuf-6.33.5-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd"}, - {file = "protobuf-6.33.5-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0"}, - {file = "protobuf-6.33.5-cp39-cp39-win32.whl", hash = "sha256:a3157e62729aafb8df6da2c03aa5c0937c7266c626ce11a278b6eb7963c4e37c"}, - {file = "protobuf-6.33.5-cp39-cp39-win_amd64.whl", hash = "sha256:8f04fa32763dcdb4973d537d6b54e615cc61108c7cb38fe59310c3192d29510a"}, - {file = "protobuf-6.33.5-py3-none-any.whl", hash = "sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02"}, - {file = "protobuf-6.33.5.tar.gz", hash = "sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c"}, + {file = "protobuf-6.33.6-cp310-abi3-win32.whl", hash = "sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3"}, + {file = "protobuf-6.33.6-cp310-abi3-win_amd64.whl", hash = "sha256:0cd27b587afca21b7cfa59a74dcbd48a50f0a6400cfb59391340ad729d91d326"}, + {file = "protobuf-6.33.6-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:9720e6961b251bde64edfdab7d500725a2af5280f3f4c87e57c0208376aa8c3a"}, + {file = "protobuf-6.33.6-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:e2afbae9b8e1825e3529f88d514754e094278bb95eadc0e199751cdd9a2e82a2"}, + {file = "protobuf-6.33.6-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:c96c37eec15086b79762ed265d59ab204dabc53056e3443e702d2681f4b39ce3"}, + {file = "protobuf-6.33.6-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:e9db7e292e0ab79dd108d7f1a94fe31601ce1ee3f7b79e0692043423020b0593"}, + {file = "protobuf-6.33.6-cp39-cp39-win32.whl", hash = "sha256:bd56799fb262994b2c2faa1799693c95cc2e22c62f56fb43af311cae45d26f0e"}, + {file = "protobuf-6.33.6-cp39-cp39-win_amd64.whl", hash = "sha256:f443a394af5ed23672bc6c486be138628fbe5c651ccbc536873d7da23d1868cf"}, + {file = "protobuf-6.33.6-py3-none-any.whl", hash = "sha256:77179e006c476e69bf8e8ce866640091ec42e1beb80b213c3900006ecfba6901"}, + {file = "protobuf-6.33.6.tar.gz", hash = "sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135"}, ] [[package]] @@ -2509,13 +2514,13 @@ typing-extensions = ">=4.14.1" [[package]] name = "pygments" -version = "2.19.2" +version = "2.20.0" description = "Pygments is a syntax highlighting package written in Python." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, - {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, + {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}, + {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}, ] [package.extras] @@ -3037,147 +3042,147 @@ typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} [[package]] name = "regex" -version = "2026.2.28" +version = "2026.3.32" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.10" files = [ - {file = "regex-2026.2.28-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fc48c500838be6882b32748f60a15229d2dea96e59ef341eaa96ec83538f498d"}, - {file = "regex-2026.2.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2afa673660928d0b63d84353c6c08a8a476ddfc4a47e11742949d182e6863ce8"}, - {file = "regex-2026.2.28-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7ab218076eb0944549e7fe74cf0e2b83a82edb27e81cc87411f76240865e04d5"}, - {file = "regex-2026.2.28-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94d63db12e45a9b9f064bfe4800cefefc7e5f182052e4c1b774d46a40ab1d9bb"}, - {file = "regex-2026.2.28-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:195237dc327858a7721bf8b0bbbef797554bc13563c3591e91cd0767bacbe359"}, - {file = "regex-2026.2.28-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b387a0d092dac157fb026d737dde35ff3e49ef27f285343e7c6401851239df27"}, - {file = "regex-2026.2.28-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3935174fa4d9f70525a4367aaff3cb8bc0548129d114260c29d9dfa4a5b41692"}, - {file = "regex-2026.2.28-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2b2b23587b26496ff5fd40df4278becdf386813ec00dc3533fa43a4cf0e2ad3c"}, - {file = "regex-2026.2.28-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3b24bd7e9d85dc7c6a8bd2aa14ecd234274a0248335a02adeb25448aecdd420d"}, - {file = "regex-2026.2.28-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bd477d5f79920338107f04aa645f094032d9e3030cc55be581df3d1ef61aa318"}, - {file = "regex-2026.2.28-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:b49eb78048c6354f49e91e4b77da21257fecb92256b6d599ae44403cab30b05b"}, - {file = "regex-2026.2.28-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:a25c7701e4f7a70021db9aaf4a4a0a67033c6318752146e03d1b94d32006217e"}, - {file = "regex-2026.2.28-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:9dd450db6458387167e033cfa80887a34c99c81d26da1bf8b0b41bf8c9cac88e"}, - {file = "regex-2026.2.28-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2954379dd20752e82d22accf3ff465311cbb2bac6c1f92c4afd400e1757f7451"}, - {file = "regex-2026.2.28-cp310-cp310-win32.whl", hash = "sha256:1f8b17be5c27a684ea6759983c13506bd77bfc7c0347dff41b18ce5ddd2ee09a"}, - {file = "regex-2026.2.28-cp310-cp310-win_amd64.whl", hash = "sha256:dd8847c4978bc3c7e6c826fb745f5570e518b8459ac2892151ce6627c7bc00d5"}, - {file = "regex-2026.2.28-cp310-cp310-win_arm64.whl", hash = "sha256:73cdcdbba8028167ea81490c7f45280113e41db2c7afb65a276f4711fa3bcbff"}, - {file = "regex-2026.2.28-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e621fb7c8dc147419b28e1702f58a0177ff8308a76fa295c71f3e7827849f5d9"}, - {file = "regex-2026.2.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0d5bef2031cbf38757a0b0bc4298bb4824b6332d28edc16b39247228fbdbad97"}, - {file = "regex-2026.2.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bcb399ed84eabf4282587ba151f2732ad8168e66f1d3f85b1d038868fe547703"}, - {file = "regex-2026.2.28-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c1b34dfa72f826f535b20712afa9bb3ba580020e834f3c69866c5bddbf10098"}, - {file = "regex-2026.2.28-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:851fa70df44325e1e4cdb79c5e676e91a78147b1b543db2aec8734d2add30ec2"}, - {file = "regex-2026.2.28-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:516604edd17b1c2c3e579cf4e9b25a53bf8fa6e7cedddf1127804d3e0140ca64"}, - {file = "regex-2026.2.28-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e7ce83654d1ab701cb619285a18a8e5a889c1216d746ddc710c914ca5fd71022"}, - {file = "regex-2026.2.28-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f2791948f7c70bb9335a9102df45e93d428f4b8128020d85920223925d73b9e1"}, - {file = "regex-2026.2.28-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:03a83cc26aa2acda6b8b9dfe748cf9e84cbd390c424a1de34fdcef58961a297a"}, - {file = "regex-2026.2.28-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ec6f5674c5dc836994f50f1186dd1fafde4be0666aae201ae2fcc3d29d8adf27"}, - {file = "regex-2026.2.28-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:50c2fc924749543e0eacc93ada6aeeb3ea5f6715825624baa0dccaec771668ae"}, - {file = "regex-2026.2.28-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ba55c50f408fb5c346a3a02d2ce0ebc839784e24f7c9684fde328ff063c3cdea"}, - {file = "regex-2026.2.28-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:edb1b1b3a5576c56f08ac46f108c40333f222ebfd5cf63afdfa3aab0791ebe5b"}, - {file = "regex-2026.2.28-cp311-cp311-win32.whl", hash = "sha256:948c12ef30ecedb128903c2c2678b339746eb7c689c5c21957c4a23950c96d15"}, - {file = "regex-2026.2.28-cp311-cp311-win_amd64.whl", hash = "sha256:fd63453f10d29097cc3dc62d070746523973fb5aa1c66d25f8558bebd47fed61"}, - {file = "regex-2026.2.28-cp311-cp311-win_arm64.whl", hash = "sha256:00f2b8d9615aa165fdff0a13f1a92049bfad555ee91e20d246a51aa0b556c60a"}, - {file = "regex-2026.2.28-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fcf26c3c6d0da98fada8ae4ef0aa1c3405a431c0a77eb17306d38a89b02adcd7"}, - {file = "regex-2026.2.28-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:02473c954af35dd2defeb07e44182f5705b30ea3f351a7cbffa9177beb14da5d"}, - {file = "regex-2026.2.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9b65d33a17101569f86d9c5966a8b1d7fbf8afdda5a8aa219301b0a80f58cf7d"}, - {file = "regex-2026.2.28-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e71dcecaa113eebcc96622c17692672c2d104b1d71ddf7adeda90da7ddeb26fc"}, - {file = "regex-2026.2.28-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:481df4623fa4969c8b11f3433ed7d5e3dc9cec0f008356c3212b3933fb77e3d8"}, - {file = "regex-2026.2.28-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:64e7c6ad614573e0640f271e811a408d79a9e1fe62a46adb602f598df42a818d"}, - {file = "regex-2026.2.28-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6b08a06976ff4fb0d83077022fde3eca06c55432bb997d8c0495b9a4e9872f4"}, - {file = "regex-2026.2.28-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:864cdd1a2ef5716b0ab468af40139e62ede1b3a53386b375ec0786bb6783fc05"}, - {file = "regex-2026.2.28-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:511f7419f7afab475fd4d639d4aedfc54205bcb0800066753ef68a59f0f330b5"}, - {file = "regex-2026.2.28-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b42f7466e32bf15a961cf09f35fa6323cc72e64d3d2c990b10de1274a5da0a59"}, - {file = "regex-2026.2.28-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8710d61737b0c0ce6836b1da7109f20d495e49b3809f30e27e9560be67a257bf"}, - {file = "regex-2026.2.28-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4390c365fd2d45278f45afd4673cb90f7285f5701607e3ad4274df08e36140ae"}, - {file = "regex-2026.2.28-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cb3b1db8ff6c7b8bf838ab05583ea15230cb2f678e569ab0e3a24d1e8320940b"}, - {file = "regex-2026.2.28-cp312-cp312-win32.whl", hash = "sha256:f8ed9a5d4612df9d4de15878f0bc6aa7a268afbe5af21a3fdd97fa19516e978c"}, - {file = "regex-2026.2.28-cp312-cp312-win_amd64.whl", hash = "sha256:01d65fd24206c8e1e97e2e31b286c59009636c022eb5d003f52760b0f42155d4"}, - {file = "regex-2026.2.28-cp312-cp312-win_arm64.whl", hash = "sha256:c0b5ccbb8ffb433939d248707d4a8b31993cb76ab1a0187ca886bf50e96df952"}, - {file = "regex-2026.2.28-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6d63a07e5ec8ce7184452cb00c41c37b49e67dc4f73b2955b5b8e782ea970784"}, - {file = "regex-2026.2.28-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e59bc8f30414d283ae8ee1617b13d8112e7135cb92830f0ec3688cb29152585a"}, - {file = "regex-2026.2.28-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:de0cf053139f96219ccfabb4a8dd2d217c8c82cb206c91d9f109f3f552d6b43d"}, - {file = "regex-2026.2.28-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb4db2f17e6484904f986c5a657cec85574c76b5c5e61c7aae9ffa1bc6224f95"}, - {file = "regex-2026.2.28-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:52b017b35ac2214d0db5f4f90e303634dc44e4aba4bd6235a27f97ecbe5b0472"}, - {file = "regex-2026.2.28-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:69fc560ccbf08a09dc9b52ab69cacfae51e0ed80dc5693078bdc97db2f91ae96"}, - {file = "regex-2026.2.28-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e61eea47230eba62a31f3e8a0e3164d0f37ef9f40529fb2c79361bc6b53d2a92"}, - {file = "regex-2026.2.28-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4f5c0b182ad4269e7381b7c27fdb0408399881f7a92a4624fd5487f2971dfc11"}, - {file = "regex-2026.2.28-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:96f6269a2882fbb0ee76967116b83679dc628e68eaea44e90884b8d53d833881"}, - {file = "regex-2026.2.28-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b5acd4b6a95f37c3c3828e5d053a7d4edaedb85de551db0153754924cb7c83e3"}, - {file = "regex-2026.2.28-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2234059cfe33d9813a3677ef7667999caea9eeaa83fef98eb6ce15c6cf9e0215"}, - {file = "regex-2026.2.28-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:c15af43c72a7fb0c97cbc66fa36a43546eddc5c06a662b64a0cbf30d6ac40944"}, - {file = "regex-2026.2.28-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9185cc63359862a6e80fe97f696e04b0ad9a11c4ac0a4a927f979f611bfe3768"}, - {file = "regex-2026.2.28-cp313-cp313-win32.whl", hash = "sha256:fb66e5245db9652abd7196ace599b04d9c0e4aa7c8f0e2803938377835780081"}, - {file = "regex-2026.2.28-cp313-cp313-win_amd64.whl", hash = "sha256:71a911098be38c859ceb3f9a9ce43f4ed9f4c6720ad8684a066ea246b76ad9ff"}, - {file = "regex-2026.2.28-cp313-cp313-win_arm64.whl", hash = "sha256:39bb5727650b9a0275c6a6690f9bb3fe693a7e6cc5c3155b1240aedf8926423e"}, - {file = "regex-2026.2.28-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:97054c55db06ab020342cc0d35d6f62a465fa7662871190175f1ad6c655c028f"}, - {file = "regex-2026.2.28-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0d25a10811de831c2baa6aef3c0be91622f44dd8d31dd12e69f6398efb15e48b"}, - {file = "regex-2026.2.28-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d6cfe798d8da41bb1862ed6e0cba14003d387c3c0c4a5d45591076ae9f0ce2f8"}, - {file = "regex-2026.2.28-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fd0ce43e71d825b7c0661f9c54d4d74bd97c56c3fd102a8985bcfea48236bacb"}, - {file = "regex-2026.2.28-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00945d007fd74a9084d2ab79b695b595c6b7ba3698972fadd43e23230c6979c1"}, - {file = "regex-2026.2.28-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bec23c11cbbf09a4df32fe50d57cbdd777bc442269b6e39a1775654f1c95dee2"}, - {file = "regex-2026.2.28-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5cdcc17d935c8f9d3f4db5c2ebe2640c332e3822ad5d23c2f8e0228e6947943a"}, - {file = "regex-2026.2.28-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a448af01e3d8031c89c5d902040b124a5e921a25c4e5e07a861ca591ce429341"}, - {file = "regex-2026.2.28-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:10d28e19bd4888e4abf43bd3925f3c134c52fdf7259219003588a42e24c2aa25"}, - {file = "regex-2026.2.28-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:99985a2c277dcb9ccb63f937451af5d65177af1efdeb8173ac55b61095a0a05c"}, - {file = "regex-2026.2.28-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:e1e7b24cb3ae9953a560c563045d1ba56ee4749fbd05cf21ba571069bd7be81b"}, - {file = "regex-2026.2.28-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:d8511a01d0e4ee1992eb3ba19e09bc1866fe03f05129c3aec3fdc4cbc77aad3f"}, - {file = "regex-2026.2.28-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:aaffaecffcd2479ce87aa1e74076c221700b7c804e48e98e62500ee748f0f550"}, - {file = "regex-2026.2.28-cp313-cp313t-win32.whl", hash = "sha256:ef77bdde9c9eba3f7fa5b58084b29bbcc74bcf55fdbeaa67c102a35b5bd7e7cc"}, - {file = "regex-2026.2.28-cp313-cp313t-win_amd64.whl", hash = "sha256:98adf340100cbe6fbaf8e6dc75e28f2c191b1be50ffefe292fb0e6f6eefdb0d8"}, - {file = "regex-2026.2.28-cp313-cp313t-win_arm64.whl", hash = "sha256:2fb950ac1d88e6b6a9414381f403797b236f9fa17e1eee07683af72b1634207b"}, - {file = "regex-2026.2.28-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:78454178c7df31372ea737996fb7f36b3c2c92cccc641d251e072478afb4babc"}, - {file = "regex-2026.2.28-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:5d10303dd18cedfd4d095543998404df656088240bcfd3cd20a8f95b861f74bd"}, - {file = "regex-2026.2.28-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:19a9c9e0a8f24f39d575a6a854d516b48ffe4cbdcb9de55cb0570a032556ecff"}, - {file = "regex-2026.2.28-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09500be324f49b470d907b3ef8af9afe857f5cca486f853853f7945ddbf75911"}, - {file = "regex-2026.2.28-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fb1c4ff62277d87a7335f2c1ea4e0387b8f2b3ad88a64efd9943906aafad4f33"}, - {file = "regex-2026.2.28-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b8b3f1be1738feadc69f62daa250c933e85c6f34fa378f54a7ff43807c1b9117"}, - {file = "regex-2026.2.28-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc8ed8c3f41c27acb83f7b6a9eb727a73fc6663441890c5cb3426a5f6a91ce7d"}, - {file = "regex-2026.2.28-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa539be029844c0ce1114762d2952ab6cfdd7c7c9bd72e0db26b94c3c36dcc5a"}, - {file = "regex-2026.2.28-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7900157786428a79615a8264dac1f12c9b02957c473c8110c6b1f972dcecaddf"}, - {file = "regex-2026.2.28-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:0b1d2b07614d95fa2bf8a63fd1e98bd8fa2b4848dc91b1efbc8ba219fdd73952"}, - {file = "regex-2026.2.28-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:b389c61aa28a79c2e0527ac36da579869c2e235a5b208a12c5b5318cda2501d8"}, - {file = "regex-2026.2.28-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f467cb602f03fbd1ab1908f68b53c649ce393fde056628dc8c7e634dab6bfc07"}, - {file = "regex-2026.2.28-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e8c8cb2deba42f5ec1ede46374e990f8adc5e6456a57ac1a261b19be6f28e4e6"}, - {file = "regex-2026.2.28-cp314-cp314-win32.whl", hash = "sha256:9036b400b20e4858d56d117108d7813ed07bb7803e3eed766675862131135ca6"}, - {file = "regex-2026.2.28-cp314-cp314-win_amd64.whl", hash = "sha256:1d367257cd86c1cbb97ea94e77b373a0bbc2224976e247f173d19e8f18b4afa7"}, - {file = "regex-2026.2.28-cp314-cp314-win_arm64.whl", hash = "sha256:5e68192bb3a1d6fb2836da24aa494e413ea65853a21505e142e5b1064a595f3d"}, - {file = "regex-2026.2.28-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:a5dac14d0872eeb35260a8e30bac07ddf22adc1e3a0635b52b02e180d17c9c7e"}, - {file = "regex-2026.2.28-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ec0c608b7a7465ffadb344ed7c987ff2f11ee03f6a130b569aa74d8a70e8333c"}, - {file = "regex-2026.2.28-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c7815afb0ca45456613fdaf60ea9c993715511c8d53a83bc468305cbc0ee23c7"}, - {file = "regex-2026.2.28-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b059e71ec363968671693a78c5053bd9cb2fe410f9b8e4657e88377ebd603a2e"}, - {file = "regex-2026.2.28-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b8cf76f1a29f0e99dcfd7aef1551a9827588aae5a737fe31442021165f1920dc"}, - {file = "regex-2026.2.28-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:180e08a435a0319e6a4821c3468da18dc7001987e1c17ae1335488dfe7518dd8"}, - {file = "regex-2026.2.28-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1e496956106fd59ba6322a8ea17141a27c5040e5ee8f9433ae92d4e5204462a0"}, - {file = "regex-2026.2.28-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bba2b18d70eeb7b79950f12f633beeecd923f7c9ad6f6bae28e59b4cb3ab046b"}, - {file = "regex-2026.2.28-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6db7bfae0f8a2793ff1f7021468ea55e2699d0790eb58ee6ab36ae43aa00bc5b"}, - {file = "regex-2026.2.28-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:d0b02e8b7e5874b48ae0f077ecca61c1a6a9f9895e9c6dfb191b55b242862033"}, - {file = "regex-2026.2.28-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:25b6eb660c5cf4b8c3407a1ed462abba26a926cc9965e164268a3267bcc06a43"}, - {file = "regex-2026.2.28-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:5a932ea8ad5d0430351ff9c76c8db34db0d9f53c1d78f06022a21f4e290c5c18"}, - {file = "regex-2026.2.28-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1c2c95e1a2b0f89d01e821ff4de1be4b5d73d1f4b0bf679fa27c1ad8d2327f1a"}, - {file = "regex-2026.2.28-cp314-cp314t-win32.whl", hash = "sha256:bbb882061f742eb5d46f2f1bd5304055be0a66b783576de3d7eef1bed4778a6e"}, - {file = "regex-2026.2.28-cp314-cp314t-win_amd64.whl", hash = "sha256:6591f281cb44dc13de9585b552cec6fc6cf47fb2fe7a48892295ee9bc4a612f9"}, - {file = "regex-2026.2.28-cp314-cp314t-win_arm64.whl", hash = "sha256:dee50f1be42222f89767b64b283283ef963189da0dda4a515aa54a5563c62dec"}, - {file = "regex-2026.2.28.tar.gz", hash = "sha256:a729e47d418ea11d03469f321aaf67cdee8954cde3ff2cf8403ab87951ad10f2"}, + {file = "regex-2026.3.32-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:462a041d2160090553572f6bb0be417ab9bb912a08de54cb692829c871ee88c1"}, + {file = "regex-2026.3.32-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c3c6f6b027d10f84bfe65049028892b5740878edd9eae5fea0d1710b09b1d257"}, + {file = "regex-2026.3.32-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:879ae91f2928a13f01a55cfa168acedd2b02b11b4cd8b5bb9223e8cde777ca52"}, + {file = "regex-2026.3.32-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:887a9fa74418d74d645281ee0edcf60694053bd1bc2ebc49eb5e66bfffc6d107"}, + {file = "regex-2026.3.32-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d571f0b2eec3513734ea31a16ce0f7840c0b85a98e7edfa0e328ed144f9ef78f"}, + {file = "regex-2026.3.32-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6ada7bd5bb6511d12177a7b00416ce55caee49fbf8c268f26b909497b534cacb"}, + {file = "regex-2026.3.32-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:918db4e34a7ef3d0beee913fa54b34231cc3424676f1c19bdb85f01828d3cd37"}, + {file = "regex-2026.3.32-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:69a847a6ffaa86e8af7b9e7037606e05a6f663deec516ad851e8e05d9908d16a"}, + {file = "regex-2026.3.32-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2c8d402ea3dfe674288fe3962016affd33b5b27213d2b5db1823ffa4de524c57"}, + {file = "regex-2026.3.32-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d6b39a2cc5625bbc4fda18919a891eab9aab934eecf83660a90ce20c53621a9a"}, + {file = "regex-2026.3.32-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f7cc00089b4c21847852c0ad76fb3680f9833b855a0d30bcec94211c435bff6b"}, + {file = "regex-2026.3.32-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:fd03e38068faeef937cc6761a250a4aaa015564bd0d61481fefcf15586d31825"}, + {file = "regex-2026.3.32-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e006ea703d5c0f3d112b51ba18af73b58209b954acfe3d8da42eacc9a00e4be6"}, + {file = "regex-2026.3.32-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6980ceb5c1049d4878632f08ba0bf7234c30e741b0dc9081da0f86eca13189d3"}, + {file = "regex-2026.3.32-cp310-cp310-win32.whl", hash = "sha256:6128dd0793a87287ea1d8bf16b4250dd96316c464ee15953d5b98875a284d41e"}, + {file = "regex-2026.3.32-cp310-cp310-win_amd64.whl", hash = "sha256:5aa78c857c1731bdd9863923ffadc816d823edf475c7db6d230c28b53b7bdb5e"}, + {file = "regex-2026.3.32-cp310-cp310-win_arm64.whl", hash = "sha256:34c905a721ddee0f84c99e3e3b59dd4a5564a6fe338222bc89dd4d4df166115c"}, + {file = "regex-2026.3.32-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d7855f5e59fcf91d0c9f4a51dc5d8847813832a2230c3e8e35912ccf20baaa2"}, + {file = "regex-2026.3.32-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:18eb45f711e942c27dbed4109830bd070d8d618e008d0db39705f3f57070a4c6"}, + {file = "regex-2026.3.32-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed3b8281c5d0944d939c82db4ec2300409dd69ee087f7a75a94f2e301e855fb4"}, + {file = "regex-2026.3.32-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ad5c53f2e8fcae9144009435ebe3d9832003508cf8935c04542a1b3b8deefa15"}, + {file = "regex-2026.3.32-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:70c634e39c5cda0da05c93d6747fdc957599f7743543662b6dbabdd8d3ba8a96"}, + {file = "regex-2026.3.32-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1e0f6648fd48f4c73d801c55ab976cd602e2da87de99c07bff005b131f269c6a"}, + {file = "regex-2026.3.32-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5e0fdb5744caf1036dec5510f543164f2144cb64932251f6dfd42fa872b7f9c"}, + {file = "regex-2026.3.32-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dab4178a0bc1ef13178832b12db7bc7f562e8f028b2b5be186e370090dc50652"}, + {file = "regex-2026.3.32-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f95bd07f301135771559101c060f558e2cf896c7df00bec050ca7f93bf11585a"}, + {file = "regex-2026.3.32-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2dcca2bceb823c9cc610e57b86a265d7ffc30e9fe98548c609eba8bd3c0c2488"}, + {file = "regex-2026.3.32-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:567b57eb987547a23306444e4f6f85d4314f83e65c71d320d898aa7550550443"}, + {file = "regex-2026.3.32-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:b6acb765e7c1f2fa08ac9057a33595e26104d7d67046becae184a8f100932dd9"}, + {file = "regex-2026.3.32-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c1ed17104d1be7f807fdec35ec99777168dd793a09510d753f8710590ba54cdd"}, + {file = "regex-2026.3.32-cp311-cp311-win32.whl", hash = "sha256:c60f1de066eb5a0fd8ee5974de4194bb1c2e7692941458807162ffbc39887303"}, + {file = "regex-2026.3.32-cp311-cp311-win_amd64.whl", hash = "sha256:8fe14e24124ef41220e5992a0f09432f890037df6f93fd3d6b7a0feff2db16b2"}, + {file = "regex-2026.3.32-cp311-cp311-win_arm64.whl", hash = "sha256:ded4fc0edf3de792850cb8b04bbf3c5bd725eeaf9df4c27aad510f6eed9c4e19"}, + {file = "regex-2026.3.32-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ad8d372587e659940568afd009afeb72be939c769c552c9b28773d0337251391"}, + {file = "regex-2026.3.32-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3f5747501b69299c6b0b047853771e4ed390510bada68cb16da9c9c2078343f7"}, + {file = "regex-2026.3.32-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:db976be51375bca900e008941639448d148c655c9545071965d0571ecc04f5d0"}, + {file = "regex-2026.3.32-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:66a5083c3ffe5a5a95f8281ea47a88072d4f24001d562d1d9d28d4cdc005fec5"}, + {file = "regex-2026.3.32-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e83ce8008b48762be296f1401f19afd9ea29f3d035d1974e0cecb74e9afbd1df"}, + {file = "regex-2026.3.32-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3aa21bad31db904e0b9055e12c8282df62d43169c4a9d2929407060066ebc74"}, + {file = "regex-2026.3.32-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f54840bea73541652f1170dc63402a5b776fc851ad36a842da9e5163c1f504a0"}, + {file = "regex-2026.3.32-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2ffbadc647325dd4e3118269bda93ded1eb5f5b0c3b7ba79a3da9fbd04f248e9"}, + {file = "regex-2026.3.32-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:66d3126afe7eac41759cd5f0b3b246598086e88e70527c0d68c9e615b81771c4"}, + {file = "regex-2026.3.32-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f785f44a44702dea89b28bce5bc82552490694ce4e144e21a4f0545e364d2150"}, + {file = "regex-2026.3.32-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:b7836aa13721dbdef658aebd11f60d00de633a95726521860fe1f6be75fa225a"}, + {file = "regex-2026.3.32-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5336b1506142eb0f23c96fb4a34b37c4fefd4fed2a7042069f3c8058efe17855"}, + {file = "regex-2026.3.32-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b56993a7aeb4140c4770f4f7965c9e5af4f024457d06e23c01b0d47501cb18ed"}, + {file = "regex-2026.3.32-cp312-cp312-win32.whl", hash = "sha256:d363660f9ef8c734495598d2f3e527fb41f745c73159dc0d743402f049fb6836"}, + {file = "regex-2026.3.32-cp312-cp312-win_amd64.whl", hash = "sha256:c9f261ad3cd97257dc1d9355bfbaa7dd703e06574bffa0fa8fe1e31da915ee38"}, + {file = "regex-2026.3.32-cp312-cp312-win_arm64.whl", hash = "sha256:89e50667e7e8c0e7903e4d644a2764fffe9a3a5d6578f72ab7a7b4205bf204b7"}, + {file = "regex-2026.3.32-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c6d9c6e783b348f719b6118bb3f187b2e138e3112576c9679eb458cc8b2e164b"}, + {file = "regex-2026.3.32-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0f21ae18dfd15752cdd98d03cbd7a3640be826bfd58482a93f730dbd24d7b9fb"}, + {file = "regex-2026.3.32-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:844d88509c968dd44b30daeefac72b038b1bf31ac372d5106358ab01d393c48b"}, + {file = "regex-2026.3.32-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8fc918cd003ba0d066bf0003deb05a259baaaab4dc9bd4f1207bbbe64224857a"}, + {file = "regex-2026.3.32-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bbc458a292aee57d572075f22c035fa32969cdb7987d454e3e34d45a40a0a8b4"}, + {file = "regex-2026.3.32-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:987cdfcfb97a249abc3601ad53c7de5c370529f1981e4c8c46793e4a1e1bfe8e"}, + {file = "regex-2026.3.32-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a5d88fa37ba5e8a80ca8d956b9ea03805cfa460223ac94b7d4854ee5e30f3173"}, + {file = "regex-2026.3.32-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4d082be64e51671dd5ee1c208c92da2ddda0f2f20d8ef387e57634f7e97b6aae"}, + {file = "regex-2026.3.32-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c1d7fa44aece1fa02b8927441614c96520253a5cad6a96994e3a81e060feed55"}, + {file = "regex-2026.3.32-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d478a2ca902b6ef28ffc9521e5f0f728d036abe35c0b250ee8ae78cfe7c5e44e"}, + {file = "regex-2026.3.32-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2820d2231885e97aff0fcf230a19ebd5d2b5b8a1ba338c20deb34f16db1c7897"}, + {file = "regex-2026.3.32-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc8ced733d6cd9af5e412f256a32f7c61cd2d7371280a65c689939ac4572499f"}, + {file = "regex-2026.3.32-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:847087abe98b3c1ebf1eb49d6ef320dbba75a83ee4f83c94704580f1df007dd4"}, + {file = "regex-2026.3.32-cp313-cp313-win32.whl", hash = "sha256:d21a07edddb3e0ca12a8b8712abc8452481c3d3db19ae87fc94e9842d005964b"}, + {file = "regex-2026.3.32-cp313-cp313-win_amd64.whl", hash = "sha256:3c054e39a9f85a3d76c62a1d50c626c5e9306964eaa675c53f61ff7ec1204bbb"}, + {file = "regex-2026.3.32-cp313-cp313-win_arm64.whl", hash = "sha256:b2e9c2ea2e93223579308263f359eab8837dc340530b860cb59b713651889f14"}, + {file = "regex-2026.3.32-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:5d86e3fb08c94f084a625c8dc2132a79a3a111c8bf6e2bc59351fa61753c2f6e"}, + {file = "regex-2026.3.32-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b6f366a5ef66a2df4d9e68035cfe9f0eb8473cdfb922c37fac1d169b468607b0"}, + {file = "regex-2026.3.32-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b8fca73e16c49dd972ce3a88278dfa5b93bf91ddef332a46e9443abe21ca2f7c"}, + {file = "regex-2026.3.32-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b953d9d496d19786f4d46e6ba4b386c6e493e81e40f9c5392332458183b0599d"}, + {file = "regex-2026.3.32-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b565f25171e04d4fad950d1fa837133e3af6ea6f509d96166eed745eb0cf63bc"}, + {file = "regex-2026.3.32-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f28eac18a8733a124444643a66ac96fef2c0ad65f50034e0a043b90333dc677f"}, + {file = "regex-2026.3.32-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7cdd508664430dd51b8888deb6c5b416d8de046b2e11837254378d31febe4a98"}, + {file = "regex-2026.3.32-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5c35d097f509cf7e40d20d5bee548d35d6049b36eb9965e8d43e4659923405b9"}, + {file = "regex-2026.3.32-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:85c9b0c131427470a6423baa0a9330be6fd8c3630cc3ee6fdee03360724cbec5"}, + {file = "regex-2026.3.32-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:e50af656c15e2723eeb7279c0837e07accc594b95ec18b86821a4d44b51b24bf"}, + {file = "regex-2026.3.32-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:4bc32b4dbdb4f9f300cf9f38f8ea2ce9511a068ffaa45ac1373ee7a943f1d810"}, + {file = "regex-2026.3.32-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e3e5d1802cba785210a4a800e63fcee7a228649a880f3bf7f2aadccb151a834b"}, + {file = "regex-2026.3.32-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ef250a3f5e93182193f5c927c5e9575b2cb14b80d03e258bc0b89cc5de076b60"}, + {file = "regex-2026.3.32-cp313-cp313t-win32.whl", hash = "sha256:9cf7036dfa2370ccc8651521fcbb40391974841119e9982fa312b552929e6c85"}, + {file = "regex-2026.3.32-cp313-cp313t-win_amd64.whl", hash = "sha256:c940e00e8d3d10932c929d4b8657c2ea47d2560f31874c3e174c0d3488e8b865"}, + {file = "regex-2026.3.32-cp313-cp313t-win_arm64.whl", hash = "sha256:ace48c5e157c1e58b7de633c5e257285ce85e567ac500c833349c363b3df69d4"}, + {file = "regex-2026.3.32-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:a416ee898ecbc5d8b283223b4cf4d560f93244f6f7615c1bd67359744b00c166"}, + {file = "regex-2026.3.32-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d76d62909bfb14521c3f7cfd5b94c0c75ec94b0a11f647d2f604998962ec7b6c"}, + {file = "regex-2026.3.32-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:631f7d95c83f42bccfe18946a38ad27ff6b6717fb4807e60cf24860b5eb277fc"}, + {file = "regex-2026.3.32-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:12917c6c6813ffcdfb11680a04e4d63c5532b88cf089f844721c5f41f41a63ad"}, + {file = "regex-2026.3.32-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3e221b615f83b15887636fcb90ed21f1a19541366f8b7ba14ba1ad8304f4ded4"}, + {file = "regex-2026.3.32-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4f9ae4755fa90f1dc2d0d393d572ebc134c0fe30fcfc0ab7e67c1db15f192041"}, + {file = "regex-2026.3.32-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a094e9dcafedfb9d333db5cf880304946683f43a6582bb86688f123335122929"}, + {file = "regex-2026.3.32-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c1cecea3e477af105f32ef2119b8d895f297492e41d317e60d474bc4bffd62ff"}, + {file = "regex-2026.3.32-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f26262900edd16272b6360014495e8d68379c6c6e95983f9b7b322dc928a1194"}, + {file = "regex-2026.3.32-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:1cb22fa9ee6a0acb22fc9aecce5f9995fe4d2426ed849357d499d62608fbd7f9"}, + {file = "regex-2026.3.32-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:9b9118a78e031a2e4709cd2fcc3028432e89b718db70073a8da574c249b5b249"}, + {file = "regex-2026.3.32-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:b193ed199848aa96618cd5959c1582a0bf23cd698b0b900cb0ffe81b02c8659c"}, + {file = "regex-2026.3.32-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:10fb2aaae1aaadf7d43c9f3c2450404253697bf8b9ce360bd5418d1d16292298"}, + {file = "regex-2026.3.32-cp314-cp314-win32.whl", hash = "sha256:110ba4920721374d16c4c8ea7ce27b09546d43e16aea1d7f43681b5b8f80ba61"}, + {file = "regex-2026.3.32-cp314-cp314-win_amd64.whl", hash = "sha256:245667ad430745bae6a1e41081872d25819d86fbd9e0eec485ba00d9f78ad43d"}, + {file = "regex-2026.3.32-cp314-cp314-win_arm64.whl", hash = "sha256:1ca02ff0ef33e9d8276a1fcd6d90ff6ea055a32c9149c0050b5b67e26c6d2c51"}, + {file = "regex-2026.3.32-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:51fb7e26f91f9091fd8ec6a946f99b15d3bc3667cb5ddc73dd6cb2222dd4a1cc"}, + {file = "regex-2026.3.32-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:51a93452034d671b0e21b883d48ea66c5d6a05620ee16a9d3f229e828568f3f0"}, + {file = "regex-2026.3.32-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:03c2ebd15ff51e7b13bb3dc28dd5ac18cd39e59ebb40430b14ae1a19e833cff1"}, + {file = "regex-2026.3.32-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5bf2f3c2c5bd8360d335c7dcd4a9006cf1dabae063ee2558ee1b07bbc8a20d88"}, + {file = "regex-2026.3.32-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8a4a3189a99ecdd1c13f42513ab3fc7fa8311b38ba7596dd98537acb8cd9acc3"}, + {file = "regex-2026.3.32-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3c0bbfbd38506e1ea96a85da6782577f06239cb9fcf9696f1ea537c980c0680b"}, + {file = "regex-2026.3.32-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8aaf8ee8f34b677f90742ca089b9c83d64bdc410528767273c816a863ed57327"}, + {file = "regex-2026.3.32-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3ea568832eca219c2be1721afa073c1c9eb8f98a9733fdedd0a9747639fc22a5"}, + {file = "regex-2026.3.32-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e4c8fa46aad1a11ae2f8fcd1c90b9d55e18925829ac0d98c5bb107f93351745"}, + {file = "regex-2026.3.32-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0cec365d44835b043d7b3266487797639d07d621bec9dc0ea224b00775797cc1"}, + {file = "regex-2026.3.32-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:09e26cad1544d856da85881ad292797289e4406338afe98163f3db9f7fac816c"}, + {file = "regex-2026.3.32-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:6062c4ef581a3e9e503dccf4e1b7f2d33fdc1c13ad510b287741ac73bc4c6b27"}, + {file = "regex-2026.3.32-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88ebc0783907468f17fca3d7821b30f9c21865a721144eb498cb0ff99a67bcac"}, + {file = "regex-2026.3.32-cp314-cp314t-win32.whl", hash = "sha256:e480d3dac06c89bc2e0fd87524cc38c546ac8b4a38177650745e64acbbcfdeba"}, + {file = "regex-2026.3.32-cp314-cp314t-win_amd64.whl", hash = "sha256:67015a8162d413af9e3309d9a24e385816666fbf09e48e3ec43342c8536f7df6"}, + {file = "regex-2026.3.32-cp314-cp314t-win_arm64.whl", hash = "sha256:1a6ac1ed758902e664e0d95c1ee5991aa6fb355423f378ed184c6ec47a1ec0e9"}, + {file = "regex-2026.3.32.tar.gz", hash = "sha256:f1574566457161678297a116fa5d1556c5a4159d64c5ff7c760e7c564bf66f16"}, ] [[package]] name = "requests" -version = "2.32.5" +version = "2.33.1" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" files = [ - {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"}, - {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"}, + {file = "requests-2.33.1-py3-none-any.whl", hash = "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a"}, + {file = "requests-2.33.1.tar.gz", hash = "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517"}, ] [package.dependencies] -certifi = ">=2017.4.17" +certifi = ">=2023.5.7" charset_normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" +urllib3 = ">=1.26,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<8)"] [[package]] name = "requests-cache" @@ -3389,60 +3394,60 @@ files = [ [[package]] name = "serpyco-rs" -version = "1.19.0" +version = "1.20.0" description = "" optional = false python-versions = ">=3.9" files = [ - {file = "serpyco_rs-1.19.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0aa06769e2a0a165439af070795dff7c272b8510d803005da06b3d5e0e56c186"}, - {file = "serpyco_rs-1.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d98ff9749e04a351eccb74cd61cac67ace4ea2a1b1aafecafb7b6a3164241c2c"}, - {file = "serpyco_rs-1.19.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a2133ebfe1cb773f310d76355819eec99a136c2df638c4e7bd93cc6bd3180b59"}, - {file = "serpyco_rs-1.19.0-cp310-cp310-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:0dcf2f44aacce39eec9303d6d6f80245a31c1ae9d6f6f1595b5f523b4883e41a"}, - {file = "serpyco_rs-1.19.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a17548844908206fbabda3ad0480edbd880e832cbe7e25ae0aac51ed145f9d39"}, - {file = "serpyco_rs-1.19.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e0fd84a4f272b2afa468bd6f39edb6554e9542e5c8edc4bd232f8d4dbb4beff"}, - {file = "serpyco_rs-1.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09c2ab08c0da4dabdf12d044e9f441251ee48353b7fcd0a5e712381356fe0d82"}, - {file = "serpyco_rs-1.19.0-cp310-cp310-win_amd64.whl", hash = "sha256:6d8ea33f71bddc5f2bda1e23aa374966fb3b10d2179b0c92ac3778c2193c4c14"}, - {file = "serpyco_rs-1.19.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:03ff7330c499b9b8f48dac7156bdf2557225ec5f0a8773838c077f95460e45a8"}, - {file = "serpyco_rs-1.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3245f70159cefe26c30e62cc474b9daa094e9282a71c880cfd92730ea8c7242d"}, - {file = "serpyco_rs-1.19.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0be7762f3f2cd745fa294efddf141b4d7bac75f3eca9deeaddf7c5d0f7411198"}, - {file = "serpyco_rs-1.19.0-cp311-cp311-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:63d295a091a5e51fb919987b44bbbf13596609ebe160a18b8ad954ea2346cd2e"}, - {file = "serpyco_rs-1.19.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b47511401744a927eb0bd502c450571b8adcb470150ed30065cba8c3bc6cb4a"}, - {file = "serpyco_rs-1.19.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a754b12375ddb3efdab72895172d87c7ea8353d3214d3ce09616db4367075f9"}, - {file = "serpyco_rs-1.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26cfe3331ae75dad1b8ffccb274577396680d78bc76418c89e515f967bc382ab"}, - {file = "serpyco_rs-1.19.0-cp311-cp311-win_amd64.whl", hash = "sha256:5fce5eaedcca4e427b31377f6b15be6a9ac14303b49c8686a9ca7c8c4c63e467"}, - {file = "serpyco_rs-1.19.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:b5aab95fe9707c40bfdc78cfcc00f93b04de98e1d7e19ed1bb132dd1e6174022"}, - {file = "serpyco_rs-1.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee815d41ac955f0bff87a35e682fa6299cfe138fbdf6f8fe7deaa501a0b69bbf"}, - {file = "serpyco_rs-1.19.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a396fe59f0d4de76b0b005461e36ce4230a0c84aa08e5bfd9465f1463061b11c"}, - {file = "serpyco_rs-1.19.0-cp312-cp312-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:fae8e4d16de8b145123b052a095e75e257d73305dc440cddcee020d9ae3385ea"}, - {file = "serpyco_rs-1.19.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff027e6c066d0fd65f157f026d748fdcb142cef2ff67368ba896665ff6ce0e6b"}, - {file = "serpyco_rs-1.19.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3785f7fdb2e7b8b4b5b3c73c2d155934cdc8156398ce331f55d2102aa47221f2"}, - {file = "serpyco_rs-1.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66a8aa4547b2ecb03a02f434df3566e29be657f83baac5fe67726729ce9afbc4"}, - {file = "serpyco_rs-1.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:1bb8204cecdd173ddc5650caf5cfbf10646d1aa25bbe3458fe6168708177a583"}, - {file = "serpyco_rs-1.19.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:1a08655fe0c83bd9fb37cc0319c0ae52c32985df41f55e6625a35054dc7fa8eb"}, - {file = "serpyco_rs-1.19.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94b1336669877cc65b711927087196f0980eb6f1e9d0500e0be288bb7b5c25a6"}, - {file = "serpyco_rs-1.19.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:61a5292c6d6885d69e31088a830c5d9a56bf7ae02dff09244553ad63992c09b4"}, - {file = "serpyco_rs-1.19.0-cp313-cp313-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d4e5df44b788f5cf4240a6fea69caf1a31ef18ebcf2e79d7ec23c3673cf26964"}, - {file = "serpyco_rs-1.19.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:500532f693e8296696a7639f4f1cc199c532e6036b1331ffec3bff9f98868cd2"}, - {file = "serpyco_rs-1.19.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b3c50dd263ab3aee304768dfdf271c126723fd8ba8792f1c457512bcb899d02"}, - {file = "serpyco_rs-1.19.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cb72d80dd60ba27244e12d8a99fd507362a87feeb677b2a5a38d050f91ad9ae"}, - {file = "serpyco_rs-1.19.0-cp313-cp313-win_amd64.whl", hash = "sha256:aa1d8d80d4aaf28e9486949e088c3b2e4339fdf78ffc6c91c1ebd968818c00f8"}, - {file = "serpyco_rs-1.19.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:3da26aa9bfccf8e4ccb0da2cdb91f4bd545a349dbf64820962b94128239a5651"}, - {file = "serpyco_rs-1.19.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1120359d721189eded9078cf743caa1f947b68ae5e27c3e886f2bf55935765a0"}, - {file = "serpyco_rs-1.19.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9deffcca1032b174f5e7c429ca160813411b99af90f1100b8c06a18b8b352b21"}, - {file = "serpyco_rs-1.19.0-cp314-cp314-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:037929bf43f26d9031865436cbd967d673030064a9f536a4d8abdd43a2005eea"}, - {file = "serpyco_rs-1.19.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22287dc48b8a688fd8040035feb86b4c6d9e03fc46a7ef37ac64c004b2edc375"}, - {file = "serpyco_rs-1.19.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d1bb4f65a1fa864f682b8516281abd82c5afb967c98487849c5c76378ac2811"}, - {file = "serpyco_rs-1.19.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eca614a2a177240ff3ceb3f945b79cc68352940aa0e1834f849a7d299635b573"}, - {file = "serpyco_rs-1.19.0-cp314-cp314-win_amd64.whl", hash = "sha256:dbb7ee4efedcf4bc5a0936eb6a9f5df85a328b5f89cc5f52ea6f467b1fdc5db4"}, - {file = "serpyco_rs-1.19.0-cp39-cp39-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:ff266550d55a2dfe17240bc440d98d7a3eb25232b59e4321af29e9b365a42fe2"}, - {file = "serpyco_rs-1.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2cb85a4fb3aaeaf238216fa89c32974c7131b378c5d40ee6b8ddd9461b4627c"}, - {file = "serpyco_rs-1.19.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5d6aa3ce4f766e9223f52461b464fe780ff566309d753972d501e86abbc16830"}, - {file = "serpyco_rs-1.19.0-cp39-cp39-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:c68d570a9082eca2f74c477361ba6d380c86fdb534d334e7a704746b7d27a0b2"}, - {file = "serpyco_rs-1.19.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92c3cca6fa1c2bdfbe292993677610e2dd21782cfbb89c48fc757ed336d013f3"}, - {file = "serpyco_rs-1.19.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13ff43f2487a556b7975ab00fbbec3794763048ebe96293e8e09de22dd81bc8b"}, - {file = "serpyco_rs-1.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd1afb01f5b8e8bf53f067f287ede7d5d82cd08343abaeca78e96cde4e6bc4d7"}, - {file = "serpyco_rs-1.19.0-cp39-cp39-win_amd64.whl", hash = "sha256:f22f289f5c300b80210f02d34011b3d83876c508cdc1a7df31fb2ee4b231d960"}, - {file = "serpyco_rs-1.19.0.tar.gz", hash = "sha256:a9fe01ddbc7ffa4f0f57896dda2759ad676937943f66d3c5af2b0472ca6672e6"}, + {file = "serpyco_rs-1.20.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:9672de723ca13a7d19cbe79debcb1b15e29abb939fbf853647dd4c2eac2814e1"}, + {file = "serpyco_rs-1.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8faa295f2e7e32bd502243f8880963d5d5405bbf95205ed4fca75d8da632ff96"}, + {file = "serpyco_rs-1.20.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d1dffbd631ae38f092da1b80e3c703c18d1d905420996ca45b8638c00bf8aea2"}, + {file = "serpyco_rs-1.20.0-cp310-cp310-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:fc6f09348a06eaa681f10cb49783ed7a0799b82050d8d7980c16129c39226ccc"}, + {file = "serpyco_rs-1.20.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1593bfb77acd193714924830f22f5221c0ba085820c8fcf5ae423d53164ab154"}, + {file = "serpyco_rs-1.20.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6c283b536684c3d3b384f56ae66d3360a48f9963cb8d3cce01d1bbbb73d5bed"}, + {file = "serpyco_rs-1.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce100d43438f1c9671f5aa4ad201cb042e60f60f13c9ab5de4676a336cb94036"}, + {file = "serpyco_rs-1.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:dedd4dda1b794b4e8269517e377df98bb10a5c779ebe8bd5a0f471a7b0f243d8"}, + {file = "serpyco_rs-1.20.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:528da9be0d6dcdf1581a356b50758598c076001b4d02af0ce2414b329b877368"}, + {file = "serpyco_rs-1.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c824084410d11f851fc71ed48e9890dd7350f826fc0d5a264f90b432ee80536f"}, + {file = "serpyco_rs-1.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:22bfb92bccb3f406d504314551dbdd4b534167a8692a16321409d8540efbd345"}, + {file = "serpyco_rs-1.20.0-cp311-cp311-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d3dfb0481667f54843742ec863a63b9b45b7a1f3aee702c612fe915794de0795"}, + {file = "serpyco_rs-1.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc4b6afb01f182ae258b57f6371598a442f4794ad27a9f47f6d1bfd121cfccff"}, + {file = "serpyco_rs-1.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:658b6f5f5c2fb320b898d54e210732e4a808cb4b4e081fc53f828e6563d2d452"}, + {file = "serpyco_rs-1.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9616604a8ccafa354636c19670a29393474efdb4178a2f8601744545408064d2"}, + {file = "serpyco_rs-1.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:b4910d64e7ec1cabfc9467350585cda427164bbbd51593c7671e2b1e8caaf4b7"}, + {file = "serpyco_rs-1.20.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4b991516b7257ec97a01d9866e7de6c6fff2a3081494d7d611e5b60f5e4a6bdb"}, + {file = "serpyco_rs-1.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a877002a1500173e6d7455d64ed669c94a2f61bdc0cd4f1085460600f0a9d63d"}, + {file = "serpyco_rs-1.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b120581f7cf66f9ab46299accae9967ab52c7bcada120e26b52592051618f86"}, + {file = "serpyco_rs-1.20.0-cp312-cp312-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:25360c018b6a8ea654df0c93ab1b6ea431e3cedc22e2713de65b34add646fe5c"}, + {file = "serpyco_rs-1.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:804d52984280d08a4b1a5308fb91b8e477eff747aba1c5fce6699f2d0c90171b"}, + {file = "serpyco_rs-1.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d1b6334d19bf88ab83572622bc20aa39f5d5cddb7d5fc78a0878acde569b319"}, + {file = "serpyco_rs-1.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac314fdfe05cb0e70df337d98a47677307d7221bb18c2cba55e1621d2b88fae7"}, + {file = "serpyco_rs-1.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:393597a66cde850a22b2e1830d6beba62c7e9173314875b5faba4d818b56a7ce"}, + {file = "serpyco_rs-1.20.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8e8c60f0e9cd5ba6c11c9f938e85b018e3e3d702426b14372031459439cf7ac8"}, + {file = "serpyco_rs-1.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:426761c7b90c8ef8fa30613a76cc55bb0b0cc7ba146bd4346281547b3877f870"}, + {file = "serpyco_rs-1.20.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1fffbed6181d21b4182457c3ff7efbe7655f60a65e8f52088199683795c64d1d"}, + {file = "serpyco_rs-1.20.0-cp313-cp313-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:46dce08188d40f2ceceb5967d59e339710805b2085ddc97f1564c1835bac526c"}, + {file = "serpyco_rs-1.20.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f44eda5143017eecb223517aef329a2fc4579faec7a36fe97c612661795c213"}, + {file = "serpyco_rs-1.20.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9706b6c329d1d09b2469c3246ce3391d8019132707633323d4806a28b393018f"}, + {file = "serpyco_rs-1.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e3b7acf56ec315649323cf4c7dd4cd109a73589774c49c32699473b97628ebb"}, + {file = "serpyco_rs-1.20.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd2d290b9e1c3d5ba1f91abaaa86509b5caa4373ede2851ab8a5a54efe318d15"}, + {file = "serpyco_rs-1.20.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:3da3da1c0190e72d6bfb2c384ae2f27cfa8b1427494d97ad1e50d7098ae40b35"}, + {file = "serpyco_rs-1.20.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:591955b43ece73b5e15830157820b1843a54b136f576aa2822bc816b6624576e"}, + {file = "serpyco_rs-1.20.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9724ddc2229fe71beaa190ed95e0d0486db9b735359cf00e27cd11e0dc293af7"}, + {file = "serpyco_rs-1.20.0-cp314-cp314-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1e670555c81c4763376bf9d3718b13be0a8a39448d6f9e36a9d5144079beeb3b"}, + {file = "serpyco_rs-1.20.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e50acab829aa88e5189e107e700fe7ff6e93315421772facbc45c1197b439cac"}, + {file = "serpyco_rs-1.20.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cde3ed2635d1d92635670820da5a475f731f43d8e3e53cd5200d2ca86bd35931"}, + {file = "serpyco_rs-1.20.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e35bdf6f25edd115927b7c36b852ef6fa1b16230fa6a0aed490a130dad896a7"}, + {file = "serpyco_rs-1.20.0-cp314-cp314-win_amd64.whl", hash = "sha256:323e9b243dd70f2b74e0eaf645a6d4982912fc14604fc351a083d36879878fb2"}, + {file = "serpyco_rs-1.20.0-cp39-cp39-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:fd616d61a6ff87635ce5d4444efa3e8e99041b6c49f054589c16906e01397308"}, + {file = "serpyco_rs-1.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e916ba4653d987909ff7395d44e9d00f9228e44ac531eaa5d62379eb16c4156"}, + {file = "serpyco_rs-1.20.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eadb5ead1a7a91b53b513701a80e6fa6019e5f4acee5e901149bfdb6a67ae430"}, + {file = "serpyco_rs-1.20.0-cp39-cp39-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:39ed3e346e2d97687f95da0fdd14221bfa91ab97397690023bd67c806293a255"}, + {file = "serpyco_rs-1.20.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d03f8ab67ad77900ac56f03b82123a310f30390bf11b870b8808aee66a42f68"}, + {file = "serpyco_rs-1.20.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:233935af3845001cb99d168ee97f322a1e1cf12197c9f7780180d2cc6d01254c"}, + {file = "serpyco_rs-1.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:663ca1745a27852aba1082a879f17807f4d657aaca56f18331eab55d8ae085ef"}, + {file = "serpyco_rs-1.20.0-cp39-cp39-win_amd64.whl", hash = "sha256:6fbe805416888698252b59d45cc25934a14ff869b1e5d76da678f82fcad4efc1"}, + {file = "serpyco_rs-1.20.0.tar.gz", hash = "sha256:67bc54c09083fc5dc5f1ae0bcc4aea8e96b6129154a8875078b1ba30fbd962a0"}, ] [package.dependencies] @@ -3507,58 +3512,58 @@ widechars = ["wcwidth"] [[package]] name = "tomli" -version = "2.4.0" +version = "2.4.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" files = [ - {file = "tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867"}, - {file = "tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9"}, - {file = "tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95"}, - {file = "tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76"}, - {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d"}, - {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576"}, - {file = "tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a"}, - {file = "tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa"}, - {file = "tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614"}, - {file = "tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1"}, - {file = "tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8"}, - {file = "tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a"}, - {file = "tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1"}, - {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b"}, - {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51"}, - {file = "tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729"}, - {file = "tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da"}, - {file = "tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3"}, - {file = "tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0"}, - {file = "tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e"}, - {file = "tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4"}, - {file = "tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e"}, - {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c"}, - {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f"}, - {file = "tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86"}, - {file = "tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87"}, - {file = "tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132"}, - {file = "tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6"}, - {file = "tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc"}, - {file = "tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66"}, - {file = "tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d"}, - {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702"}, - {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8"}, - {file = "tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776"}, - {file = "tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475"}, - {file = "tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2"}, - {file = "tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9"}, - {file = "tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0"}, - {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df"}, - {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d"}, - {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f"}, - {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b"}, - {file = "tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087"}, - {file = "tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd"}, - {file = "tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4"}, - {file = "tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a"}, - {file = "tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c"}, + {file = "tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30"}, + {file = "tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a"}, + {file = "tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076"}, + {file = "tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9"}, + {file = "tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c"}, + {file = "tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc"}, + {file = "tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049"}, + {file = "tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e"}, + {file = "tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece"}, + {file = "tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a"}, + {file = "tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085"}, + {file = "tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9"}, + {file = "tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5"}, + {file = "tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585"}, + {file = "tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1"}, + {file = "tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917"}, + {file = "tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9"}, + {file = "tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257"}, + {file = "tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54"}, + {file = "tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a"}, + {file = "tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897"}, + {file = "tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f"}, + {file = "tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d"}, + {file = "tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5"}, + {file = "tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd"}, + {file = "tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36"}, + {file = "tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd"}, + {file = "tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf"}, + {file = "tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac"}, + {file = "tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662"}, + {file = "tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853"}, + {file = "tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15"}, + {file = "tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba"}, + {file = "tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6"}, + {file = "tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7"}, + {file = "tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232"}, + {file = "tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4"}, + {file = "tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c"}, + {file = "tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d"}, + {file = "tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41"}, + {file = "tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c"}, + {file = "tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f"}, + {file = "tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8"}, + {file = "tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26"}, + {file = "tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396"}, + {file = "tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe"}, + {file = "tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f"}, ] [[package]] diff --git a/airbyte-integrations/connectors/source-google-drive/pyproject.toml b/airbyte-integrations/connectors/source-google-drive/pyproject.toml index f3f63cf95bd7..829b04c00b58 100644 --- a/airbyte-integrations/connectors/source-google-drive/pyproject.toml +++ b/airbyte-integrations/connectors/source-google-drive/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "0.5.12" +version = "0.5.13" name = "source-google-drive" description = "Source implementation for Google Drive." authors = [ "Airbyte ",] diff --git a/docs/integrations/sources/google-drive.md b/docs/integrations/sources/google-drive.md index 2d008ba4fd8e..745924a55940 100644 --- a/docs/integrations/sources/google-drive.md +++ b/docs/integrations/sources/google-drive.md @@ -324,6 +324,7 @@ By default, this stream is enabled and retrieves information about **users and g | Version | Date | Pull Request | Subject | |---------|------------|----------------------------------------------------------|----------------------------------------------------------------------------------------------| +| 0.5.13 | 2026-03-31 | [75368](https://github.com/airbytehq/airbyte/pull/75368) | Update dependencies | | 0.5.12 | 2026-03-17 | [74923](https://github.com/airbytehq/airbyte/pull/74923) | Update dependencies | | 0.5.11 | 2026-03-03 | [73119](https://github.com/airbytehq/airbyte/pull/73119) | Update dependencies | | 0.5.10 | 2026-02-03 | [72377](https://github.com/airbytehq/airbyte/pull/72377) | Update dependencies | From c0c6d10823330a3506eba875fe8fadfeff086acb Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:42:08 +0000 Subject: [PATCH 154/379] =?UTF-8?q?deps(source-nutshell):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75361)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-nutshell/metadata.yaml | 4 ++-- docs/integrations/sources/nutshell.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-nutshell/metadata.yaml b/airbyte-integrations/connectors/source-nutshell/metadata.yaml index eb1b52185f77..0b5e5058836e 100644 --- a/airbyte-integrations/connectors/source-nutshell/metadata.yaml +++ b/airbyte-integrations/connectors/source-nutshell/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-nutshell connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.10.4@sha256:2f551a3fb5d580b34f4253aa1904d26c309364b09538f0b0fef3d8a98546f795 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 8ac02323-03a3-4026-96f0-68573237c49a - dockerImageTag: 0.0.49 + dockerImageTag: 0.0.50 dockerRepository: airbyte/source-nutshell githubIssueLabel: source-nutshell icon: icon.svg diff --git a/docs/integrations/sources/nutshell.md b/docs/integrations/sources/nutshell.md index 9142e0a5c651..eae4383f1a81 100644 --- a/docs/integrations/sources/nutshell.md +++ b/docs/integrations/sources/nutshell.md @@ -47,6 +47,7 @@ Using this connector we can extract data from various streams such as contacts , | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.50 | 2026-03-31 | [75361](https://github.com/airbytehq/airbyte/pull/75361) | Update dependencies | | 0.0.49 | 2026-03-10 | [74615](https://github.com/airbytehq/airbyte/pull/74615) | Update dependencies | | 0.0.48 | 2026-02-24 | [73581](https://github.com/airbytehq/airbyte/pull/73581) | Update dependencies | | 0.0.47 | 2026-02-10 | [73062](https://github.com/airbytehq/airbyte/pull/73062) | Update dependencies | From a3f215586947e5943d58411854ced807c2bc668c Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:42:19 +0000 Subject: [PATCH 155/379] =?UTF-8?q?deps(source-lob):=20=F0=9F=90=99=20upda?= =?UTF-8?q?te=20dependencies=20[2026-03-31]=20(#75326)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-lob/metadata.yaml | 4 ++-- docs/integrations/sources/lob.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-lob/metadata.yaml b/airbyte-integrations/connectors/source-lob/metadata.yaml index b5951286e4ea..1fb06c51d7ad 100644 --- a/airbyte-integrations/connectors/source-lob/metadata.yaml +++ b/airbyte-integrations/connectors/source-lob/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-lob connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.10.4@sha256:2f551a3fb5d580b34f4253aa1904d26c309364b09538f0b0fef3d8a98546f795 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: c6d14c44-cd3e-4f94-8924-201c5615f3a7 - dockerImageTag: 0.0.50 + dockerImageTag: 0.0.51 dockerRepository: airbyte/source-lob githubIssueLabel: source-lob icon: icon.svg diff --git a/docs/integrations/sources/lob.md b/docs/integrations/sources/lob.md index b058510c55ad..638882e6dab2 100644 --- a/docs/integrations/sources/lob.md +++ b/docs/integrations/sources/lob.md @@ -34,6 +34,7 @@ Visit `https://docs.lob.com/` for API documentation | Version | Date | Pull Request | Subject | | ------------------ | ------------ | --- | ---------------- | +| 0.0.51 | 2026-03-31 | [75326](https://github.com/airbytehq/airbyte/pull/75326) | Update dependencies | | 0.0.50 | 2026-03-10 | [74431](https://github.com/airbytehq/airbyte/pull/74431) | Update dependencies | | 0.0.49 | 2026-03-03 | [72763](https://github.com/airbytehq/airbyte/pull/72763) | Update dependencies | | 0.0.48 | 2026-01-20 | [72037](https://github.com/airbytehq/airbyte/pull/72037) | Update dependencies | From 3144320091489107e5b57c2d8c1c818bc34d28d9 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:42:28 +0000 Subject: [PATCH 156/379] =?UTF-8?q?deps(source-lever-hiring):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75032)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-lever-hiring/metadata.yaml | 4 ++-- docs/integrations/sources/lever-hiring.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-lever-hiring/metadata.yaml b/airbyte-integrations/connectors/source-lever-hiring/metadata.yaml index de3abea71a02..26732c6aa8ed 100644 --- a/airbyte-integrations/connectors/source-lever-hiring/metadata.yaml +++ b/airbyte-integrations/connectors/source-lever-hiring/metadata.yaml @@ -18,11 +18,11 @@ data: # Please update to the latest version of the connector base image. # https://hub.docker.com/r/airbyte/python-connector-base # Please use the full address with sha256 hash to guarantee build reproducibility. - baseImage: docker.io/airbyte/source-declarative-manifest:7.10.1@sha256:bd69f6b52bdd92ce06c30786d67546427b828ffb553363c8950b2816c552d6e0 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 3981c999-bd7d-4afc-849b-e53dea90c948 - dockerImageTag: 0.4.27 + dockerImageTag: 0.4.28 dockerRepository: airbyte/source-lever-hiring githubIssueLabel: source-lever-hiring icon: icon.svg diff --git a/docs/integrations/sources/lever-hiring.md b/docs/integrations/sources/lever-hiring.md index ba03d399a7d5..76781f75c7b7 100644 --- a/docs/integrations/sources/lever-hiring.md +++ b/docs/integrations/sources/lever-hiring.md @@ -46,6 +46,7 @@ The Lever Hiring connector should not run into Lever Hiring API limitations unde | Version | Date | Pull Request | Subject | |:--------|:-----------|:---------------------------------------------------------|:----------------------------------| +| 0.4.28 | 2026-03-31 | [75032](https://github.com/airbytehq/airbyte/pull/75032) | Update dependencies | | 0.4.27 | 2026-02-24 | [73939](https://github.com/airbytehq/airbyte/pull/73939) | Update dependencies | | 0.4.26 | 2026-02-17 | [73554](https://github.com/airbytehq/airbyte/pull/73554) | Update dependencies | | 0.4.25 | 2026-02-10 | [73047](https://github.com/airbytehq/airbyte/pull/73047) | Update dependencies | From 9984563326c68ea3af8c570494e44006d563805c Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:42:32 +0000 Subject: [PATCH 157/379] =?UTF-8?q?deps(source-kissmetrics):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75031)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-kissmetrics/metadata.yaml | 4 ++-- docs/integrations/sources/kissmetrics.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-kissmetrics/metadata.yaml b/airbyte-integrations/connectors/source-kissmetrics/metadata.yaml index 1561af187d70..e0a1a7cb2f3b 100644 --- a/airbyte-integrations/connectors/source-kissmetrics/metadata.yaml +++ b/airbyte-integrations/connectors/source-kissmetrics/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-kissmetrics connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.10.4@sha256:2f551a3fb5d580b34f4253aa1904d26c309364b09538f0b0fef3d8a98546f795 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: ea2607ce-b94d-4218-83f8-724010403c9e - dockerImageTag: 0.0.49 + dockerImageTag: 0.0.50 dockerRepository: airbyte/source-kissmetrics githubIssueLabel: source-kissmetrics icon: icon.svg diff --git a/docs/integrations/sources/kissmetrics.md b/docs/integrations/sources/kissmetrics.md index 6e98f5d9f3ed..2b0bcea8f2f6 100644 --- a/docs/integrations/sources/kissmetrics.md +++ b/docs/integrations/sources/kissmetrics.md @@ -30,6 +30,7 @@ Refer `https://support.kissmetrics.io/reference/authorization` for more details. | Version | Date | Pull Request | Subject | |---------| ------------ | --- | ---------------- | +| 0.0.50 | 2026-03-31 | [75031](https://github.com/airbytehq/airbyte/pull/75031) | Update dependencies | | 0.0.49 | 2026-03-10 | [74442](https://github.com/airbytehq/airbyte/pull/74442) | Update dependencies | | 0.0.48 | 2026-02-24 | [73984](https://github.com/airbytehq/airbyte/pull/73984) | Update dependencies | | 0.0.47 | 2026-02-10 | [72772](https://github.com/airbytehq/airbyte/pull/72772) | Update dependencies | From 36c02325eb9de7f19c441b8d236d7f013f75551b Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:42:40 +0000 Subject: [PATCH 158/379] =?UTF-8?q?deps(source-grafana):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#74931)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-grafana/metadata.yaml | 4 ++-- docs/integrations/sources/grafana.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-grafana/metadata.yaml b/airbyte-integrations/connectors/source-grafana/metadata.yaml index 6a8c17c87cd3..ea936e06f152 100644 --- a/airbyte-integrations/connectors/source-grafana/metadata.yaml +++ b/airbyte-integrations/connectors/source-grafana/metadata.yaml @@ -12,11 +12,11 @@ data: enabled: false packageName: airbyte-source-grafana connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.10.4@sha256:2f551a3fb5d580b34f4253aa1904d26c309364b09538f0b0fef3d8a98546f795 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: bdf17de3-a522-4929-ab63-0205f794f7b4 - dockerImageTag: 0.0.5 + dockerImageTag: 0.0.6 dockerRepository: airbyte/source-grafana githubIssueLabel: source-grafana icon: icon.svg diff --git a/docs/integrations/sources/grafana.md b/docs/integrations/sources/grafana.md index 929a1acef81c..c97ea72cd185 100644 --- a/docs/integrations/sources/grafana.md +++ b/docs/integrations/sources/grafana.md @@ -24,6 +24,7 @@ Grafana is an observability and analytics platform that lets teams visualize, ex | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.6 | 2026-03-31 | [74931](https://github.com/airbytehq/airbyte/pull/74931) | Update dependencies | | 0.0.5 | 2026-03-10 | [74658](https://github.com/airbytehq/airbyte/pull/74658) | Update dependencies | | 0.0.4 | 2026-02-24 | [73967](https://github.com/airbytehq/airbyte/pull/73967) | Update dependencies | | 0.0.3 | 2026-02-10 | [73074](https://github.com/airbytehq/airbyte/pull/73074) | Update dependencies | From d365b38b5905a72824002f85b5f27a43cd60fcd0 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:30:30 +0000 Subject: [PATCH 159/379] =?UTF-8?q?deps(source-salesflare):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75840)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-salesflare/metadata.yaml | 4 ++-- docs/integrations/sources/salesflare.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-salesflare/metadata.yaml b/airbyte-integrations/connectors/source-salesflare/metadata.yaml index f0f581614f26..45ace06016b7 100644 --- a/airbyte-integrations/connectors/source-salesflare/metadata.yaml +++ b/airbyte-integrations/connectors/source-salesflare/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-salesflare connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: a312f5ec-ba92-4c5b-a03c-197fbd961b91 - dockerImageTag: 0.0.44 + dockerImageTag: 0.0.45 dockerRepository: airbyte/source-salesflare githubIssueLabel: source-salesflare icon: icon.svg diff --git a/docs/integrations/sources/salesflare.md b/docs/integrations/sources/salesflare.md index 322f1c16f4da..d82e45c3d6bb 100644 --- a/docs/integrations/sources/salesflare.md +++ b/docs/integrations/sources/salesflare.md @@ -31,6 +31,7 @@ Docs : https://api.salesflare.com/docs | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.45 | 2026-03-31 | [75840](https://github.com/airbytehq/airbyte/pull/75840) | Update dependencies | | 0.0.44 | 2026-03-24 | [75335](https://github.com/airbytehq/airbyte/pull/75335) | Update dependencies | | 0.0.43 | 2026-03-10 | [74675](https://github.com/airbytehq/airbyte/pull/74675) | Update dependencies | | 0.0.42 | 2026-02-24 | [73179](https://github.com/airbytehq/airbyte/pull/73179) | Update dependencies | From 7b19878447f86fda28e79d2a3e61b3a3f659d129 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:30:37 +0000 Subject: [PATCH 160/379] =?UTF-8?q?deps(source-zoom):=20=F0=9F=90=99=20upd?= =?UTF-8?q?ate=20dependencies=20[2026-03-31]=20(#75837)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-zoom/metadata.yaml | 4 ++-- docs/integrations/sources/zoom.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-zoom/metadata.yaml b/airbyte-integrations/connectors/source-zoom/metadata.yaml index bd5cc1e8f646..a2c25596560f 100644 --- a/airbyte-integrations/connectors/source-zoom/metadata.yaml +++ b/airbyte-integrations/connectors/source-zoom/metadata.yaml @@ -3,11 +3,11 @@ data: ql: 200 sl: 100 connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: cbfd9856-1322-44fb-bcf1-0b39b7a8e92e - dockerImageTag: 1.2.46 + dockerImageTag: 1.2.47 dockerRepository: airbyte/source-zoom documentationUrl: https://docs.airbyte.com/integrations/sources/zoom githubIssueLabel: source-zoom diff --git a/docs/integrations/sources/zoom.md b/docs/integrations/sources/zoom.md index 3b96d7465695..81be71640dfa 100644 --- a/docs/integrations/sources/zoom.md +++ b/docs/integrations/sources/zoom.md @@ -71,6 +71,7 @@ JWT Tokens are deprecated, only Server-to-Server works now. [link to Zoom](https | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :--------------------------------------------------- | +| 1.2.47 | 2026-03-31 | [75837](https://github.com/airbytehq/airbyte/pull/75837) | Update dependencies | | 1.2.46 | 2026-03-24 | [75052](https://github.com/airbytehq/airbyte/pull/75052) | Update dependencies | | 1.2.45 | 2026-03-10 | [74448](https://github.com/airbytehq/airbyte/pull/74448) | Update dependencies | | 1.2.44 | 2026-02-24 | [73991](https://github.com/airbytehq/airbyte/pull/73991) | Update dependencies | From 4e7e79ae77c448d8cdd100134938ec786b09e4ed Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:30:42 +0000 Subject: [PATCH 161/379] =?UTF-8?q?deps(source-zoho-desk):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75836)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-zoho-desk/metadata.yaml | 4 ++-- docs/integrations/sources/zoho-desk.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-zoho-desk/metadata.yaml b/airbyte-integrations/connectors/source-zoho-desk/metadata.yaml index 03df4aeb96b9..623217614071 100644 --- a/airbyte-integrations/connectors/source-zoho-desk/metadata.yaml +++ b/airbyte-integrations/connectors/source-zoho-desk/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-zoho-desk connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 08164461-a3fd-49d5-8185-b83d51013585 - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-zoho-desk githubIssueLabel: source-zoho-desk icon: icon.svg diff --git a/docs/integrations/sources/zoho-desk.md b/docs/integrations/sources/zoho-desk.md index d4d953f6ff72..0282f2154b7e 100644 --- a/docs/integrations/sources/zoho-desk.md +++ b/docs/integrations/sources/zoho-desk.md @@ -57,6 +57,7 @@ This directory contains the manifest-only connector for source-zoho-desk | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.48 | 2026-03-31 | [75836](https://github.com/airbytehq/airbyte/pull/75836) | Update dependencies | | 0.0.47 | 2026-03-17 | [75045](https://github.com/airbytehq/airbyte/pull/75045) | Update dependencies | | 0.0.46 | 2026-03-10 | [74438](https://github.com/airbytehq/airbyte/pull/74438) | Update dependencies | | 0.0.45 | 2026-02-24 | [73988](https://github.com/airbytehq/airbyte/pull/73988) | Update dependencies | From fa0c615515fdadcee626df3da50da096dc9691c1 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:30:49 +0000 Subject: [PATCH 162/379] =?UTF-8?q?deps(source-zoho-expense):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75835)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-zoho-expense/metadata.yaml | 4 ++-- docs/integrations/sources/zoho-expense.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-zoho-expense/metadata.yaml b/airbyte-integrations/connectors/source-zoho-expense/metadata.yaml index 2374bc088141..605d28b4d2ef 100644 --- a/airbyte-integrations/connectors/source-zoho-expense/metadata.yaml +++ b/airbyte-integrations/connectors/source-zoho-expense/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-zoho-expense connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 9acfeefc-dad6-4887-a928-6c15ce5737b6 - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-zoho-expense githubIssueLabel: source-zoho-expense icon: icon.svg diff --git a/docs/integrations/sources/zoho-expense.md b/docs/integrations/sources/zoho-expense.md index 7c2c2de03d49..0b09c6f78fad 100644 --- a/docs/integrations/sources/zoho-expense.md +++ b/docs/integrations/sources/zoho-expense.md @@ -31,6 +31,7 @@ Zoho Expense connector enables seamless data synchronization between Zoho Expens | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.49 | 2026-03-31 | [75835](https://github.com/airbytehq/airbyte/pull/75835) | Update dependencies | | 0.0.48 | 2026-03-24 | [75367](https://github.com/airbytehq/airbyte/pull/75367) | Update dependencies | | 0.0.47 | 2026-03-10 | [74464](https://github.com/airbytehq/airbyte/pull/74464) | Update dependencies | | 0.0.46 | 2026-02-24 | [73995](https://github.com/airbytehq/airbyte/pull/73995) | Update dependencies | From b69cfea044ce8b2e10fed549c316298ec15a3794 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:30:55 +0000 Subject: [PATCH 163/379] =?UTF-8?q?deps(source-mercado-ads):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75834)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-mercado-ads/metadata.yaml | 4 ++-- docs/integrations/sources/mercado-ads.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-mercado-ads/metadata.yaml b/airbyte-integrations/connectors/source-mercado-ads/metadata.yaml index 25712d15a032..49efce795177 100644 --- a/airbyte-integrations/connectors/source-mercado-ads/metadata.yaml +++ b/airbyte-integrations/connectors/source-mercado-ads/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-mercado-ads connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: ada19dae-81e5-4241-8e64-a9b2680b1b35 - dockerImageTag: 0.0.26 + dockerImageTag: 0.0.27 dockerRepository: airbyte/source-mercado-ads githubIssueLabel: source-mercado-ads icon: icon.svg diff --git a/docs/integrations/sources/mercado-ads.md b/docs/integrations/sources/mercado-ads.md index 9e82cdc58d70..712743e74b5f 100644 --- a/docs/integrations/sources/mercado-ads.md +++ b/docs/integrations/sources/mercado-ads.md @@ -40,6 +40,7 @@ Get ad analytics from all Mercado Ads placements | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.27 | 2026-03-31 | [75834](https://github.com/airbytehq/airbyte/pull/75834) | Update dependencies | | 0.0.26 | 2026-03-24 | [74582](https://github.com/airbytehq/airbyte/pull/74582) | Update dependencies | | 0.0.25 | 2026-02-24 | [73811](https://github.com/airbytehq/airbyte/pull/73811) | Update dependencies | | 0.0.24 | 2026-02-17 | [73382](https://github.com/airbytehq/airbyte/pull/73382) | Update dependencies | From 4774e618c9823f47cf3caa806bff54274319ecdc Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:31:00 +0000 Subject: [PATCH 164/379] =?UTF-8?q?deps(source-zoho-billing):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75833)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-zoho-billing/metadata.yaml | 4 ++-- docs/integrations/sources/zoho-billing.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-zoho-billing/metadata.yaml b/airbyte-integrations/connectors/source-zoho-billing/metadata.yaml index a010ca3b1de0..a0464bb540f1 100644 --- a/airbyte-integrations/connectors/source-zoho-billing/metadata.yaml +++ b/airbyte-integrations/connectors/source-zoho-billing/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-zoho-billing connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: cd0c7d19-6189-4ed2-9c9f-663d1bea7789 - dockerImageTag: 0.0.46 + dockerImageTag: 0.0.47 dockerRepository: airbyte/source-zoho-billing githubIssueLabel: source-zoho-billing icon: icon.svg diff --git a/docs/integrations/sources/zoho-billing.md b/docs/integrations/sources/zoho-billing.md index f2cedaba3872..9d5657ce4f60 100644 --- a/docs/integrations/sources/zoho-billing.md +++ b/docs/integrations/sources/zoho-billing.md @@ -35,6 +35,7 @@ Docs : https://www.zoho.com/billing/api/v1/introduction/#overview | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.47 | 2026-03-31 | [75833](https://github.com/airbytehq/airbyte/pull/75833) | Update dependencies | | 0.0.46 | 2026-03-24 | [74466](https://github.com/airbytehq/airbyte/pull/74466) | Update dependencies | | 0.0.45 | 2026-02-24 | [73987](https://github.com/airbytehq/airbyte/pull/73987) | Update dependencies | | 0.0.44 | 2026-02-17 | [73590](https://github.com/airbytehq/airbyte/pull/73590) | Update dependencies | From a4493f43dc9648240042c4fe70f70b55947fa0aa Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:31:07 +0000 Subject: [PATCH 165/379] =?UTF-8?q?deps(source-zoho-analytics-metadata-api?= =?UTF-8?q?):=20=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75?= =?UTF-8?q?831)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../source-zoho-analytics-metadata-api/metadata.yaml | 4 ++-- docs/integrations/sources/zoho-analytics-metadata-api.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-zoho-analytics-metadata-api/metadata.yaml b/airbyte-integrations/connectors/source-zoho-analytics-metadata-api/metadata.yaml index c63405504bf8..13fefa706a0e 100644 --- a/airbyte-integrations/connectors/source-zoho-analytics-metadata-api/metadata.yaml +++ b/airbyte-integrations/connectors/source-zoho-analytics-metadata-api/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-zoho-analytics-metadata-api connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 63114ebf-1c0e-4e6e-bb93-28ae03332b14 - dockerImageTag: 0.0.49 + dockerImageTag: 0.0.50 dockerRepository: airbyte/source-zoho-analytics-metadata-api githubIssueLabel: source-zoho-analytics-metadata-api icon: icon.svg diff --git a/docs/integrations/sources/zoho-analytics-metadata-api.md b/docs/integrations/sources/zoho-analytics-metadata-api.md index 684ce43e73d0..353a20508524 100644 --- a/docs/integrations/sources/zoho-analytics-metadata-api.md +++ b/docs/integrations/sources/zoho-analytics-metadata-api.md @@ -30,6 +30,7 @@ Zoho Analytics Metadata api connector enables seamless data syncing from Zoho An | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.50 | 2026-03-31 | [75831](https://github.com/airbytehq/airbyte/pull/75831) | Update dependencies | | 0.0.49 | 2026-03-24 | [74461](https://github.com/airbytehq/airbyte/pull/74461) | Update dependencies | | 0.0.48 | 2026-02-24 | [73989](https://github.com/airbytehq/airbyte/pull/73989) | Update dependencies | | 0.0.47 | 2026-02-17 | [73591](https://github.com/airbytehq/airbyte/pull/73591) | Update dependencies | From 8831ae26c6b048167743fa7f4727f7b90ae6919f Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:31:14 +0000 Subject: [PATCH 166/379] =?UTF-8?q?deps(source-mailosaur):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75830)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-mailosaur/metadata.yaml | 4 ++-- docs/integrations/sources/mailosaur.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-mailosaur/metadata.yaml b/airbyte-integrations/connectors/source-mailosaur/metadata.yaml index 1802ce28465a..274dc30e969c 100644 --- a/airbyte-integrations/connectors/source-mailosaur/metadata.yaml +++ b/airbyte-integrations/connectors/source-mailosaur/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-mailosaur connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 251ed5c8-a927-4fb4-ad45-75393d564f3c - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-mailosaur githubIssueLabel: source-mailosaur icon: icon.svg diff --git a/docs/integrations/sources/mailosaur.md b/docs/integrations/sources/mailosaur.md index 73a4c4c0677a..df88b28c65bd 100644 --- a/docs/integrations/sources/mailosaur.md +++ b/docs/integrations/sources/mailosaur.md @@ -24,6 +24,7 @@ Docs : https://mailosaur.com/docs | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.48 | 2026-03-31 | [75830](https://github.com/airbytehq/airbyte/pull/75830) | Update dependencies | | 0.0.47 | 2026-03-17 | [74978](https://github.com/airbytehq/airbyte/pull/74978) | Update dependencies | | 0.0.46 | 2026-03-10 | [74539](https://github.com/airbytehq/airbyte/pull/74539) | Update dependencies | | 0.0.45 | 2026-02-24 | [73810](https://github.com/airbytehq/airbyte/pull/73810) | Update dependencies | From c4c1101d7365187437b7d86e0fe210dc304d6753 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:31:21 +0000 Subject: [PATCH 167/379] =?UTF-8?q?deps(source-marketstack):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75829)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-marketstack/metadata.yaml | 4 ++-- docs/integrations/sources/marketstack.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-marketstack/metadata.yaml b/airbyte-integrations/connectors/source-marketstack/metadata.yaml index b99aa3387147..0f332d7304a1 100644 --- a/airbyte-integrations/connectors/source-marketstack/metadata.yaml +++ b/airbyte-integrations/connectors/source-marketstack/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-marketstack connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 0caeba13-0807-46aa-a6c0-7e8d25d168be - dockerImageTag: 0.0.49 + dockerImageTag: 0.0.50 dockerRepository: airbyte/source-marketstack githubIssueLabel: source-marketstack icon: icon.svg diff --git a/docs/integrations/sources/marketstack.md b/docs/integrations/sources/marketstack.md index 08686e1968e3..7163605df19b 100644 --- a/docs/integrations/sources/marketstack.md +++ b/docs/integrations/sources/marketstack.md @@ -25,6 +25,7 @@ Using this connector we can extract Historical Data , Splits and Dividends data | Version | Date | Pull Request | Subject | |---------|-------------------|--------------|----------------| +| 0.0.50 | 2026-03-31 | [75829](https://github.com/airbytehq/airbyte/pull/75829) | Update dependencies | | 0.0.49 | 2026-03-24 | [73831](https://github.com/airbytehq/airbyte/pull/73831) | Update dependencies | | 0.0.48 | 2026-02-17 | [73396](https://github.com/airbytehq/airbyte/pull/73396) | Update dependencies | | 0.0.47 | 2026-02-10 | [73205](https://github.com/airbytehq/airbyte/pull/73205) | Update dependencies | From 43afb715f3d46ec98bca583020d22dd88c4ed449 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:31:28 +0000 Subject: [PATCH 168/379] =?UTF-8?q?deps(source-mendeley):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75828)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-mendeley/metadata.yaml | 4 ++-- docs/integrations/sources/mendeley.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-mendeley/metadata.yaml b/airbyte-integrations/connectors/source-mendeley/metadata.yaml index 4537da05c233..5d887dd81a0a 100644 --- a/airbyte-integrations/connectors/source-mendeley/metadata.yaml +++ b/airbyte-integrations/connectors/source-mendeley/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-mendeley connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 9a24ef99-06b5-4e04-9d9e-09e41e5e2a24 - dockerImageTag: 0.0.32 + dockerImageTag: 0.0.33 dockerRepository: airbyte/source-mendeley githubIssueLabel: source-mendeley icon: icon.svg diff --git a/docs/integrations/sources/mendeley.md b/docs/integrations/sources/mendeley.md index e774f2d39e7b..15c2fc22aa69 100644 --- a/docs/integrations/sources/mendeley.md +++ b/docs/integrations/sources/mendeley.md @@ -35,6 +35,7 @@ API Reference: https://dev.mendeley.com/methods/#introduction | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.33 | 2026-03-31 | [75828](https://github.com/airbytehq/airbyte/pull/75828) | Update dependencies | | 0.0.32 | 2026-03-17 | [74980](https://github.com/airbytehq/airbyte/pull/74980) | Update dependencies | | 0.0.31 | 2026-03-10 | [74543](https://github.com/airbytehq/airbyte/pull/74543) | Update dependencies | | 0.0.30 | 2026-02-24 | [73420](https://github.com/airbytehq/airbyte/pull/73420) | Update dependencies | From 5b7ae418ec2342c28f2b06dc902cb3f67382127e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:31:33 +0000 Subject: [PATCH 169/379] =?UTF-8?q?deps(source-revenuecat):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75827)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-revenuecat/metadata.yaml | 4 ++-- docs/integrations/sources/revenuecat.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-revenuecat/metadata.yaml b/airbyte-integrations/connectors/source-revenuecat/metadata.yaml index 7fdb2c550844..45a69059d06e 100644 --- a/airbyte-integrations/connectors/source-revenuecat/metadata.yaml +++ b/airbyte-integrations/connectors/source-revenuecat/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-revenuecat connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: d8b3b5d6-7b64-49f7-9e73-73a1da277cf2 - dockerImageTag: 0.1.32 + dockerImageTag: 0.1.33 dockerRepository: airbyte/source-revenuecat githubIssueLabel: source-revenuecat icon: icon.svg diff --git a/docs/integrations/sources/revenuecat.md b/docs/integrations/sources/revenuecat.md index bb590e567df6..767409caeba1 100644 --- a/docs/integrations/sources/revenuecat.md +++ b/docs/integrations/sources/revenuecat.md @@ -49,6 +49,7 @@ To get started; | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.1.33 | 2026-03-31 | [75827](https://github.com/airbytehq/airbyte/pull/75827) | Update dependencies | | 0.1.32 | 2026-03-24 | [75351](https://github.com/airbytehq/airbyte/pull/75351) | Update dependencies | | 0.1.31 | 2026-03-10 | [74699](https://github.com/airbytehq/airbyte/pull/74699) | Update dependencies | | 0.1.30 | 2026-02-24 | [73745](https://github.com/airbytehq/airbyte/pull/73745) | Update dependencies | From 8c9838b4d2c177f7e2d4c0151e7dfe49f9e23365 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:31:39 +0000 Subject: [PATCH 170/379] =?UTF-8?q?deps(source-pendo):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75826)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-pendo/metadata.yaml | 4 ++-- docs/integrations/sources/pendo.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-pendo/metadata.yaml b/airbyte-integrations/connectors/source-pendo/metadata.yaml index 5252fb48df59..c8660498e741 100644 --- a/airbyte-integrations/connectors/source-pendo/metadata.yaml +++ b/airbyte-integrations/connectors/source-pendo/metadata.yaml @@ -3,11 +3,11 @@ data: ql: 100 sl: 100 connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: b1ccb590-e84f-46c0-83a0-2048ccfffdae - dockerImageTag: 0.2.46 + dockerImageTag: 0.2.47 dockerRepository: airbyte/source-pendo documentationUrl: https://docs.airbyte.com/integrations/sources/pendo githubIssueLabel: source-pendo diff --git a/docs/integrations/sources/pendo.md b/docs/integrations/sources/pendo.md index 664407511f3a..088bbbc13ac0 100644 --- a/docs/integrations/sources/pendo.md +++ b/docs/integrations/sources/pendo.md @@ -64,6 +64,7 @@ The Pendo source connector supports the following [sync modes](https://docs.airb | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------ | +| 0.2.47 | 2026-03-31 | [75826](https://github.com/airbytehq/airbyte/pull/75826) | Update dependencies | | 0.2.46 | 2026-03-24 | [74455](https://github.com/airbytehq/airbyte/pull/74455) | Update dependencies | | 0.2.45 | 2026-02-24 | [73847](https://github.com/airbytehq/airbyte/pull/73847) | Update dependencies | | 0.2.44 | 2026-02-17 | [73577](https://github.com/airbytehq/airbyte/pull/73577) | Update dependencies | From c742720e04ff128e0422c53f7d62f0a466d581a3 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:31:45 +0000 Subject: [PATCH 171/379] =?UTF-8?q?deps(source-safetyculture):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75825)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-safetyculture/metadata.yaml | 4 ++-- docs/integrations/sources/safetyculture.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-safetyculture/metadata.yaml b/airbyte-integrations/connectors/source-safetyculture/metadata.yaml index f90ac4d90be7..6d5549995cc1 100644 --- a/airbyte-integrations/connectors/source-safetyculture/metadata.yaml +++ b/airbyte-integrations/connectors/source-safetyculture/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-safetyculture connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 570b875e-52d9-40e0-a43c-340ebae2d9f8 - dockerImageTag: 0.0.54 + dockerImageTag: 0.0.55 dockerRepository: airbyte/source-safetyculture githubIssueLabel: source-safetyculture icon: icon.svg diff --git a/docs/integrations/sources/safetyculture.md b/docs/integrations/sources/safetyculture.md index 37ad7ec38c14..eabd2c0a7fba 100644 --- a/docs/integrations/sources/safetyculture.md +++ b/docs/integrations/sources/safetyculture.md @@ -54,6 +54,7 @@ The source connector supports the following [sync modes](https://docs.airbyte.co | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.55 | 2026-03-31 | [75825](https://github.com/airbytehq/airbyte/pull/75825) | Update dependencies | | 0.0.54 | 2026-03-24 | [75340](https://github.com/airbytehq/airbyte/pull/75340) | Update dependencies | | 0.0.53 | 2026-03-10 | [74677](https://github.com/airbytehq/airbyte/pull/74677) | Update dependencies | | 0.0.52 | 2026-02-24 | [73770](https://github.com/airbytehq/airbyte/pull/73770) | Update dependencies | From 62be903d7eeee48e815792507df2c4b0aa18ee08 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:31:51 +0000 Subject: [PATCH 172/379] =?UTF-8?q?deps(source-repairshopr):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75824)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-repairshopr/metadata.yaml | 4 ++-- docs/integrations/sources/repairshopr.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-repairshopr/metadata.yaml b/airbyte-integrations/connectors/source-repairshopr/metadata.yaml index 6f62e4242413..40dee48676cc 100644 --- a/airbyte-integrations/connectors/source-repairshopr/metadata.yaml +++ b/airbyte-integrations/connectors/source-repairshopr/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-repairshopr connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: d12ba86d-e393-4269-a6b7-4eddcba98eb4 - dockerImageTag: 0.0.44 + dockerImageTag: 0.0.45 dockerRepository: airbyte/source-repairshopr githubIssueLabel: source-repairshopr icon: icon.svg diff --git a/docs/integrations/sources/repairshopr.md b/docs/integrations/sources/repairshopr.md index 2e54d033815e..cc8f6b59f001 100644 --- a/docs/integrations/sources/repairshopr.md +++ b/docs/integrations/sources/repairshopr.md @@ -35,6 +35,7 @@ With this connector we can extract data from various streams such as customers , | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.45 | 2026-03-31 | [75824](https://github.com/airbytehq/airbyte/pull/75824) | Update dependencies | | 0.0.44 | 2026-03-24 | [75334](https://github.com/airbytehq/airbyte/pull/75334) | Update dependencies | | 0.0.43 | 2026-03-10 | [74678](https://github.com/airbytehq/airbyte/pull/74678) | Update dependencies | | 0.0.42 | 2026-02-24 | [73744](https://github.com/airbytehq/airbyte/pull/73744) | Update dependencies | From 660ff56bfe53012d8f40d7647bfd5fe4989c2d29 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:31:58 +0000 Subject: [PATCH 173/379] =?UTF-8?q?deps(source-rocketlane):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75823)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-rocketlane/metadata.yaml | 4 ++-- docs/integrations/sources/rocketlane.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-rocketlane/metadata.yaml b/airbyte-integrations/connectors/source-rocketlane/metadata.yaml index e4437d512176..a1ad429c98bf 100644 --- a/airbyte-integrations/connectors/source-rocketlane/metadata.yaml +++ b/airbyte-integrations/connectors/source-rocketlane/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-rocketlane connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 6c817011-0b41-47ce-9b50-0274e0c6b127 - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-rocketlane githubIssueLabel: source-rocketlane icon: icon.svg diff --git a/docs/integrations/sources/rocketlane.md b/docs/integrations/sources/rocketlane.md index 8a23a39d0e3f..ea6632dcaa97 100644 --- a/docs/integrations/sources/rocketlane.md +++ b/docs/integrations/sources/rocketlane.md @@ -27,6 +27,7 @@ Rocketlane connector enables seamless data integration by syncing project, task | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.49 | 2026-03-31 | [75823](https://github.com/airbytehq/airbyte/pull/75823) | Update dependencies | | 0.0.48 | 2026-03-24 | [75342](https://github.com/airbytehq/airbyte/pull/75342) | Update dependencies | | 0.0.47 | 2026-03-10 | [74694](https://github.com/airbytehq/airbyte/pull/74694) | Update dependencies | | 0.0.46 | 2026-02-24 | [73479](https://github.com/airbytehq/airbyte/pull/73479) | Update dependencies | From 862859f3e6a9859bcf25aa877d6de21cf887a6c4 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:32:05 +0000 Subject: [PATCH 174/379] =?UTF-8?q?deps(source-persona):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75822)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-persona/metadata.yaml | 4 ++-- docs/integrations/sources/persona.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-persona/metadata.yaml b/airbyte-integrations/connectors/source-persona/metadata.yaml index 55200259f2b8..8af3f65c94eb 100644 --- a/airbyte-integrations/connectors/source-persona/metadata.yaml +++ b/airbyte-integrations/connectors/source-persona/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-persona connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 7e55429a-a1ea-43c2-81c2-4fc3cf88f81f - dockerImageTag: 0.0.50 + dockerImageTag: 0.0.51 dockerRepository: airbyte/source-persona githubIssueLabel: source-persona icon: icon.svg diff --git a/docs/integrations/sources/persona.md b/docs/integrations/sources/persona.md index 09db6738b70d..25d2504ec863 100644 --- a/docs/integrations/sources/persona.md +++ b/docs/integrations/sources/persona.md @@ -28,6 +28,7 @@ Airbyte connector for [Persona](https://withpersona.com) that makes it easy to m | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.51 | 2026-03-31 | [75822](https://github.com/airbytehq/airbyte/pull/75822) | Update dependencies | | 0.0.50 | 2026-03-24 | [75402](https://github.com/airbytehq/airbyte/pull/75402) | Update dependencies | | 0.0.49 | 2026-03-10 | [74481](https://github.com/airbytehq/airbyte/pull/74481) | Update dependencies | | 0.0.48 | 2026-03-03 | [74157](https://github.com/airbytehq/airbyte/pull/74157) | Update dependencies | From 605dfb312c8a098b55d16d75388696921997b18f Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:32:11 +0000 Subject: [PATCH 175/379] =?UTF-8?q?deps(source-revolut-merchant):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75821)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-revolut-merchant/metadata.yaml | 4 ++-- docs/integrations/sources/revolut-merchant.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-revolut-merchant/metadata.yaml b/airbyte-integrations/connectors/source-revolut-merchant/metadata.yaml index 16028e571b12..40cba756443e 100644 --- a/airbyte-integrations/connectors/source-revolut-merchant/metadata.yaml +++ b/airbyte-integrations/connectors/source-revolut-merchant/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-revolut-merchant connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 47a7a5cf-7bfa-406e-8ef8-f23cd041866b - dockerImageTag: 0.0.46 + dockerImageTag: 0.0.47 dockerRepository: airbyte/source-revolut-merchant githubIssueLabel: source-revolut-merchant icon: icon.svg diff --git a/docs/integrations/sources/revolut-merchant.md b/docs/integrations/sources/revolut-merchant.md index 491cdaa322c5..1f400ad1f328 100644 --- a/docs/integrations/sources/revolut-merchant.md +++ b/docs/integrations/sources/revolut-merchant.md @@ -34,6 +34,7 @@ You can find more about the API here https://developer.revolut.com/docs/merchant | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.47 | 2026-03-31 | [75821](https://github.com/airbytehq/airbyte/pull/75821) | Update dependencies | | 0.0.46 | 2026-03-17 | [74960](https://github.com/airbytehq/airbyte/pull/74960) | Update dependencies | | 0.0.45 | 2026-03-10 | [74689](https://github.com/airbytehq/airbyte/pull/74689) | Update dependencies | | 0.0.44 | 2026-02-24 | [73771](https://github.com/airbytehq/airbyte/pull/73771) | Update dependencies | From c6131c72be09638f07d033c1dbc96fae9754ff8a Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:32:21 +0000 Subject: [PATCH 176/379] =?UTF-8?q?deps(source-pardot):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75820)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-pardot/metadata.yaml | 4 ++-- docs/integrations/sources/pardot.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-pardot/metadata.yaml b/airbyte-integrations/connectors/source-pardot/metadata.yaml index 8f91ea270931..57d30b8c10e4 100644 --- a/airbyte-integrations/connectors/source-pardot/metadata.yaml +++ b/airbyte-integrations/connectors/source-pardot/metadata.yaml @@ -2,7 +2,7 @@ data: connectorSubtype: api connectorType: source definitionId: ad15c7ba-72a7-440b-af15-b9a963dc1a8a - dockerImageTag: 1.0.39 + dockerImageTag: 1.0.40 dockerRepository: airbyte/source-pardot githubIssueLabel: source-pardot icon: salesforcepardot.svg @@ -34,7 +34,7 @@ data: connectorTestSuitesOptions: - suite: unitTests connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e externalDocumentationUrls: - title: Pardot API reference url: https://developer.salesforce.com/docs/marketing/pardot/overview diff --git a/docs/integrations/sources/pardot.md b/docs/integrations/sources/pardot.md index 005fcc8a58ff..e28c38cfa271 100644 --- a/docs/integrations/sources/pardot.md +++ b/docs/integrations/sources/pardot.md @@ -94,6 +94,7 @@ If there are more endpoints you'd like Airbyte to support, please [create an iss | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :-------------------- | +| 1.0.40 | 2026-03-31 | [75820](https://github.com/airbytehq/airbyte/pull/75820) | Update dependencies | | 1.0.39 | 2026-03-24 | [75021](https://github.com/airbytehq/airbyte/pull/75021) | Update dependencies | | 1.0.38 | 2026-03-10 | [74501](https://github.com/airbytehq/airbyte/pull/74501) | Update dependencies | | 1.0.37 | 2026-03-03 | [74170](https://github.com/airbytehq/airbyte/pull/74170) | Update dependencies | From 96eae6e589a7ae47570c0c630a89f33d35a3fa88 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:32:28 +0000 Subject: [PATCH 177/379] =?UTF-8?q?deps(source-sap-fieldglass):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75819)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-sap-fieldglass/metadata.yaml | 4 ++-- docs/integrations/sources/sap-fieldglass.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-sap-fieldglass/metadata.yaml b/airbyte-integrations/connectors/source-sap-fieldglass/metadata.yaml index b82faa01cb5d..a295c44c4198 100644 --- a/airbyte-integrations/connectors/source-sap-fieldglass/metadata.yaml +++ b/airbyte-integrations/connectors/source-sap-fieldglass/metadata.yaml @@ -2,7 +2,7 @@ data: connectorSubtype: api connectorType: source definitionId: ec5f3102-fb31-4916-99ae-864faf8e7e25 - dockerImageTag: 0.2.36 + dockerImageTag: 0.2.37 dockerRepository: airbyte/source-sap-fieldglass githubIssueLabel: source-sap-fieldglass icon: sapfieldglass.svg @@ -39,7 +39,7 @@ data: type: GSM alias: airbyte-connector-testing-secret-store connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e externalDocumentationUrls: - title: SAP Fieldglass API url: https://api.sap.com/package/SAPFieldglass/rest diff --git a/docs/integrations/sources/sap-fieldglass.md b/docs/integrations/sources/sap-fieldglass.md index 68af473706b0..bfd6ecae8729 100644 --- a/docs/integrations/sources/sap-fieldglass.md +++ b/docs/integrations/sources/sap-fieldglass.md @@ -25,6 +25,7 @@ This page contains the setup guide and reference information for the SAP Fieldgl | Version | Date | Pull Request | Subject | | :------ | :--------- | :---------------------------------------------- |:--------------------------------------------| +| 0.2.37 | 2026-03-31 | [75819](https://github.com/airbytehq/airbyte/pull/75819) | Update dependencies | | 0.2.36 | 2026-03-24 | [75336](https://github.com/airbytehq/airbyte/pull/75336) | Update dependencies | | 0.2.35 | 2026-03-10 | [74695](https://github.com/airbytehq/airbyte/pull/74695) | Update dependencies | | 0.2.34 | 2026-02-24 | [73492](https://github.com/airbytehq/airbyte/pull/73492) | Update dependencies | From 9c5321604f2a97d99469efbad84bbe30b4c5aa60 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:32:37 +0000 Subject: [PATCH 178/379] =?UTF-8?q?deps(source-partnerize):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75818)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-partnerize/metadata.yaml | 4 ++-- docs/integrations/sources/partnerize.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-partnerize/metadata.yaml b/airbyte-integrations/connectors/source-partnerize/metadata.yaml index 417d5489e957..5c81c46eab02 100644 --- a/airbyte-integrations/connectors/source-partnerize/metadata.yaml +++ b/airbyte-integrations/connectors/source-partnerize/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-partnerize connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.10.4@sha256:2f551a3fb5d580b34f4253aa1904d26c309364b09538f0b0fef3d8a98546f795 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: f3a62a08-635e-4e54-93c8-fc6c7b13ff68 - dockerImageTag: 0.0.32 + dockerImageTag: 0.0.33 dockerRepository: airbyte/source-partnerize githubIssueLabel: source-partnerize icon: icon.svg diff --git a/docs/integrations/sources/partnerize.md b/docs/integrations/sources/partnerize.md index 2e64971045e0..4556214e3170 100644 --- a/docs/integrations/sources/partnerize.md +++ b/docs/integrations/sources/partnerize.md @@ -29,6 +29,7 @@ Documentation: https://api-docs.partnerize.com/partner/#section/Introduction | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.33 | 2026-03-31 | [75818](https://github.com/airbytehq/airbyte/pull/75818) | Update dependencies | | 0.0.32 | 2026-03-10 | [74479](https://github.com/airbytehq/airbyte/pull/74479) | Update dependencies | | 0.0.31 | 2026-02-24 | [73835](https://github.com/airbytehq/airbyte/pull/73835) | Update dependencies | | 0.0.30 | 2026-02-03 | [72581](https://github.com/airbytehq/airbyte/pull/72581) | Update dependencies | From 09e77ff6c2b3320143956f31f3114bab16c1932d Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:32:46 +0000 Subject: [PATCH 179/379] =?UTF-8?q?deps(source-pennylane):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75817)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-pennylane/metadata.yaml | 4 ++-- docs/integrations/sources/pennylane.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-pennylane/metadata.yaml b/airbyte-integrations/connectors/source-pennylane/metadata.yaml index 283bceea16df..974786be43b7 100644 --- a/airbyte-integrations/connectors/source-pennylane/metadata.yaml +++ b/airbyte-integrations/connectors/source-pennylane/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-pennylane connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: b9e4a306-4e3b-4387-a01d-c00d03d8c28c - dockerImageTag: 0.3.29 + dockerImageTag: 0.3.30 dockerRepository: airbyte/source-pennylane githubIssueLabel: source-pennylane icon: icon.svg diff --git a/docs/integrations/sources/pennylane.md b/docs/integrations/sources/pennylane.md index 4cf648c1bfde..f7de390e498c 100644 --- a/docs/integrations/sources/pennylane.md +++ b/docs/integrations/sources/pennylane.md @@ -28,6 +28,7 @@ | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.3.30 | 2026-03-31 | [75817](https://github.com/airbytehq/airbyte/pull/75817) | Update dependencies | | 0.3.29 | 2026-03-17 | [75030](https://github.com/airbytehq/airbyte/pull/75030) | Update dependencies | | 0.3.28 | 2026-03-10 | [74480](https://github.com/airbytehq/airbyte/pull/74480) | Update dependencies | | 0.3.27 | 2026-02-24 | [73839](https://github.com/airbytehq/airbyte/pull/73839) | Update dependencies | From aafe40ba719e23bf5edae5221e27fd17d7490d9c Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:32:54 +0000 Subject: [PATCH 180/379] =?UTF-8?q?deps(source-pipeliner):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75816)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-pipeliner/metadata.yaml | 4 ++-- docs/integrations/sources/pipeliner.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-pipeliner/metadata.yaml b/airbyte-integrations/connectors/source-pipeliner/metadata.yaml index d92d9685b85d..1019bbaa808c 100644 --- a/airbyte-integrations/connectors/source-pipeliner/metadata.yaml +++ b/airbyte-integrations/connectors/source-pipeliner/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-pipeliner connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 39fd5da7-5713-446b-a9c6-c695f0352f20 - dockerImageTag: 0.0.45 + dockerImageTag: 0.0.46 dockerRepository: airbyte/source-pipeliner githubIssueLabel: source-pipeliner icon: icon.svg diff --git a/docs/integrations/sources/pipeliner.md b/docs/integrations/sources/pipeliner.md index 41698b5166e9..bb9e8e67bdc7 100644 --- a/docs/integrations/sources/pipeliner.md +++ b/docs/integrations/sources/pipeliner.md @@ -48,6 +48,7 @@ Using this connector we fetch data from various streams such as contacts, data, | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.46 | 2026-03-31 | [75816](https://github.com/airbytehq/airbyte/pull/75816) | Update dependencies | | 0.0.45 | 2026-03-24 | [75404](https://github.com/airbytehq/airbyte/pull/75404) | Update dependencies | | 0.0.44 | 2026-03-10 | [74452](https://github.com/airbytehq/airbyte/pull/74452) | Update dependencies | | 0.0.43 | 2026-02-24 | [73854](https://github.com/airbytehq/airbyte/pull/73854) | Update dependencies | From ec2732f534a515c874a19a622e4238a3fc772821 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:33:01 +0000 Subject: [PATCH 181/379] =?UTF-8?q?deps(source-zoho-invoice):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75815)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-zoho-invoice/metadata.yaml | 4 ++-- docs/integrations/sources/zoho-invoice.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-zoho-invoice/metadata.yaml b/airbyte-integrations/connectors/source-zoho-invoice/metadata.yaml index ece71233da57..4d82c54b439f 100644 --- a/airbyte-integrations/connectors/source-zoho-invoice/metadata.yaml +++ b/airbyte-integrations/connectors/source-zoho-invoice/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-zoho-invoice connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 6ee3d92d-b081-4024-9214-2987ae114c17 - dockerImageTag: 0.0.45 + dockerImageTag: 0.0.46 dockerRepository: airbyte/source-zoho-invoice githubIssueLabel: source-zoho-invoice icon: icon.svg diff --git a/docs/integrations/sources/zoho-invoice.md b/docs/integrations/sources/zoho-invoice.md index f320cbc7b652..fda94baeb0e8 100644 --- a/docs/integrations/sources/zoho-invoice.md +++ b/docs/integrations/sources/zoho-invoice.md @@ -33,6 +33,7 @@ Docs : https://www.zoho.com/invoice/api/v3/introduction/#overview | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.46 | 2026-03-31 | [75815](https://github.com/airbytehq/airbyte/pull/75815) | Update dependencies | | 0.0.45 | 2026-03-17 | [74465](https://github.com/airbytehq/airbyte/pull/74465) | Update dependencies | | 0.0.44 | 2026-02-24 | [73993](https://github.com/airbytehq/airbyte/pull/73993) | Update dependencies | | 0.0.43 | 2026-02-17 | [73583](https://github.com/airbytehq/airbyte/pull/73583) | Update dependencies | From a1e6db231a0c6e5b3f5a4ecb379b8927a94cb0ab Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:33:08 +0000 Subject: [PATCH 182/379] =?UTF-8?q?deps(source-zoho-books):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75814)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-zoho-books/metadata.yaml | 4 ++-- docs/integrations/sources/zoho-books.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-zoho-books/metadata.yaml b/airbyte-integrations/connectors/source-zoho-books/metadata.yaml index 0c9e63386ed5..fb250c707405 100644 --- a/airbyte-integrations/connectors/source-zoho-books/metadata.yaml +++ b/airbyte-integrations/connectors/source-zoho-books/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-zoho-books connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: b67f9de8-177d-4d48-9c5c-8a767d845885 - dockerImageTag: 0.0.51 + dockerImageTag: 0.0.52 dockerRepository: airbyte/source-zoho-books githubIssueLabel: source-zoho-books icon: icon.svg diff --git a/docs/integrations/sources/zoho-books.md b/docs/integrations/sources/zoho-books.md index 7b892ef717d4..d948c60dc3a0 100644 --- a/docs/integrations/sources/zoho-books.md +++ b/docs/integrations/sources/zoho-books.md @@ -38,6 +38,7 @@ The Zoho Books connector enables seamless integration of financial data, automa | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.52 | 2026-03-31 | [75814](https://github.com/airbytehq/airbyte/pull/75814) | Update dependencies | | 0.0.51 | 2026-03-17 | [75042](https://github.com/airbytehq/airbyte/pull/75042) | Update dependencies | | 0.0.50 | 2026-03-10 | [74434](https://github.com/airbytehq/airbyte/pull/74434) | Update dependencies | | 0.0.49 | 2026-02-24 | [73979](https://github.com/airbytehq/airbyte/pull/73979) | Update dependencies | From 685ba07b8ab4d7a56283ef2fd446b18f353689ce Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:33:15 +0000 Subject: [PATCH 183/379] =?UTF-8?q?deps(source-dwolla):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75813)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-dwolla/metadata.yaml | 4 ++-- docs/integrations/sources/dwolla.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-dwolla/metadata.yaml b/airbyte-integrations/connectors/source-dwolla/metadata.yaml index 267cdfdad5bf..94a69d432af4 100644 --- a/airbyte-integrations/connectors/source-dwolla/metadata.yaml +++ b/airbyte-integrations/connectors/source-dwolla/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-dwolla connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 775602d3-844c-4b5c-9931-3f0a923c12f2 - dockerImageTag: 0.0.31 + dockerImageTag: 0.0.32 dockerRepository: airbyte/source-dwolla githubIssueLabel: source-dwolla icon: icon.svg diff --git a/docs/integrations/sources/dwolla.md b/docs/integrations/sources/dwolla.md index faac65cb21c0..a2b8ebaf3a21 100644 --- a/docs/integrations/sources/dwolla.md +++ b/docs/integrations/sources/dwolla.md @@ -27,6 +27,7 @@ API Reference: https://developers.dwolla.com/docs | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.32 | 2026-03-31 | [75813](https://github.com/airbytehq/airbyte/pull/75813) | Update dependencies | | 0.0.31 | 2026-03-17 | [74996](https://github.com/airbytehq/airbyte/pull/74996) | Update dependencies | | 0.0.30 | 2026-03-10 | [74191](https://github.com/airbytehq/airbyte/pull/74191) | Update dependencies | | 0.0.29 | 2026-02-17 | [72630](https://github.com/airbytehq/airbyte/pull/72630) | Update dependencies | From ac82d37083d8fb7b0b44eba8a62e7c1828bb05a9 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:33:23 +0000 Subject: [PATCH 184/379] =?UTF-8?q?deps(source-zonka-feedback):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75812)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-zonka-feedback/metadata.yaml | 4 ++-- docs/integrations/sources/zonka-feedback.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-zonka-feedback/metadata.yaml b/airbyte-integrations/connectors/source-zonka-feedback/metadata.yaml index e9fa044d8b56..f4243d1f42a3 100644 --- a/airbyte-integrations/connectors/source-zonka-feedback/metadata.yaml +++ b/airbyte-integrations/connectors/source-zonka-feedback/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-zonka-feedback connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 353443ba-1330-409e-83b5-b0a2dfc88540 - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-zonka-feedback githubIssueLabel: source-zonka-feedback icon: icon.svg diff --git a/docs/integrations/sources/zonka-feedback.md b/docs/integrations/sources/zonka-feedback.md index e6384323ced7..b6c3b39fbfc8 100644 --- a/docs/integrations/sources/zonka-feedback.md +++ b/docs/integrations/sources/zonka-feedback.md @@ -32,6 +32,7 @@ For more information about the API visit https://apidocs.zonkafeedback.com/#intr | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.49 | 2026-03-31 | [75812](https://github.com/airbytehq/airbyte/pull/75812) | Update dependencies | | 0.0.48 | 2026-03-24 | [75053](https://github.com/airbytehq/airbyte/pull/75053) | Update dependencies | | 0.0.47 | 2026-03-10 | [74430](https://github.com/airbytehq/airbyte/pull/74430) | Update dependencies | | 0.0.46 | 2026-02-24 | [73994](https://github.com/airbytehq/airbyte/pull/73994) | Update dependencies | From 5d4c789cd68038c92bb4947b347b08c1773230d4 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:33:31 +0000 Subject: [PATCH 185/379] =?UTF-8?q?deps(source-zoho-campaign):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75811)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-zoho-campaign/metadata.yaml | 4 ++-- docs/integrations/sources/zoho-campaign.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-zoho-campaign/metadata.yaml b/airbyte-integrations/connectors/source-zoho-campaign/metadata.yaml index 091378b78abd..1052cc7ec7f8 100644 --- a/airbyte-integrations/connectors/source-zoho-campaign/metadata.yaml +++ b/airbyte-integrations/connectors/source-zoho-campaign/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-zoho-campaign connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 1d0d5605-604b-401a-8a69-92f841a95a90 - dockerImageTag: 0.0.49 + dockerImageTag: 0.0.50 dockerRepository: airbyte/source-zoho-campaign githubIssueLabel: source-zoho-campaign icon: icon.svg diff --git a/docs/integrations/sources/zoho-campaign.md b/docs/integrations/sources/zoho-campaign.md index f5e0b29b34c8..57a66d93c496 100644 --- a/docs/integrations/sources/zoho-campaign.md +++ b/docs/integrations/sources/zoho-campaign.md @@ -32,6 +32,7 @@ The Zoho Campaigns connector enables seamless integration of mailing lists, camp | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.50 | 2026-03-31 | [75811](https://github.com/airbytehq/airbyte/pull/75811) | Update dependencies | | 0.0.49 | 2026-03-17 | [75048](https://github.com/airbytehq/airbyte/pull/75048) | Update dependencies | | 0.0.48 | 2026-03-10 | [74427](https://github.com/airbytehq/airbyte/pull/74427) | Update dependencies | | 0.0.47 | 2026-02-24 | [73992](https://github.com/airbytehq/airbyte/pull/73992) | Update dependencies | From 3c3723db01857514d8e28e3e77f882b358d66eb3 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:33:40 +0000 Subject: [PATCH 186/379] =?UTF-8?q?deps(source-mantle):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75810)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-mantle/metadata.yaml | 4 ++-- docs/integrations/sources/mantle.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-mantle/metadata.yaml b/airbyte-integrations/connectors/source-mantle/metadata.yaml index 13f8caf847e5..99ec2adcabe4 100644 --- a/airbyte-integrations/connectors/source-mantle/metadata.yaml +++ b/airbyte-integrations/connectors/source-mantle/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-mantle connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: da48299b-4afa-46b4-bb9d-e1ade37e7169 - dockerImageTag: 0.0.18 + dockerImageTag: 0.0.19 dockerRepository: airbyte/source-mantle githubIssueLabel: source-mantle icon: icon.svg diff --git a/docs/integrations/sources/mantle.md b/docs/integrations/sources/mantle.md index edccf14515d4..5eea84c91205 100644 --- a/docs/integrations/sources/mantle.md +++ b/docs/integrations/sources/mantle.md @@ -21,6 +21,7 @@ This connector use the Mantle API to get customers and subscriptions streams | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.19 | 2026-03-31 | [75810](https://github.com/airbytehq/airbyte/pull/75810) | Update dependencies | | 0.0.18 | 2026-03-17 | [73821](https://github.com/airbytehq/airbyte/pull/73821) | Update dependencies | | 0.0.17 | 2026-02-17 | [73394](https://github.com/airbytehq/airbyte/pull/73394) | Update dependencies | | 0.0.16 | 2026-02-10 | [73189](https://github.com/airbytehq/airbyte/pull/73189) | Update dependencies | From f868aca7040c5ade810306e54ad8238b6858bbe8 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:33:51 +0000 Subject: [PATCH 187/379] =?UTF-8?q?deps(source-factorial):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75809)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-factorial/metadata.yaml | 4 ++-- docs/integrations/sources/factorial.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-factorial/metadata.yaml b/airbyte-integrations/connectors/source-factorial/metadata.yaml index 7112e88fdb5b..293da2989354 100644 --- a/airbyte-integrations/connectors/source-factorial/metadata.yaml +++ b/airbyte-integrations/connectors/source-factorial/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-factorial connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 02e8708f-3270-4f13-8b67-257b8ef439f0 - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-factorial githubIssueLabel: source-factorial icon: icon.svg diff --git a/docs/integrations/sources/factorial.md b/docs/integrations/sources/factorial.md index 0261e0205255..e8ba4dfea9e5 100644 --- a/docs/integrations/sources/factorial.md +++ b/docs/integrations/sources/factorial.md @@ -53,6 +53,7 @@ Visit `https://apidoc.factorialhr.com/reference` for API documentation | Version | Date | Pull Request | Subject | | ------------------ | ------------ | --- | ---------------- | +| 0.0.48 | 2026-03-31 | [75809](https://github.com/airbytehq/airbyte/pull/75809) | Update dependencies | | 0.0.47 | 2026-03-24 | [74467](https://github.com/airbytehq/airbyte/pull/74467) | Update dependencies | | 0.0.46 | 2026-03-03 | [74190](https://github.com/airbytehq/airbyte/pull/74190) | Update dependencies | | 0.0.45 | 2026-02-17 | [73483](https://github.com/airbytehq/airbyte/pull/73483) | Update dependencies | From 47a86a57ed215b7a81c8492208a173b7921692cf Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:33:57 +0000 Subject: [PATCH 188/379] =?UTF-8?q?deps(source-zendesk-talk):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75808)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-zendesk-talk/metadata.yaml | 4 ++-- docs/integrations/sources/zendesk-talk.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-zendesk-talk/metadata.yaml b/airbyte-integrations/connectors/source-zendesk-talk/metadata.yaml index 86a70248a1f6..b75a2a390d48 100644 --- a/airbyte-integrations/connectors/source-zendesk-talk/metadata.yaml +++ b/airbyte-integrations/connectors/source-zendesk-talk/metadata.yaml @@ -7,11 +7,11 @@ data: - ${subdomain}.zendesk.com - zendesk.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: c8630570-086d-4a40-99ae-ea5b18673071 - dockerImageTag: 2.0.8 + dockerImageTag: 2.0.9 dockerRepository: airbyte/source-zendesk-talk documentationUrl: https://docs.airbyte.com/integrations/sources/zendesk-talk externalDocumentationUrls: diff --git a/docs/integrations/sources/zendesk-talk.md b/docs/integrations/sources/zendesk-talk.md index 56cf5d97f684..2f438997371d 100644 --- a/docs/integrations/sources/zendesk-talk.md +++ b/docs/integrations/sources/zendesk-talk.md @@ -79,6 +79,7 @@ The Zendesk connector should not run into Zendesk API limitations under normal u | Version | Date | Pull Request | Subject | |:--------|:-----------|:---------------------------------------------------------|:----------------------------------------------------------------------------| +| 2.0.9 | 2026-03-31 | [75808](https://github.com/airbytehq/airbyte/pull/75808) | Update dependencies | | 2.0.8 | 2026-03-11 | [74395](https://github.com/airbytehq/airbyte/pull/74395) | Migrate to scopes object array format | | 2.0.7 | 2026-03-10 | [74446](https://github.com/airbytehq/airbyte/pull/74446) | Update dependencies | | 2.0.6 | 2026-02-24 | [73990](https://github.com/airbytehq/airbyte/pull/73990) | Update dependencies | From 6cca50853cc2b6ca6b6500e08b173fc370827215 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:34:03 +0000 Subject: [PATCH 189/379] =?UTF-8?q?deps(source-metricool):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75807)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-metricool/metadata.yaml | 4 ++-- docs/integrations/sources/metricool.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-metricool/metadata.yaml b/airbyte-integrations/connectors/source-metricool/metadata.yaml index ae8d9bb5c7db..3efe308731e2 100644 --- a/airbyte-integrations/connectors/source-metricool/metadata.yaml +++ b/airbyte-integrations/connectors/source-metricool/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-metricool connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: e4e1ed94-f374-47fe-8dfa-872fb9935fbe - dockerImageTag: 0.0.19 + dockerImageTag: 0.0.20 dockerRepository: airbyte/source-metricool githubIssueLabel: source-metricool icon: icon.svg diff --git a/docs/integrations/sources/metricool.md b/docs/integrations/sources/metricool.md index 7078a438ebe3..7506be7c1d77 100644 --- a/docs/integrations/sources/metricool.md +++ b/docs/integrations/sources/metricool.md @@ -55,6 +55,7 @@ Supported Data Streams: | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.20 | 2026-03-31 | [75807](https://github.com/airbytehq/airbyte/pull/75807) | Update dependencies | | 0.0.19 | 2026-03-17 | [74565](https://github.com/airbytehq/airbyte/pull/74565) | Update dependencies | | 0.0.18 | 2026-02-24 | [73809](https://github.com/airbytehq/airbyte/pull/73809) | Update dependencies | | 0.0.17 | 2026-02-17 | [73392](https://github.com/airbytehq/airbyte/pull/73392) | Update dependencies | From f98b66fdf903f4b5593c53643f6a481480341b9a Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:34:09 +0000 Subject: [PATCH 190/379] =?UTF-8?q?deps(source-ezofficeinventory):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75806)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-ezofficeinventory/metadata.yaml | 4 ++-- docs/integrations/sources/ezofficeinventory.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-ezofficeinventory/metadata.yaml b/airbyte-integrations/connectors/source-ezofficeinventory/metadata.yaml index 2a2c0259cae6..a4231eea8d91 100644 --- a/airbyte-integrations/connectors/source-ezofficeinventory/metadata.yaml +++ b/airbyte-integrations/connectors/source-ezofficeinventory/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-ezofficeinventory connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 7b6be0f6-4139-42f8-a89e-2ca25560979a - dockerImageTag: 0.0.49 + dockerImageTag: 0.0.50 dockerRepository: airbyte/source-ezofficeinventory githubIssueLabel: source-ezofficeinventory icon: icon.svg diff --git a/docs/integrations/sources/ezofficeinventory.md b/docs/integrations/sources/ezofficeinventory.md index 57d4478afe03..ba4db028220c 100644 --- a/docs/integrations/sources/ezofficeinventory.md +++ b/docs/integrations/sources/ezofficeinventory.md @@ -37,6 +37,7 @@ A manifest only source for EZOfficeInventory. https://ezo.io/ezofficeinventory/ | Version | Date | Pull Request | Subject | |---------|------------|----------------------------------------------------------|-------------------------------------------------------------------------------------------| +| 0.0.50 | 2026-03-31 | [75806](https://github.com/airbytehq/airbyte/pull/75806) | Update dependencies | | 0.0.49 | 2026-03-17 | [74999](https://github.com/airbytehq/airbyte/pull/74999) | Update dependencies | | 0.0.48 | 2026-03-10 | [74432](https://github.com/airbytehq/airbyte/pull/74432) | Update dependencies | | 0.0.47 | 2026-02-24 | [73897](https://github.com/airbytehq/airbyte/pull/73897) | Update dependencies | From 0c3f49aa5f9740283abcb757b9dcaace6ce08bf2 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:34:17 +0000 Subject: [PATCH 191/379] =?UTF-8?q?deps(source-zoho-inventory):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75804)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-zoho-inventory/metadata.yaml | 4 ++-- docs/integrations/sources/zoho-inventory.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-zoho-inventory/metadata.yaml b/airbyte-integrations/connectors/source-zoho-inventory/metadata.yaml index 886b037361e8..f5d1cb656576 100644 --- a/airbyte-integrations/connectors/source-zoho-inventory/metadata.yaml +++ b/airbyte-integrations/connectors/source-zoho-inventory/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-zoho-inventory connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 757a3302-b2d5-4fb5-ae7f-b161fd619215 - dockerImageTag: 0.0.50 + dockerImageTag: 0.0.51 dockerRepository: airbyte/source-zoho-inventory githubIssueLabel: source-zoho-inventory icon: icon.svg diff --git a/docs/integrations/sources/zoho-inventory.md b/docs/integrations/sources/zoho-inventory.md index 1520a75c79c7..3422427a0e96 100644 --- a/docs/integrations/sources/zoho-inventory.md +++ b/docs/integrations/sources/zoho-inventory.md @@ -35,6 +35,7 @@ The Zoho Inventory connector enables seamless data synchronization between Zoho | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.51 | 2026-03-31 | [75804](https://github.com/airbytehq/airbyte/pull/75804) | Update dependencies | | 0.0.50 | 2026-03-17 | [75051](https://github.com/airbytehq/airbyte/pull/75051) | Update dependencies | | 0.0.49 | 2026-03-10 | [74443](https://github.com/airbytehq/airbyte/pull/74443) | Update dependencies | | 0.0.48 | 2026-02-24 | [73985](https://github.com/airbytehq/airbyte/pull/73985) | Update dependencies | From 3bf5c7b806456319d2f7c084a0ea927f63819b94 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:34:22 +0000 Subject: [PATCH 192/379] =?UTF-8?q?deps(source-mailchimp):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75803)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-mailchimp/metadata.yaml | 4 ++-- docs/integrations/sources/mailchimp.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-mailchimp/metadata.yaml b/airbyte-integrations/connectors/source-mailchimp/metadata.yaml index c48f0a9168f1..79735a3240a3 100644 --- a/airbyte-integrations/connectors/source-mailchimp/metadata.yaml +++ b/airbyte-integrations/connectors/source-mailchimp/metadata.yaml @@ -7,11 +7,11 @@ data: - "*.api.mailchimp.com" - "login.mailchimp.com" connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: b03a9f3e-22a5-11eb-adc1-0242ac120002 - dockerImageTag: 2.1.20 + dockerImageTag: 2.1.21 dockerRepository: airbyte/source-mailchimp documentationUrl: https://docs.airbyte.com/integrations/sources/mailchimp externalDocumentationUrls: diff --git a/docs/integrations/sources/mailchimp.md b/docs/integrations/sources/mailchimp.md index 787e0f73a2d9..c04ea5350611 100644 --- a/docs/integrations/sources/mailchimp.md +++ b/docs/integrations/sources/mailchimp.md @@ -126,6 +126,7 @@ Now that you have set up the Mailchimp source connector, check out the following | Version | Date | Pull Request | Subject | |--------|------------|----------------------------------------------------------|---------------------------------------------------------------------------| +| 2.1.21 | 2026-03-31 | [75803](https://github.com/airbytehq/airbyte/pull/75803) | Update dependencies | | 2.1.20 | 2026-03-24 | [74579](https://github.com/airbytehq/airbyte/pull/74579) | Update dependencies | | 2.1.19 | 2026-03-03 | [74155](https://github.com/airbytehq/airbyte/pull/74155) | Update dependencies | | 2.1.18 | 2026-02-17 | [73380](https://github.com/airbytehq/airbyte/pull/73380) | Update dependencies | From 3fd6a9f75bcf9fdd4b1af074a091f62fbbba80e4 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:34:31 +0000 Subject: [PATCH 193/379] =?UTF-8?q?deps(source-miro):=20=F0=9F=90=99=20upd?= =?UTF-8?q?ate=20dependencies=20[2026-03-31]=20(#75802)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-miro/metadata.yaml | 4 ++-- docs/integrations/sources/miro.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-miro/metadata.yaml b/airbyte-integrations/connectors/source-miro/metadata.yaml index 3046bd83cb26..9a9791f7ecda 100644 --- a/airbyte-integrations/connectors/source-miro/metadata.yaml +++ b/airbyte-integrations/connectors/source-miro/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-miro connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: f8276ae8-4ada-4ae5-819c-b1836aa78135 - dockerImageTag: 0.0.50 + dockerImageTag: 0.0.51 dockerRepository: airbyte/source-miro githubIssueLabel: source-miro icon: icon.svg diff --git a/docs/integrations/sources/miro.md b/docs/integrations/sources/miro.md index 9b530a569f3d..3a8b04489249 100644 --- a/docs/integrations/sources/miro.md +++ b/docs/integrations/sources/miro.md @@ -25,6 +25,7 @@ Airbyte connector for Miro can be used to extract data related to board content, | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.51 | 2026-03-31 | [75802](https://github.com/airbytehq/airbyte/pull/75802) | Update dependencies | | 0.0.50 | 2026-03-24 | [75389](https://github.com/airbytehq/airbyte/pull/75389) | Update dependencies | | 0.0.49 | 2026-03-10 | [74593](https://github.com/airbytehq/airbyte/pull/74593) | Update dependencies | | 0.0.48 | 2026-03-03 | [74189](https://github.com/airbytehq/airbyte/pull/74189) | Update dependencies | From 963ea2c922825c138c175beca7efed3e2120997f Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:34:38 +0000 Subject: [PATCH 194/379] =?UTF-8?q?deps(source-luma):=20=F0=9F=90=99=20upd?= =?UTF-8?q?ate=20dependencies=20[2026-03-31]=20(#75801)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-luma/metadata.yaml | 4 ++-- docs/integrations/sources/luma.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-luma/metadata.yaml b/airbyte-integrations/connectors/source-luma/metadata.yaml index 9fea2b22e87a..28cb9ea6fce5 100644 --- a/airbyte-integrations/connectors/source-luma/metadata.yaml +++ b/airbyte-integrations/connectors/source-luma/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-luma connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 8ac29756-9a9d-4472-a20b-df29ac29764a - dockerImageTag: 0.0.54 + dockerImageTag: 0.0.55 dockerRepository: airbyte/source-luma githubIssueLabel: source-luma icon: icon.svg diff --git a/docs/integrations/sources/luma.md b/docs/integrations/sources/luma.md index a75c4179ddf1..0839d643dba0 100644 --- a/docs/integrations/sources/luma.md +++ b/docs/integrations/sources/luma.md @@ -20,6 +20,7 @@ | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.55 | 2026-03-31 | [75801](https://github.com/airbytehq/airbyte/pull/75801) | Update dependencies | | 0.0.54 | 2026-03-24 | [75398](https://github.com/airbytehq/airbyte/pull/75398) | Update dependencies | | 0.0.53 | 2026-03-10 | [74561](https://github.com/airbytehq/airbyte/pull/74561) | Update dependencies | | 0.0.52 | 2026-02-24 | [73824](https://github.com/airbytehq/airbyte/pull/73824) | Update dependencies | From dba6d83ebf424c9895beb8193e1a2f825c0efe74 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:34:43 +0000 Subject: [PATCH 195/379] =?UTF-8?q?deps(source-mailtrap):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75800)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-mailtrap/metadata.yaml | 4 ++-- docs/integrations/sources/mailtrap.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-mailtrap/metadata.yaml b/airbyte-integrations/connectors/source-mailtrap/metadata.yaml index 3a968441bfe1..09b5b23dea5b 100644 --- a/airbyte-integrations/connectors/source-mailtrap/metadata.yaml +++ b/airbyte-integrations/connectors/source-mailtrap/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-mailtrap connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 9ba00df2-313c-46f2-b102-a5063a1ee18a - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-mailtrap githubIssueLabel: source-mailtrap icon: icon.svg diff --git a/docs/integrations/sources/mailtrap.md b/docs/integrations/sources/mailtrap.md index d0c38ba4f450..a7a59db54c32 100644 --- a/docs/integrations/sources/mailtrap.md +++ b/docs/integrations/sources/mailtrap.md @@ -28,6 +28,7 @@ Email Delivery Platform for individuals and businesses to test, send and control | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.49 | 2026-03-31 | [75800](https://github.com/airbytehq/airbyte/pull/75800) | Update dependencies | | 0.0.48 | 2026-03-24 | [75010](https://github.com/airbytehq/airbyte/pull/75010) | Update dependencies | | 0.0.47 | 2026-03-10 | [74544](https://github.com/airbytehq/airbyte/pull/74544) | Update dependencies | | 0.0.46 | 2026-02-24 | [73417](https://github.com/airbytehq/airbyte/pull/73417) | Update dependencies | From b19399041835a06c595586db1854ae810a2b6ae2 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:34:51 +0000 Subject: [PATCH 196/379] =?UTF-8?q?deps(source-zoho-bigin):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75799)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-zoho-bigin/metadata.yaml | 4 ++-- docs/integrations/sources/zoho-bigin.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-zoho-bigin/metadata.yaml b/airbyte-integrations/connectors/source-zoho-bigin/metadata.yaml index 4a6f40539a2c..04e743b9844c 100644 --- a/airbyte-integrations/connectors/source-zoho-bigin/metadata.yaml +++ b/airbyte-integrations/connectors/source-zoho-bigin/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-zoho-bigin connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 30e47b8d-5132-4b24-a204-2493bda33c8d - dockerImageTag: 0.0.50 + dockerImageTag: 0.0.51 dockerRepository: airbyte/source-zoho-bigin githubIssueLabel: source-zoho-bigin icon: icon.svg diff --git a/docs/integrations/sources/zoho-bigin.md b/docs/integrations/sources/zoho-bigin.md index b9cdaeee8589..22c0dfe39815 100644 --- a/docs/integrations/sources/zoho-bigin.md +++ b/docs/integrations/sources/zoho-bigin.md @@ -32,6 +32,7 @@ | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.51 | 2026-03-31 | [75799](https://github.com/airbytehq/airbyte/pull/75799) | Update dependencies | | 0.0.50 | 2026-03-24 | [75369](https://github.com/airbytehq/airbyte/pull/75369) | Update dependencies | | 0.0.49 | 2026-03-10 | [74424](https://github.com/airbytehq/airbyte/pull/74424) | Update dependencies | | 0.0.48 | 2026-02-24 | [73982](https://github.com/airbytehq/airbyte/pull/73982) | Update dependencies | From 94ffa3ebbee1c06519a8902290be13f15c6811ed Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:34:56 +0000 Subject: [PATCH 197/379] =?UTF-8?q?deps(source-sendinblue):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75798)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-sendinblue/metadata.yaml | 4 ++-- docs/integrations/sources/sendinblue.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-sendinblue/metadata.yaml b/airbyte-integrations/connectors/source-sendinblue/metadata.yaml index 761a9856fd9b..67c17899b4a3 100644 --- a/airbyte-integrations/connectors/source-sendinblue/metadata.yaml +++ b/airbyte-integrations/connectors/source-sendinblue/metadata.yaml @@ -9,11 +9,11 @@ data: # Please update to the latest version of the connector base image. # https://hub.docker.com/r/airbyte/python-connector-base # Please use the full address with sha256 hash to guarantee build reproducibility. - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 2e88fa20-a2f6-43cc-bba6-98a0a3f244fb - dockerImageTag: 0.2.25 + dockerImageTag: 0.2.26 dockerRepository: airbyte/source-sendinblue documentationUrl: https://docs.airbyte.com/integrations/sources/sendinblue githubIssueLabel: source-sendinblue diff --git a/docs/integrations/sources/sendinblue.md b/docs/integrations/sources/sendinblue.md index 7216ed5c4a00..1efb1c346a11 100644 --- a/docs/integrations/sources/sendinblue.md +++ b/docs/integrations/sources/sendinblue.md @@ -34,6 +34,7 @@ Sendinblue APIs are under rate limits for the number of API calls allowed per AP | Version | Date | Pull Request | Subject | | :------ | :--------- | :-------------------------------------------------------- | :------------------------------------------------------------ | +| 0.2.26 | 2026-03-31 | [75798](https://github.com/airbytehq/airbyte/pull/75798) | Update dependencies | | 0.2.25 | 2026-03-24 | [75120](https://github.com/airbytehq/airbyte/pull/75120) | Update dependencies | | 0.2.24 | 2026-02-24 | [73936](https://github.com/airbytehq/airbyte/pull/73936) | Update dependencies | | 0.2.23 | 2026-02-17 | [73463](https://github.com/airbytehq/airbyte/pull/73463) | Update dependencies | From 53ef5a494ad423fae508f4b0f346eb3b10551eaa Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:35:03 +0000 Subject: [PATCH 198/379] =?UTF-8?q?deps(source-sentry):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75797)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-sentry/metadata.yaml | 4 ++-- docs/integrations/sources/sentry.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-sentry/metadata.yaml b/airbyte-integrations/connectors/source-sentry/metadata.yaml index eb24cc0eb536..3c899b0e477f 100644 --- a/airbyte-integrations/connectors/source-sentry/metadata.yaml +++ b/airbyte-integrations/connectors/source-sentry/metadata.yaml @@ -6,11 +6,11 @@ data: hosts: - "*" connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: cdaf146a-9b75-49fd-9dd2-9d64a0bb4781 - dockerImageTag: 0.9.18 + dockerImageTag: 0.9.19 dockerRepository: airbyte/source-sentry documentationUrl: https://docs.airbyte.com/integrations/sources/sentry externalDocumentationUrls: diff --git a/docs/integrations/sources/sentry.md b/docs/integrations/sources/sentry.md index be42ac887bca..bcd43cde927a 100644 --- a/docs/integrations/sources/sentry.md +++ b/docs/integrations/sources/sentry.md @@ -65,6 +65,7 @@ Please be aware: this also means that any change older than 90 days will not be | Version | Date | Pull Request | Subject | |:--------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0.9.19 | 2026-03-31 | [75797](https://github.com/airbytehq/airbyte/pull/75797) | Update dependencies | | 0.9.18 | 2026-03-24 | [75330](https://github.com/airbytehq/airbyte/pull/75330) | Update dependencies | | 0.9.17 | 2026-03-10 | [74601](https://github.com/airbytehq/airbyte/pull/74601) | Update dependencies | | 0.9.16 | 2026-03-03 | [73562](https://github.com/airbytehq/airbyte/pull/73562) | Update dependencies | From ece206451ee064a7fac95fd08c8b61f8779f78cf Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:35:14 +0000 Subject: [PATCH 199/379] =?UTF-8?q?deps(source-shutterstock):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75792)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-shutterstock/metadata.yaml | 4 ++-- docs/integrations/sources/shutterstock.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-shutterstock/metadata.yaml b/airbyte-integrations/connectors/source-shutterstock/metadata.yaml index 037cffe6167c..56d6f9deabde 100644 --- a/airbyte-integrations/connectors/source-shutterstock/metadata.yaml +++ b/airbyte-integrations/connectors/source-shutterstock/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-shutterstock connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 998c12c8-09f9-4f57-9411-4efc498b7858 - dockerImageTag: 0.0.32 + dockerImageTag: 0.0.33 dockerRepository: airbyte/source-shutterstock githubIssueLabel: source-shutterstock icon: icon.svg diff --git a/docs/integrations/sources/shutterstock.md b/docs/integrations/sources/shutterstock.md index f58a6b2aa693..7ce40c0ca49d 100644 --- a/docs/integrations/sources/shutterstock.md +++ b/docs/integrations/sources/shutterstock.md @@ -34,6 +34,7 @@ API Reference: https://api-reference.shutterstock.com/#overview | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.33 | 2026-03-31 | [75792](https://github.com/airbytehq/airbyte/pull/75792) | Update dependencies | | 0.0.32 | 2026-03-17 | [75110](https://github.com/airbytehq/airbyte/pull/75110) | Update dependencies | | 0.0.31 | 2026-03-03 | [73969](https://github.com/airbytehq/airbyte/pull/73969) | Update dependencies | | 0.0.30 | 2026-02-17 | [73535](https://github.com/airbytehq/airbyte/pull/73535) | Update dependencies | From 95bab0c0e93350ad300071bfdb183da323482a68 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:35:19 +0000 Subject: [PATCH 200/379] =?UTF-8?q?deps(source-segment):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75791)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-segment/metadata.yaml | 4 ++-- docs/integrations/sources/segment.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-segment/metadata.yaml b/airbyte-integrations/connectors/source-segment/metadata.yaml index 44bf7c42bb74..9353ab1df7a9 100644 --- a/airbyte-integrations/connectors/source-segment/metadata.yaml +++ b/airbyte-integrations/connectors/source-segment/metadata.yaml @@ -14,11 +14,11 @@ data: enabled: false packageName: airbyte-source-segment connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: b17132d0-4108-4a76-ae5e-639c15beae47 - dockerImageTag: 0.0.46 + dockerImageTag: 0.0.47 dockerRepository: airbyte/source-segment githubIssueLabel: source-segment icon: icon.svg diff --git a/docs/integrations/sources/segment.md b/docs/integrations/sources/segment.md index e39f353716d5..8256532265c9 100644 --- a/docs/integrations/sources/segment.md +++ b/docs/integrations/sources/segment.md @@ -34,6 +34,7 @@ Connector that pulls from Segment's Public API. | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.47 | 2026-03-31 | [75791](https://github.com/airbytehq/airbyte/pull/75791) | Update dependencies | | 0.0.46 | 2026-03-17 | [74599](https://github.com/airbytehq/airbyte/pull/74599) | Update dependencies | | 0.0.45 | 2026-02-24 | [73759](https://github.com/airbytehq/airbyte/pull/73759) | Update dependencies | | 0.0.44 | 2026-02-17 | [73464](https://github.com/airbytehq/airbyte/pull/73464) | Update dependencies | From 0e014c6856d025093bb52f68d55c34ff68259190 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:35:24 +0000 Subject: [PATCH 201/379] =?UTF-8?q?deps(source-missive):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75790)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-missive/metadata.yaml | 4 ++-- docs/integrations/sources/missive.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-missive/metadata.yaml b/airbyte-integrations/connectors/source-missive/metadata.yaml index 15b58f218f62..4ed2832016e0 100644 --- a/airbyte-integrations/connectors/source-missive/metadata.yaml +++ b/airbyte-integrations/connectors/source-missive/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-missive connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 740eadea-6f7a-49dc-a2e6-bdf935a79996 - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-missive githubIssueLabel: source-missive icon: icon.svg diff --git a/docs/integrations/sources/missive.md b/docs/integrations/sources/missive.md index 785d0323bd4e..07dfbec56536 100644 --- a/docs/integrations/sources/missive.md +++ b/docs/integrations/sources/missive.md @@ -35,6 +35,7 @@ Visit `https://missiveapp.com/help/api-documentation/rest-endpoints` for API doc | Version | Date | Pull Request | Subject | | ------------------ | ------------ | --- | ---------------- | +| 0.0.49 | 2026-03-31 | [75790](https://github.com/airbytehq/airbyte/pull/75790) | Update dependencies | | 0.0.48 | 2026-03-24 | [75365](https://github.com/airbytehq/airbyte/pull/75365) | Update dependencies | | 0.0.47 | 2026-03-10 | [74590](https://github.com/airbytehq/airbyte/pull/74590) | Update dependencies | | 0.0.46 | 2026-02-24 | [73865](https://github.com/airbytehq/airbyte/pull/73865) | Update dependencies | From b8f78db83d48f14d4f34c384c05146877d4c0382 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:35:29 +0000 Subject: [PATCH 202/379] =?UTF-8?q?deps(source-smartengage):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75789)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-smartengage/metadata.yaml | 4 ++-- docs/integrations/sources/smartengage.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-smartengage/metadata.yaml b/airbyte-integrations/connectors/source-smartengage/metadata.yaml index 9863f45fbb60..f81b33a092b8 100644 --- a/airbyte-integrations/connectors/source-smartengage/metadata.yaml +++ b/airbyte-integrations/connectors/source-smartengage/metadata.yaml @@ -3,11 +3,11 @@ data: ql: 100 sl: 100 connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 21cc4a17-a011-4485-8a3e-e2341a91ab9f - dockerImageTag: 0.2.34 + dockerImageTag: 0.2.35 dockerRepository: airbyte/source-smartengage documentationUrl: https://docs.airbyte.com/integrations/sources/smartengage githubIssueLabel: source-smartengage diff --git a/docs/integrations/sources/smartengage.md b/docs/integrations/sources/smartengage.md index 0af4babf3aed..40b10009b110 100644 --- a/docs/integrations/sources/smartengage.md +++ b/docs/integrations/sources/smartengage.md @@ -31,6 +31,7 @@ This source can sync data from the [SmartEngage API](https://smartengage.com/doc | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------ | +| 0.2.35 | 2026-03-31 | [75789](https://github.com/airbytehq/airbyte/pull/75789) | Update dependencies | | 0.2.34 | 2026-03-17 | [75117](https://github.com/airbytehq/airbyte/pull/75117) | Update dependencies | | 0.2.33 | 2026-03-03 | [67440](https://github.com/airbytehq/airbyte/pull/67440) | Update dependencies | | 0.2.32 | 2025-09-30 | [66915](https://github.com/airbytehq/airbyte/pull/66915) | Update dependencies | From cb63f9b9c042ceabb22dce493f64029147af181f Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:35:36 +0000 Subject: [PATCH 203/379] =?UTF-8?q?deps(source-signnow):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75787)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-signnow/metadata.yaml | 4 ++-- docs/integrations/sources/signnow.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-signnow/metadata.yaml b/airbyte-integrations/connectors/source-signnow/metadata.yaml index a3b944d54760..0f89456d7770 100644 --- a/airbyte-integrations/connectors/source-signnow/metadata.yaml +++ b/airbyte-integrations/connectors/source-signnow/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-signnow connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 379fc8e8-c6ec-4c13-90cb-dfebb536fac6 - dockerImageTag: 0.0.34 + dockerImageTag: 0.0.35 dockerRepository: airbyte/source-signnow githubIssueLabel: source-signnow icon: icon.svg diff --git a/docs/integrations/sources/signnow.md b/docs/integrations/sources/signnow.md index 8db8100b08e6..974edd6fc169 100644 --- a/docs/integrations/sources/signnow.md +++ b/docs/integrations/sources/signnow.md @@ -34,6 +34,7 @@ API Reference: https://docs.signnow.com/docs/signnow/welcome | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.35 | 2026-03-31 | [75787](https://github.com/airbytehq/airbyte/pull/75787) | Update dependencies | | 0.0.34 | 2026-03-24 | [75119](https://github.com/airbytehq/airbyte/pull/75119) | Update dependencies | | 0.0.33 | 2026-02-24 | [73938](https://github.com/airbytehq/airbyte/pull/73938) | Update dependencies | | 0.0.32 | 2026-02-17 | [73561](https://github.com/airbytehq/airbyte/pull/73561) | Update dependencies | From e08b344bdc5f0d1173bd1f1025f0c708d41d633e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:35:42 +0000 Subject: [PATCH 204/379] =?UTF-8?q?deps(source-cimis):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75786)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-cimis/metadata.yaml | 4 ++-- docs/integrations/sources/cimis.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-cimis/metadata.yaml b/airbyte-integrations/connectors/source-cimis/metadata.yaml index 1dada2ba9757..3d61853c5e6f 100644 --- a/airbyte-integrations/connectors/source-cimis/metadata.yaml +++ b/airbyte-integrations/connectors/source-cimis/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-cimis connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: d169ef9b-6741-4af6-b4c8-7ec4410d7f0e - dockerImageTag: 0.0.51 + dockerImageTag: 0.0.52 dockerRepository: airbyte/source-cimis githubIssueLabel: source-cimis icon: icon.svg diff --git a/docs/integrations/sources/cimis.md b/docs/integrations/sources/cimis.md index 10430f0a55a5..7e82102525ae 100644 --- a/docs/integrations/sources/cimis.md +++ b/docs/integrations/sources/cimis.md @@ -33,6 +33,7 @@ To get started, register and request your appKey from the [CIMIS website](https: | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.52 | 2026-03-31 | [75786](https://github.com/airbytehq/airbyte/pull/75786) | Update dependencies | | 0.0.51 | 2026-03-24 | [74457](https://github.com/airbytehq/airbyte/pull/74457) | Update dependencies | | 0.0.50 | 2026-02-24 | [73825](https://github.com/airbytehq/airbyte/pull/73825) | Update dependencies | | 0.0.49 | 2026-02-17 | [73475](https://github.com/airbytehq/airbyte/pull/73475) | Update dependencies | From 16eef3c417ded1566ef1f0ffcc55d0599db9a4c6 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:35:51 +0000 Subject: [PATCH 205/379] =?UTF-8?q?deps(source-nexiopay):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75785)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-nexiopay/metadata.yaml | 4 ++-- docs/integrations/sources/nexiopay.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-nexiopay/metadata.yaml b/airbyte-integrations/connectors/source-nexiopay/metadata.yaml index 485d52db343d..6a0d76edafb4 100644 --- a/airbyte-integrations/connectors/source-nexiopay/metadata.yaml +++ b/airbyte-integrations/connectors/source-nexiopay/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-nexiopay connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.10.4@sha256:2f551a3fb5d580b34f4253aa1904d26c309364b09538f0b0fef3d8a98546f795 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 699d7359-204a-4650-81d2-ca03d607cacc - dockerImageTag: 0.0.33 + dockerImageTag: 0.0.34 dockerRepository: airbyte/source-nexiopay githubIssueLabel: source-nexiopay icon: icon.svg diff --git a/docs/integrations/sources/nexiopay.md b/docs/integrations/sources/nexiopay.md index fb9c99a66aa3..737a68d38850 100644 --- a/docs/integrations/sources/nexiopay.md +++ b/docs/integrations/sources/nexiopay.md @@ -28,6 +28,7 @@ API Reference: https://docs.nexiopay.com/reference/api-reference | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.34 | 2026-03-31 | [75785](https://github.com/airbytehq/airbyte/pull/75785) | Update dependencies | | 0.0.33 | 2026-03-10 | [74619](https://github.com/airbytehq/airbyte/pull/74619) | Update dependencies | | 0.0.32 | 2026-02-24 | [73873](https://github.com/airbytehq/airbyte/pull/73873) | Update dependencies | | 0.0.31 | 2026-02-17 | [73550](https://github.com/airbytehq/airbyte/pull/73550) | Update dependencies | From 806e6497569eafe64ac98b18238bf3eaa26c213e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:36:01 +0000 Subject: [PATCH 206/379] =?UTF-8?q?deps(source-simfin):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75784)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-simfin/metadata.yaml | 4 ++-- docs/integrations/sources/simfin.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-simfin/metadata.yaml b/airbyte-integrations/connectors/source-simfin/metadata.yaml index 0d4a7258167a..5ba8932d1204 100644 --- a/airbyte-integrations/connectors/source-simfin/metadata.yaml +++ b/airbyte-integrations/connectors/source-simfin/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-simfin connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: f00b4899-1154-477e-8508-3d7f33ffb28c - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-simfin githubIssueLabel: source-simfin icon: icon.svg diff --git a/docs/integrations/sources/simfin.md b/docs/integrations/sources/simfin.md index 38065a88eb04..a6114a11ad5d 100644 --- a/docs/integrations/sources/simfin.md +++ b/docs/integrations/sources/simfin.md @@ -28,6 +28,7 @@ Docs https://simfin.readme.io/reference/getting-started-1 | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.48 | 2026-03-31 | [75784](https://github.com/airbytehq/airbyte/pull/75784) | Update dependencies | | 0.0.47 | 2026-03-17 | [75113](https://github.com/airbytehq/airbyte/pull/75113) | Update dependencies | | 0.0.46 | 2026-03-03 | [73977](https://github.com/airbytehq/airbyte/pull/73977) | Update dependencies | | 0.0.45 | 2026-02-17 | [73553](https://github.com/airbytehq/airbyte/pull/73553) | Update dependencies | From b291d5dfe65eea741b30b7186c70993b590c70be Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:36:11 +0000 Subject: [PATCH 207/379] =?UTF-8?q?deps(source-chameleon):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75782)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-chameleon/metadata.yaml | 4 ++-- docs/integrations/sources/chameleon.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-chameleon/metadata.yaml b/airbyte-integrations/connectors/source-chameleon/metadata.yaml index 693508dbb676..133f228ec6b3 100644 --- a/airbyte-integrations/connectors/source-chameleon/metadata.yaml +++ b/airbyte-integrations/connectors/source-chameleon/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-chameleon connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 64a0240a-81a4-4e40-8002-e063b17cfbbe - dockerImageTag: 0.1.45 + dockerImageTag: 0.1.46 dockerRepository: airbyte/source-chameleon githubIssueLabel: source-chameleon icon: icon.svg diff --git a/docs/integrations/sources/chameleon.md b/docs/integrations/sources/chameleon.md index 8d675fb12fb9..91dfc41d864e 100644 --- a/docs/integrations/sources/chameleon.md +++ b/docs/integrations/sources/chameleon.md @@ -40,6 +40,7 @@ Refer `https://app.chameleon.io/settings/tokens` for getting your API key. | Version | Date | Pull Request | Subject | |------------------|------------|--------------|----------------| +| 0.1.46 | 2026-03-31 | [75782](https://github.com/airbytehq/airbyte/pull/75782) | Update dependencies | | 0.1.45 | 2026-03-17 | [75104](https://github.com/airbytehq/airbyte/pull/75104) | Update dependencies | | 0.1.44 | 2026-02-24 | [73794](https://github.com/airbytehq/airbyte/pull/73794) | Update dependencies | | 0.1.43 | 2026-02-17 | [73469](https://github.com/airbytehq/airbyte/pull/73469) | Update dependencies | From dd45a5ac082637759720490850c32649817a81d8 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:36:19 +0000 Subject: [PATCH 208/379] =?UTF-8?q?deps(source-ebay-finance):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75781)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-ebay-finance/metadata.yaml | 4 ++-- docs/integrations/sources/ebay-finance.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-ebay-finance/metadata.yaml b/airbyte-integrations/connectors/source-ebay-finance/metadata.yaml index 944c4179223d..1db3565f4b5c 100644 --- a/airbyte-integrations/connectors/source-ebay-finance/metadata.yaml +++ b/airbyte-integrations/connectors/source-ebay-finance/metadata.yaml @@ -14,11 +14,11 @@ data: enabled: false packageName: airbyte-source-ebay-finance connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 177c8ac0-5b2e-497d-9526-c787fb333fc9 - dockerImageTag: 0.0.32 + dockerImageTag: 0.0.33 dockerRepository: airbyte/source-ebay-finance githubIssueLabel: source-ebay-finance icon: icon.svg diff --git a/docs/integrations/sources/ebay-finance.md b/docs/integrations/sources/ebay-finance.md index 66154dd89f5d..3ae1a19f5b3b 100644 --- a/docs/integrations/sources/ebay-finance.md +++ b/docs/integrations/sources/ebay-finance.md @@ -28,6 +28,7 @@ Documentation: https://developer.ebay.com/api-docs/sell/finances/overview.html | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.33 | 2026-03-31 | [75781](https://github.com/airbytehq/airbyte/pull/75781) | Update dependencies | | 0.0.32 | 2026-03-17 | [75006](https://github.com/airbytehq/airbyte/pull/75006) | Update dependencies | | 0.0.31 | 2026-03-10 | [74445](https://github.com/airbytehq/airbyte/pull/74445) | Update dependencies | | 0.0.30 | 2026-02-24 | [73910](https://github.com/airbytehq/airbyte/pull/73910) | Update dependencies | From 68fed03f9885172d212973df7137c4a054aa396a Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:36:25 +0000 Subject: [PATCH 209/379] =?UTF-8?q?deps(source-tavus):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75780)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-tavus/metadata.yaml | 4 ++-- docs/integrations/sources/tavus.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-tavus/metadata.yaml b/airbyte-integrations/connectors/source-tavus/metadata.yaml index 121521e0fef4..b6d237acc67d 100644 --- a/airbyte-integrations/connectors/source-tavus/metadata.yaml +++ b/airbyte-integrations/connectors/source-tavus/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-tavus connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: f2889d35-753f-4106-bce5-8a865bc339a6 - dockerImageTag: 0.0.30 + dockerImageTag: 0.0.31 dockerRepository: airbyte/source-tavus githubIssueLabel: source-tavus icon: icon.svg diff --git a/docs/integrations/sources/tavus.md b/docs/integrations/sources/tavus.md index 8e4dfb252efb..1b5ae2f44106 100644 --- a/docs/integrations/sources/tavus.md +++ b/docs/integrations/sources/tavus.md @@ -25,6 +25,7 @@ API Reference: https://docs.tavus.io/api-reference/phoenix-replica-model/get-rep | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.31 | 2026-03-31 | [75780](https://github.com/airbytehq/airbyte/pull/75780) | Update dependencies | | 0.0.30 | 2026-03-17 | [75041](https://github.com/airbytehq/airbyte/pull/75041) | Update dependencies | | 0.0.29 | 2026-03-10 | [74581](https://github.com/airbytehq/airbyte/pull/74581) | Update dependencies | | 0.0.28 | 2026-02-24 | [73834](https://github.com/airbytehq/airbyte/pull/73834) | Update dependencies | From fafcc70e5fe973402e14936bc2ec263fbdd0aab7 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:36:31 +0000 Subject: [PATCH 210/379] =?UTF-8?q?deps(source-drift):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75779)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-drift/metadata.yaml | 4 ++-- docs/integrations/sources/drift.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-drift/metadata.yaml b/airbyte-integrations/connectors/source-drift/metadata.yaml index b1c54ef546dc..0b85c0a83038 100644 --- a/airbyte-integrations/connectors/source-drift/metadata.yaml +++ b/airbyte-integrations/connectors/source-drift/metadata.yaml @@ -6,11 +6,11 @@ data: hosts: - https://driftapi.com/ connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 445831eb-78db-4b1f-8f1f-0d96ad8739e2 - dockerImageTag: 0.4.46 + dockerImageTag: 0.4.47 dockerRepository: airbyte/source-drift documentationUrl: https://docs.airbyte.com/integrations/sources/drift githubIssueLabel: source-drift diff --git a/docs/integrations/sources/drift.md b/docs/integrations/sources/drift.md index f4972b56afb9..e48aab814448 100644 --- a/docs/integrations/sources/drift.md +++ b/docs/integrations/sources/drift.md @@ -56,6 +56,7 @@ The Drift connector should not run into Drift API limitations under normal usage | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------ | +| 0.4.47 | 2026-03-31 | [75779](https://github.com/airbytehq/airbyte/pull/75779) | Update dependencies | | 0.4.46 | 2026-03-24 | [75036](https://github.com/airbytehq/airbyte/pull/75036) | Update dependencies | | 0.4.45 | 2026-03-03 | [74193](https://github.com/airbytehq/airbyte/pull/74193) | Update dependencies | | 0.4.44 | 2026-02-03 | [72603](https://github.com/airbytehq/airbyte/pull/72603) | Update dependencies | From 2489d6ccaabd8d1eeb8888fbe7d29925862339a6 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:36:38 +0000 Subject: [PATCH 211/379] =?UTF-8?q?deps(source-eventbrite):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75778)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-eventbrite/metadata.yaml | 4 ++-- docs/integrations/sources/eventbrite.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-eventbrite/metadata.yaml b/airbyte-integrations/connectors/source-eventbrite/metadata.yaml index a66091c0f002..0dc387464d4e 100644 --- a/airbyte-integrations/connectors/source-eventbrite/metadata.yaml +++ b/airbyte-integrations/connectors/source-eventbrite/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-eventbrite connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 6748b22d-3d27-4907-b8c0-04f6c8ef71b8 - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-eventbrite githubIssueLabel: source-eventbrite icon: icon.svg diff --git a/docs/integrations/sources/eventbrite.md b/docs/integrations/sources/eventbrite.md index cdfd11eb0444..5dab09d68cd1 100644 --- a/docs/integrations/sources/eventbrite.md +++ b/docs/integrations/sources/eventbrite.md @@ -37,6 +37,7 @@ To get a Private Token: | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.49 | 2026-03-31 | [75778](https://github.com/airbytehq/airbyte/pull/75778) | Update dependencies | | 0.0.48 | 2026-03-24 | [74468](https://github.com/airbytehq/airbyte/pull/74468) | Update dependencies | | 0.0.47 | 2026-02-24 | [73906](https://github.com/airbytehq/airbyte/pull/73906) | Update dependencies | | 0.0.46 | 2026-02-17 | [73456](https://github.com/airbytehq/airbyte/pull/73456) | Update dependencies | From 4177403abb9dc26b2c2fab85faadee81fa63540c Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:36:48 +0000 Subject: [PATCH 212/379] =?UTF-8?q?deps(source-employment-hero):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75776)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-employment-hero/metadata.yaml | 4 ++-- docs/integrations/sources/employment-hero.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-employment-hero/metadata.yaml b/airbyte-integrations/connectors/source-employment-hero/metadata.yaml index 2b564ff64792..5764649c37ac 100644 --- a/airbyte-integrations/connectors/source-employment-hero/metadata.yaml +++ b/airbyte-integrations/connectors/source-employment-hero/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-employment-hero connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: e2db518e-ef68-40bb-a2b6-b9f9aabbadb3 - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-employment-hero githubIssueLabel: source-employment-hero icon: icon.svg diff --git a/docs/integrations/sources/employment-hero.md b/docs/integrations/sources/employment-hero.md index a51ea7a866fd..1dbafb6b2d46 100644 --- a/docs/integrations/sources/employment-hero.md +++ b/docs/integrations/sources/employment-hero.md @@ -58,6 +58,7 @@ Hit Get new Access token and approve via browser, Postman will collect a new `ac | Version | Date | Pull Request | Subject | | ------------------ | ------------ | --- | ---------------- | +| 0.0.48 | 2026-03-31 | [75776](https://github.com/airbytehq/airbyte/pull/75776) | Update dependencies | | 0.0.47 | 2026-03-24 | [75338](https://github.com/airbytehq/airbyte/pull/75338) | Update dependencies | | 0.0.46 | 2026-03-10 | [74440](https://github.com/airbytehq/airbyte/pull/74440) | Update dependencies | | 0.0.45 | 2026-02-24 | [73901](https://github.com/airbytehq/airbyte/pull/73901) | Update dependencies | From c7d7732b4024a13fc464e9c2e3852a316b21bece Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:36:54 +0000 Subject: [PATCH 213/379] =?UTF-8?q?deps(source-eventee):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75775)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-eventee/metadata.yaml | 4 ++-- docs/integrations/sources/eventee.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-eventee/metadata.yaml b/airbyte-integrations/connectors/source-eventee/metadata.yaml index e3b724c0dd1c..15957c906a15 100644 --- a/airbyte-integrations/connectors/source-eventee/metadata.yaml +++ b/airbyte-integrations/connectors/source-eventee/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-eventee connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 8be64312-22e6-4c6d-8738-2294bd565139 - dockerImageTag: 0.0.50 + dockerImageTag: 0.0.51 dockerRepository: airbyte/source-eventee githubIssueLabel: source-eventee icon: icon.svg diff --git a/docs/integrations/sources/eventee.md b/docs/integrations/sources/eventee.md index ebdb724bc729..1741250bab21 100644 --- a/docs/integrations/sources/eventee.md +++ b/docs/integrations/sources/eventee.md @@ -27,6 +27,7 @@ The Airbyte connector for Eventee enables seamless integration and automated dat | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.51 | 2026-03-31 | [75775](https://github.com/airbytehq/airbyte/pull/75775) | Update dependencies | | 0.0.50 | 2026-03-17 | [75004](https://github.com/airbytehq/airbyte/pull/75004) | Update dependencies | | 0.0.49 | 2026-03-10 | [74436](https://github.com/airbytehq/airbyte/pull/74436) | Update dependencies | | 0.0.48 | 2026-03-03 | [73923](https://github.com/airbytehq/airbyte/pull/73923) | Update dependencies | From e2bd29cfcdd13bf1144e45d98e1b83d8fcba3b71 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:37:01 +0000 Subject: [PATCH 214/379] =?UTF-8?q?deps(source-e-conomic):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75774)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-e-conomic/metadata.yaml | 4 ++-- docs/integrations/sources/e-conomic.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-e-conomic/metadata.yaml b/airbyte-integrations/connectors/source-e-conomic/metadata.yaml index 1508ae054116..7043be3458ef 100644 --- a/airbyte-integrations/connectors/source-e-conomic/metadata.yaml +++ b/airbyte-integrations/connectors/source-e-conomic/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-e-conomic connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 2724ccae-2503-4348-9f1c-b5645b54a985 - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-e-conomic githubIssueLabel: source-e-conomic icon: icon.svg diff --git a/docs/integrations/sources/e-conomic.md b/docs/integrations/sources/e-conomic.md index 63a400c91757..de263db7c240 100644 --- a/docs/integrations/sources/e-conomic.md +++ b/docs/integrations/sources/e-conomic.md @@ -52,6 +52,7 @@ The Airbyte connector for e-conomic enables seamless integration with the e-cono | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.49 | 2026-03-31 | [75774](https://github.com/airbytehq/airbyte/pull/75774) | Update dependencies | | 0.0.48 | 2026-03-24 | [75037](https://github.com/airbytehq/airbyte/pull/75037) | Update dependencies | | 0.0.47 | 2026-03-10 | [74429](https://github.com/airbytehq/airbyte/pull/74429) | Update dependencies | | 0.0.46 | 2026-03-03 | [73488](https://github.com/airbytehq/airbyte/pull/73488) | Update dependencies | From 9503134c40343a3878647f790149adf6e10ec50f Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:37:08 +0000 Subject: [PATCH 215/379] =?UTF-8?q?deps(source-dropbox-sign):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75773)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-dropbox-sign/metadata.yaml | 4 ++-- docs/integrations/sources/dropbox-sign.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-dropbox-sign/metadata.yaml b/airbyte-integrations/connectors/source-dropbox-sign/metadata.yaml index 7ab77e11d219..e23c44998c06 100644 --- a/airbyte-integrations/connectors/source-dropbox-sign/metadata.yaml +++ b/airbyte-integrations/connectors/source-dropbox-sign/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-dropbox-sign connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: da9cccd2-7319-44ea-b6cf-ddc08f13e959 - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-dropbox-sign githubIssueLabel: source-dropbox-sign icon: icon.svg diff --git a/docs/integrations/sources/dropbox-sign.md b/docs/integrations/sources/dropbox-sign.md index 084c5e946348..b37fffe111c5 100644 --- a/docs/integrations/sources/dropbox-sign.md +++ b/docs/integrations/sources/dropbox-sign.md @@ -23,6 +23,7 @@ See the [API docs](https://developers.hellosign.com/api/reference/authentication | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.48 | 2026-03-31 | [75773](https://github.com/airbytehq/airbyte/pull/75773) | Update dependencies | | 0.0.47 | 2026-03-17 | [74472](https://github.com/airbytehq/airbyte/pull/74472) | Update dependencies | | 0.0.46 | 2026-02-24 | [73920](https://github.com/airbytehq/airbyte/pull/73920) | Update dependencies | | 0.0.45 | 2026-02-03 | [72618](https://github.com/airbytehq/airbyte/pull/72618) | Update dependencies | From 01e96b7af90ccf9a649596edff29d03bbb5ebd49 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:39:30 +0000 Subject: [PATCH 216/379] =?UTF-8?q?deps(source-easypromos):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75772)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-easypromos/metadata.yaml | 4 ++-- docs/integrations/sources/easypromos.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-easypromos/metadata.yaml b/airbyte-integrations/connectors/source-easypromos/metadata.yaml index c9d2e37c7053..aa9fe536571e 100644 --- a/airbyte-integrations/connectors/source-easypromos/metadata.yaml +++ b/airbyte-integrations/connectors/source-easypromos/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-easypromos connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 8b418a25-7042-430f-96d8-72853a337a26 - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-easypromos githubIssueLabel: source-easypromos icon: icon.svg diff --git a/docs/integrations/sources/easypromos.md b/docs/integrations/sources/easypromos.md index 81007c157766..9b8e26fdc934 100644 --- a/docs/integrations/sources/easypromos.md +++ b/docs/integrations/sources/easypromos.md @@ -25,6 +25,7 @@ Airbyte connector for [Easypromos](https://www.easypromosapp.com/) enables seaml | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.49 | 2026-03-31 | [75772](https://github.com/airbytehq/airbyte/pull/75772) | Update dependencies | | 0.0.48 | 2026-03-24 | [74471](https://github.com/airbytehq/airbyte/pull/74471) | Update dependencies | | 0.0.47 | 2026-02-24 | [73908](https://github.com/airbytehq/airbyte/pull/73908) | Update dependencies | | 0.0.46 | 2026-02-17 | [73453](https://github.com/airbytehq/airbyte/pull/73453) | Update dependencies | From a7e90bb0b0f1acd61dc4212604f95b6d49ab31cf Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:39:35 +0000 Subject: [PATCH 217/379] =?UTF-8?q?deps(source-testrail):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75771)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> From e78b79995e6a085e39b56df8cf7bfd06e9922e8a Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:39:40 +0000 Subject: [PATCH 218/379] =?UTF-8?q?deps(source-tremendous):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75770)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> From 00cd562fcc94b6482d04c341b9526fb1adb8a008 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:39:46 +0000 Subject: [PATCH 219/379] =?UTF-8?q?deps(source-chift):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75769)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-chift/metadata.yaml | 4 ++-- docs/integrations/sources/chift.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-chift/metadata.yaml b/airbyte-integrations/connectors/source-chift/metadata.yaml index acbe2b342e17..d3ffc6545e75 100644 --- a/airbyte-integrations/connectors/source-chift/metadata.yaml +++ b/airbyte-integrations/connectors/source-chift/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-chift connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: d03aa64c-21a9-4edc-97b9-5590600ee3d6 - dockerImageTag: 0.0.10 + dockerImageTag: 0.0.11 dockerRepository: airbyte/source-chift githubIssueLabel: source-chift icon: icon.svg diff --git a/docs/integrations/sources/chift.md b/docs/integrations/sources/chift.md index 326fd014e9ce..e1f1558734d9 100644 --- a/docs/integrations/sources/chift.md +++ b/docs/integrations/sources/chift.md @@ -23,6 +23,7 @@ Chift is a tool that allows for the integration of financial data into SaaS prod | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.11 | 2026-03-31 | [75769](https://github.com/airbytehq/airbyte/pull/75769) | Update dependencies | | 0.0.10 | 2026-03-17 | [75077](https://github.com/airbytehq/airbyte/pull/75077) | Update dependencies | | 0.0.9 | 2026-03-10 | [74454](https://github.com/airbytehq/airbyte/pull/74454) | Update dependencies | | 0.0.8 | 2026-02-24 | [73822](https://github.com/airbytehq/airbyte/pull/73822) | Update dependencies | From 1bc9dac9e5b98bd276f98617574aa3fdc11d142d Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:39:52 +0000 Subject: [PATCH 220/379] =?UTF-8?q?deps(source-ninjaone-rmm):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75768)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> From ed00eabe9c5e1b921e48323759130255eb7e043c Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:40:00 +0000 Subject: [PATCH 221/379] =?UTF-8?q?deps(source-clockodo):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75767)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> From e4edd275d4a335c6eda20e11dde3f618b8de0f30 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:42:24 +0000 Subject: [PATCH 222/379] =?UTF-8?q?deps(source-tempo):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75766)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> From e9c4abbee2e72e1e7c658b4d5e7b81a29c4cdcff Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:42:29 +0000 Subject: [PATCH 223/379] =?UTF-8?q?deps(source-nylas):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75765)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> From 79478722f1a239d378f800574a049a6676cf14d4 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:42:35 +0000 Subject: [PATCH 224/379] =?UTF-8?q?deps(source-taboola):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75764)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> From 4f6b2d88f56826961313ce38e0fe0df42be2a0dc Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:42:42 +0000 Subject: [PATCH 225/379] =?UTF-8?q?deps(source-finage):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75763)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-finage/metadata.yaml | 4 ++-- docs/integrations/sources/finage.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-finage/metadata.yaml b/airbyte-integrations/connectors/source-finage/metadata.yaml index f40a3ee4c8bf..e162569d3e4a 100644 --- a/airbyte-integrations/connectors/source-finage/metadata.yaml +++ b/airbyte-integrations/connectors/source-finage/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-finage connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 5220663f-d87b-498e-8aed-1f2d59371a61 - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-finage githubIssueLabel: source-finage icon: icon.svg diff --git a/docs/integrations/sources/finage.md b/docs/integrations/sources/finage.md index ea6d64acc782..5a3279ddf77a 100644 --- a/docs/integrations/sources/finage.md +++ b/docs/integrations/sources/finage.md @@ -44,6 +44,7 @@ This connector can be used to extract data from various APIs such as symbol-list | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.49 | 2026-03-31 | [75763](https://github.com/airbytehq/airbyte/pull/75763) | Update dependencies | | 0.0.48 | 2026-03-17 | [74638](https://github.com/airbytehq/airbyte/pull/74638) | Update dependencies | | 0.0.47 | 2026-02-24 | [73748](https://github.com/airbytehq/airbyte/pull/73748) | Update dependencies | | 0.0.46 | 2026-02-17 | [73373](https://github.com/airbytehq/airbyte/pull/73373) | Update dependencies | From 06c84cd4170e04d1cba3d527366dfee28c725b1e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:42:50 +0000 Subject: [PATCH 226/379] =?UTF-8?q?deps(source-fastly):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75760)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-fastly/metadata.yaml | 4 ++-- docs/integrations/sources/fastly.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-fastly/metadata.yaml b/airbyte-integrations/connectors/source-fastly/metadata.yaml index 92035296244c..b61725c31b5d 100644 --- a/airbyte-integrations/connectors/source-fastly/metadata.yaml +++ b/airbyte-integrations/connectors/source-fastly/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-fastly connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: d14ff3ed-5049-4dfb-bc28-1d7ccaf67182 - dockerImageTag: 0.0.30 + dockerImageTag: 0.0.31 dockerRepository: airbyte/source-fastly githubIssueLabel: source-fastly icon: icon.svg diff --git a/docs/integrations/sources/fastly.md b/docs/integrations/sources/fastly.md index a51cb8de856a..18976a6dc6a0 100644 --- a/docs/integrations/sources/fastly.md +++ b/docs/integrations/sources/fastly.md @@ -28,6 +28,7 @@ API Reference: https://www.fastly.com/documentation/reference/api/ | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.31 | 2026-03-31 | [75760](https://github.com/airbytehq/airbyte/pull/75760) | Update dependencies | | 0.0.30 | 2026-03-17 | [74914](https://github.com/airbytehq/airbyte/pull/74914) | Update dependencies | | 0.0.29 | 2026-02-24 | [73778](https://github.com/airbytehq/airbyte/pull/73778) | Update dependencies | | 0.0.28 | 2026-02-17 | [73403](https://github.com/airbytehq/airbyte/pull/73403) | Update dependencies | From fb39b32352afa3006fe48bbc2c1eb486caa04779 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:42:55 +0000 Subject: [PATCH 227/379] =?UTF-8?q?deps(source-clazar):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75759)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-clazar/metadata.yaml | 4 ++-- docs/integrations/sources/clazar.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-clazar/metadata.yaml b/airbyte-integrations/connectors/source-clazar/metadata.yaml index dc82c15dda38..5dce4febdcaf 100644 --- a/airbyte-integrations/connectors/source-clazar/metadata.yaml +++ b/airbyte-integrations/connectors/source-clazar/metadata.yaml @@ -12,11 +12,11 @@ data: enabled: false packageName: airbyte-source-clazar connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: d7df7b64-6266-45b5-ad83-e1515578f371 - dockerImageTag: 0.4.51 + dockerImageTag: 0.4.52 dockerRepository: airbyte/source-clazar githubIssueLabel: source-clazar icon: clazar.svg diff --git a/docs/integrations/sources/clazar.md b/docs/integrations/sources/clazar.md index d0fc6bb1e8fa..c6258d6f4d97 100644 --- a/docs/integrations/sources/clazar.md +++ b/docs/integrations/sources/clazar.md @@ -112,6 +112,7 @@ Please [create an issue](https://github.com/airbytehq/airbyte/issues) if you see | Version | Date | Pull Request | Subject | |:--------|:-----------|:---------------------------------------------------------|:--------------------------------------------------------------------------| +| 0.4.52 | 2026-03-31 | [75759](https://github.com/airbytehq/airbyte/pull/75759) | Update dependencies | | 0.4.51 | 2026-03-17 | [75079](https://github.com/airbytehq/airbyte/pull/75079) | Update dependencies | | 0.4.50 | 2026-03-10 | [74422](https://github.com/airbytehq/airbyte/pull/74422) | Update dependencies | | 0.4.49 | 2026-02-24 | [73795](https://github.com/airbytehq/airbyte/pull/73795) | Update dependencies | From 2898fc395ee554ada994fdbaccf775ebf061cfcf Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:43:01 +0000 Subject: [PATCH 228/379] =?UTF-8?q?deps(source-mode):=20=F0=9F=90=99=20upd?= =?UTF-8?q?ate=20dependencies=20[2026-03-31]=20(#75755)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-mode/metadata.yaml | 4 ++-- docs/integrations/sources/mode.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-mode/metadata.yaml b/airbyte-integrations/connectors/source-mode/metadata.yaml index fcbe78edb66e..745179c9aca6 100644 --- a/airbyte-integrations/connectors/source-mode/metadata.yaml +++ b/airbyte-integrations/connectors/source-mode/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-mode connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 948f3a37-f80b-4f57-a918-9fd733f7a018 - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-mode githubIssueLabel: source-mode icon: icon.svg diff --git a/docs/integrations/sources/mode.md b/docs/integrations/sources/mode.md index 519a0033dcdb..ab6668a92cce 100644 --- a/docs/integrations/sources/mode.md +++ b/docs/integrations/sources/mode.md @@ -39,6 +39,7 @@ This Airbyte connector for Mode allows you to seamlessly sync data between Mode | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.49 | 2026-03-31 | [75755](https://github.com/airbytehq/airbyte/pull/75755) | Update dependencies | | 0.0.48 | 2026-03-17 | [75065](https://github.com/airbytehq/airbyte/pull/75065) | Update dependencies | | 0.0.47 | 2026-03-03 | [74181](https://github.com/airbytehq/airbyte/pull/74181) | Update dependencies | | 0.0.46 | 2026-02-17 | [73556](https://github.com/airbytehq/airbyte/pull/73556) | Update dependencies | From 4c1934334a0be9327c3c54f755b98927a249daa9 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:43:09 +0000 Subject: [PATCH 229/379] =?UTF-8?q?deps(source-coassemble):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75754)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-coassemble/metadata.yaml | 4 ++-- docs/integrations/sources/coassemble.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-coassemble/metadata.yaml b/airbyte-integrations/connectors/source-coassemble/metadata.yaml index 56b63e55f81a..9c3a4a870b58 100644 --- a/airbyte-integrations/connectors/source-coassemble/metadata.yaml +++ b/airbyte-integrations/connectors/source-coassemble/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-coassemble connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 85999b05-fae0-4312-a3ae-f4987f50d434 - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-coassemble githubIssueLabel: source-coassemble icon: icon.svg diff --git a/docs/integrations/sources/coassemble.md b/docs/integrations/sources/coassemble.md index e0a7bd3a1b1f..54d718d8dd31 100644 --- a/docs/integrations/sources/coassemble.md +++ b/docs/integrations/sources/coassemble.md @@ -26,6 +26,7 @@ See the [Coassemble API docs](https://developers.coassemble.com/get-started) for | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.48 | 2026-03-31 | [75754](https://github.com/airbytehq/airbyte/pull/75754) | Update dependencies | | 0.0.47 | 2026-03-17 | [75106](https://github.com/airbytehq/airbyte/pull/75106) | Update dependencies | | 0.0.46 | 2026-03-03 | [73827](https://github.com/airbytehq/airbyte/pull/73827) | Update dependencies | | 0.0.45 | 2026-02-17 | [73446](https://github.com/airbytehq/airbyte/pull/73446) | Update dependencies | From fd5ed7d728606ccffe072f30100ec925a4634326 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:43:15 +0000 Subject: [PATCH 230/379] =?UTF-8?q?deps(source-clarif-ai):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75753)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-clarif-ai/metadata.yaml | 4 ++-- docs/integrations/sources/clarif-ai.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-clarif-ai/metadata.yaml b/airbyte-integrations/connectors/source-clarif-ai/metadata.yaml index fba0665df93d..df17e4d9e8e2 100644 --- a/airbyte-integrations/connectors/source-clarif-ai/metadata.yaml +++ b/airbyte-integrations/connectors/source-clarif-ai/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-clarif-ai connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 7fbeaeea-2d0d-4f13-8200-fa228494d91c - dockerImageTag: 0.0.52 + dockerImageTag: 0.0.53 dockerRepository: airbyte/source-clarif-ai githubIssueLabel: source-clarif-ai icon: icon.svg diff --git a/docs/integrations/sources/clarif-ai.md b/docs/integrations/sources/clarif-ai.md index 6535462436ec..80635d7c39a6 100644 --- a/docs/integrations/sources/clarif-ai.md +++ b/docs/integrations/sources/clarif-ai.md @@ -31,6 +31,7 @@ API Documentation: https://docs.clarifai.com/api-guide/api-overview/helpful-api- | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.53 | 2026-03-31 | [75753](https://github.com/airbytehq/airbyte/pull/75753) | Update dependencies | | 0.0.52 | 2026-03-17 | [75073](https://github.com/airbytehq/airbyte/pull/75073) | Update dependencies | | 0.0.51 | 2026-03-10 | [74437](https://github.com/airbytehq/airbyte/pull/74437) | Update dependencies | | 0.0.50 | 2026-03-03 | [74227](https://github.com/airbytehq/airbyte/pull/74227) | Update dependencies | From ff59d06da8a844964b522b0505c36276489c3862 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:43:23 +0000 Subject: [PATCH 231/379] =?UTF-8?q?deps(source-clickup-api):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75750)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-clickup-api/metadata.yaml | 4 ++-- docs/integrations/sources/clickup-api.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-clickup-api/metadata.yaml b/airbyte-integrations/connectors/source-clickup-api/metadata.yaml index b36572e0322f..cb00f8ac5e27 100644 --- a/airbyte-integrations/connectors/source-clickup-api/metadata.yaml +++ b/airbyte-integrations/connectors/source-clickup-api/metadata.yaml @@ -5,7 +5,7 @@ data: connectorSubtype: api connectorType: source definitionId: 311a7a27-3fb5-4f7e-8265-5e4afe258b66 - dockerImageTag: 0.3.44 + dockerImageTag: 0.3.45 dockerRepository: airbyte/source-clickup-api githubIssueLabel: source-clickup-api icon: clickup.svg @@ -43,7 +43,7 @@ data: type: GSM alias: airbyte-connector-testing-secret-store connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e externalDocumentationUrls: - title: ClickUp API reference url: https://clickup.com/api/ diff --git a/docs/integrations/sources/clickup-api.md b/docs/integrations/sources/clickup-api.md index 00e745917e96..4eb8aab56c02 100644 --- a/docs/integrations/sources/clickup-api.md +++ b/docs/integrations/sources/clickup-api.md @@ -57,6 +57,7 @@ Here are some optional fields: | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :-------------------------------- | +| 0.3.45 | 2026-03-31 | [75750](https://github.com/airbytehq/airbyte/pull/75750) | Update dependencies | | 0.3.44 | 2026-03-17 | [75076](https://github.com/airbytehq/airbyte/pull/75076) | Update dependencies | | 0.3.43 | 2026-03-03 | [74217](https://github.com/airbytehq/airbyte/pull/74217) | Update dependencies | | 0.3.42 | 2026-02-17 | [72740](https://github.com/airbytehq/airbyte/pull/72740) | Update dependencies | From 1455f73dabe8713406c660b244ea5ae7b3ff968e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:43:30 +0000 Subject: [PATCH 232/379] =?UTF-8?q?deps(source-nocrm):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75749)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-nocrm/metadata.yaml | 4 ++-- docs/integrations/sources/nocrm.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-nocrm/metadata.yaml b/airbyte-integrations/connectors/source-nocrm/metadata.yaml index 33a1715b6c59..3c77bae2b8d6 100644 --- a/airbyte-integrations/connectors/source-nocrm/metadata.yaml +++ b/airbyte-integrations/connectors/source-nocrm/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-nocrm connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: b58ba2a9-6335-496d-8c55-4e9d483f49a1 - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-nocrm githubIssueLabel: source-nocrm icon: icon.svg diff --git a/docs/integrations/sources/nocrm.md b/docs/integrations/sources/nocrm.md index 06bf08d352dd..39a7ab8375df 100644 --- a/docs/integrations/sources/nocrm.md +++ b/docs/integrations/sources/nocrm.md @@ -33,6 +33,7 @@ | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.48 | 2026-03-31 | [75749](https://github.com/airbytehq/airbyte/pull/75749) | Update dependencies | | 0.0.47 | 2026-03-17 | [74623](https://github.com/airbytehq/airbyte/pull/74623) | Update dependencies | | 0.0.46 | 2026-03-03 | [73578](https://github.com/airbytehq/airbyte/pull/73578) | Update dependencies | | 0.0.45 | 2026-02-10 | [73059](https://github.com/airbytehq/airbyte/pull/73059) | Update dependencies | From 96a7bae507b2a81e6b2f0e13424cf7436f6f5330 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:43:35 +0000 Subject: [PATCH 233/379] =?UTF-8?q?deps(source-notion):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75747)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-notion/metadata.yaml | 4 ++-- docs/integrations/sources/notion.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-notion/metadata.yaml b/airbyte-integrations/connectors/source-notion/metadata.yaml index 0f7123b3310c..2efa76f11a2d 100644 --- a/airbyte-integrations/connectors/source-notion/metadata.yaml +++ b/airbyte-integrations/connectors/source-notion/metadata.yaml @@ -6,11 +6,11 @@ data: hosts: - api.notion.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.10.4@sha256:2f551a3fb5d580b34f4253aa1904d26c309364b09538f0b0fef3d8a98546f795 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 6e00b415-b02e-4160-bf02-58176a0ae687 - dockerImageTag: 4.0.3 + dockerImageTag: 4.0.4 dockerRepository: airbyte/source-notion documentationUrl: https://docs.airbyte.com/integrations/sources/notion externalDocumentationUrls: diff --git a/docs/integrations/sources/notion.md b/docs/integrations/sources/notion.md index 6ee7a53e14b9..7127f84b408a 100644 --- a/docs/integrations/sources/notion.md +++ b/docs/integrations/sources/notion.md @@ -122,6 +122,7 @@ The Blocks stream recursively fetches child blocks up to 30 levels deep. Pages w | Version | Date | Pull Request | Subject | |:------------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 4.0.4 | 2026-03-31 | [75747](https://github.com/airbytehq/airbyte/pull/75747) | Update dependencies | | 4.0.3 | 2026-03-30 | [75603](https://github.com/airbytehq/airbyte/pull/75603) | Fix 429 status code mapping from RETRY to RATE_LIMITED for improved rate limit handling and observability | | 4.0.2 | 2026-03-23 | [75290](https://github.com/airbytehq/airbyte/pull/75290) | Update v4.0.0 upgrade deadline to 2026-04-10 | | 4.0.1 | 2026-03-10 | [74616](https://github.com/airbytehq/airbyte/pull/74616) | Update dependencies | From 4c9165843926bf5f49008d91b6c7b269d5c6acc8 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:43:41 +0000 Subject: [PATCH 234/379] =?UTF-8?q?deps(source-thinkific-courses):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75746)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-thinkific-courses/metadata.yaml | 4 ++-- docs/integrations/sources/thinkific-courses.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-thinkific-courses/metadata.yaml b/airbyte-integrations/connectors/source-thinkific-courses/metadata.yaml index 3d93faf5279d..c11d37f9a7b6 100644 --- a/airbyte-integrations/connectors/source-thinkific-courses/metadata.yaml +++ b/airbyte-integrations/connectors/source-thinkific-courses/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-thinkific-courses connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: f3ef5282-1829-4e1d-a12e-2a637c393884 - dockerImageTag: 0.0.36 + dockerImageTag: 0.0.37 dockerRepository: airbyte/source-thinkific-courses githubIssueLabel: source-thinkific-courses icon: icon.svg diff --git a/docs/integrations/sources/thinkific-courses.md b/docs/integrations/sources/thinkific-courses.md index dc7020757706..f1090a477fed 100644 --- a/docs/integrations/sources/thinkific-courses.md +++ b/docs/integrations/sources/thinkific-courses.md @@ -24,6 +24,7 @@ This connector retrives basic data information from courses. | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.37 | 2026-03-31 | [75746](https://github.com/airbytehq/airbyte/pull/75746) | Update dependencies | | 0.0.36 | 2026-03-24 | [74546](https://github.com/airbytehq/airbyte/pull/74546) | Update dependencies | | 0.0.35 | 2026-02-24 | [73851](https://github.com/airbytehq/airbyte/pull/73851) | Update dependencies | | 0.0.34 | 2026-02-17 | [73515](https://github.com/airbytehq/airbyte/pull/73515) | Update dependencies | From 7669c71e94b6664300a9062677244bf9c92e8589 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:44:04 +0000 Subject: [PATCH 235/379] =?UTF-8?q?deps(source-newsdata-io):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75359)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-newsdata-io/metadata.yaml | 4 ++-- docs/integrations/sources/newsdata-io.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-newsdata-io/metadata.yaml b/airbyte-integrations/connectors/source-newsdata-io/metadata.yaml index efb19893605c..e0b24484e3aa 100644 --- a/airbyte-integrations/connectors/source-newsdata-io/metadata.yaml +++ b/airbyte-integrations/connectors/source-newsdata-io/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-newsdata-io connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.10.4@sha256:2f551a3fb5d580b34f4253aa1904d26c309364b09538f0b0fef3d8a98546f795 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 67f03df4-2c61-4d8c-80cd-0931287f87d8 - dockerImageTag: 0.0.46 + dockerImageTag: 0.0.47 dockerRepository: airbyte/source-newsdata-io githubIssueLabel: source-newsdata-io icon: icon.svg diff --git a/docs/integrations/sources/newsdata-io.md b/docs/integrations/sources/newsdata-io.md index 622d1e3cd2bb..a8722e401802 100644 --- a/docs/integrations/sources/newsdata-io.md +++ b/docs/integrations/sources/newsdata-io.md @@ -31,6 +31,7 @@ Historical News is only available for premium users of NewsData service. | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.47 | 2026-03-31 | [75359](https://github.com/airbytehq/airbyte/pull/75359) | Update dependencies | | 0.0.46 | 2026-03-10 | [74591](https://github.com/airbytehq/airbyte/pull/74591) | Update dependencies | | 0.0.45 | 2026-03-03 | [72594](https://github.com/airbytehq/airbyte/pull/72594) | Update dependencies | | 0.0.44 | 2026-01-20 | [71655](https://github.com/airbytehq/airbyte/pull/71655) | Update dependencies | From 33a45206cefa148fac7f24d74366cbd87af1112d Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:44:17 +0000 Subject: [PATCH 236/379] =?UTF-8?q?deps(source-tiktok-marketing):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75063)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-tiktok-marketing/metadata.yaml | 4 ++-- docs/integrations/sources/tiktok-marketing.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-tiktok-marketing/metadata.yaml b/airbyte-integrations/connectors/source-tiktok-marketing/metadata.yaml index c22ec68a5969..f7068f013f49 100644 --- a/airbyte-integrations/connectors/source-tiktok-marketing/metadata.yaml +++ b/airbyte-integrations/connectors/source-tiktok-marketing/metadata.yaml @@ -7,11 +7,11 @@ data: - sandbox-ads.tiktok.com - business-api.tiktok.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.10.1@sha256:bd69f6b52bdd92ce06c30786d67546427b828ffb553363c8950b2816c552d6e0 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 4bfac00d-ce15-44ff-95b9-9e3c3e8fbd35 - dockerImageTag: 5.0.4 + dockerImageTag: 5.0.5 dockerRepository: airbyte/source-tiktok-marketing documentationUrl: https://docs.airbyte.com/integrations/sources/tiktok-marketing externalDocumentationUrls: diff --git a/docs/integrations/sources/tiktok-marketing.md b/docs/integrations/sources/tiktok-marketing.md index 5efe04b5bd59..8e24ce130868 100644 --- a/docs/integrations/sources/tiktok-marketing.md +++ b/docs/integrations/sources/tiktok-marketing.md @@ -155,6 +155,7 @@ For information on breaking changes and migration steps, see the [TikTok Marketi | Version | Date | Pull Request | Subject | |:-----------|:-----------|:----------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 5.0.5 | 2026-03-31 | [75063](https://github.com/airbytehq/airbyte/pull/75063) | Update dependencies | | 5.0.4 | 2026-03-23 | [74376](https://github.com/airbytehq/airbyte/pull/74376) | Handle TikTok API error 60001 (service maintenance) as retryable instead of fatal; ignore error 40002 (resource not accessible or does not exist) | | 5.0.3 | 2026-03-12 | [74762](https://github.com/airbytehq/airbyte/pull/74762) | Promoting release candidate 5.0.3-rc.1 to a main version. | | 5.0.3-rc.1 | 2026-03-05 | [74085](https://github.com/airbytehq/airbyte/pull/74085) | Add missing video engagement metrics to audience report streams | From e98b83a802205d5a09c2a6e68e05a5e1b3b75457 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:27:28 +0000 Subject: [PATCH 237/379] =?UTF-8?q?deps(source-assemblyai):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75896)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-assemblyai/metadata.yaml | 4 ++-- docs/integrations/sources/assemblyai.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-assemblyai/metadata.yaml b/airbyte-integrations/connectors/source-assemblyai/metadata.yaml index 57b68f2ba77e..dbceae2aacf6 100644 --- a/airbyte-integrations/connectors/source-assemblyai/metadata.yaml +++ b/airbyte-integrations/connectors/source-assemblyai/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-assemblyai connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: dcb2f998-6493-4078-8390-e320487157a0 - dockerImageTag: 0.0.25 + dockerImageTag: 0.0.26 dockerRepository: airbyte/source-assemblyai githubIssueLabel: source-assemblyai icon: icon.svg diff --git a/docs/integrations/sources/assemblyai.md b/docs/integrations/sources/assemblyai.md index 814787b8dadb..112269d3d12a 100644 --- a/docs/integrations/sources/assemblyai.md +++ b/docs/integrations/sources/assemblyai.md @@ -25,6 +25,7 @@ API Reference: https://www.assemblyai.com/docs/api-reference/overview | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.26 | 2026-03-31 | [75896](https://github.com/airbytehq/airbyte/pull/75896) | Update dependencies | | 0.0.25 | 2026-03-17 | [75011](https://github.com/airbytehq/airbyte/pull/75011) | Update dependencies | | 0.0.24 | 2026-03-03 | [74172](https://github.com/airbytehq/airbyte/pull/74172) | Update dependencies | | 0.0.23 | 2026-02-17 | [73422](https://github.com/airbytehq/airbyte/pull/73422) | Update dependencies | From 1acb31173be1ddedf433d194f859124cda1fbe4f Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:27:32 +0000 Subject: [PATCH 238/379] =?UTF-8?q?deps(source-apify-dataset):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75895)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-apify-dataset/metadata.yaml | 4 ++-- docs/integrations/sources/apify-dataset.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-apify-dataset/metadata.yaml b/airbyte-integrations/connectors/source-apify-dataset/metadata.yaml index 3163cce7dd9e..9961bc5c277d 100644 --- a/airbyte-integrations/connectors/source-apify-dataset/metadata.yaml +++ b/airbyte-integrations/connectors/source-apify-dataset/metadata.yaml @@ -3,11 +3,11 @@ data: hosts: - api.apify.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 47f17145-fe20-4ef5-a548-e29b048adf84 - dockerImageTag: 2.2.42 + dockerImageTag: 2.2.43 dockerRepository: airbyte/source-apify-dataset documentationUrl: https://docs.airbyte.com/integrations/sources/apify-dataset githubIssueLabel: source-apify-dataset diff --git a/docs/integrations/sources/apify-dataset.md b/docs/integrations/sources/apify-dataset.md index 16409c9c35b7..549535bc3a7e 100644 --- a/docs/integrations/sources/apify-dataset.md +++ b/docs/integrations/sources/apify-dataset.md @@ -72,6 +72,7 @@ The Apify dataset connector uses [Apify Python Client](https://docs.apify.com/ap | Version | Date | Pull Request | Subject | | :------ | :--------- | :----------------------------------------------------------- | :------------------------------------------------------------------------------ | +| 2.2.43 | 2026-03-31 | [75895](https://github.com/airbytehq/airbyte/pull/75895) | Update dependencies | | 2.2.42 | 2026-03-17 | [75003](https://github.com/airbytehq/airbyte/pull/75003) | Update dependencies | | 2.2.41 | 2026-03-10 | [74482](https://github.com/airbytehq/airbyte/pull/74482) | Update dependencies | | 2.2.40 | 2026-02-24 | [73807](https://github.com/airbytehq/airbyte/pull/73807) | Update dependencies | From 2d4daa33e09ce4cc9d8ea9d4a5a68a39ae721c61 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:27:37 +0000 Subject: [PATCH 239/379] =?UTF-8?q?deps(source-appfigures):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75894)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-appfigures/metadata.yaml | 4 ++-- docs/integrations/sources/appfigures.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-appfigures/metadata.yaml b/airbyte-integrations/connectors/source-appfigures/metadata.yaml index 2031da45d350..6b1e8c0f0b6d 100644 --- a/airbyte-integrations/connectors/source-appfigures/metadata.yaml +++ b/airbyte-integrations/connectors/source-appfigures/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-appfigures connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: e2fcf0a0-3f99-4938-ba34-3a6dd51fd4a4 - dockerImageTag: 0.0.40 + dockerImageTag: 0.0.41 dockerRepository: airbyte/source-appfigures githubIssueLabel: source-appfigures icon: icon.svg diff --git a/docs/integrations/sources/appfigures.md b/docs/integrations/sources/appfigures.md index 68c4f3d5e1d3..2ae0e8484cc8 100644 --- a/docs/integrations/sources/appfigures.md +++ b/docs/integrations/sources/appfigures.md @@ -39,6 +39,7 @@ Refer `https://docs.appfigures.com/api/reference/v2/authentication` for more det | Version | Date | Pull Request | Subject | |---------| ----------- | -- | ---------------- | +| 0.0.41 | 2026-03-31 | [75894](https://github.com/airbytehq/airbyte/pull/75894) | Update dependencies | | 0.0.40 | 2026-03-17 | [75007](https://github.com/airbytehq/airbyte/pull/75007) | Update dependencies | | 0.0.39 | 2026-03-10 | [74499](https://github.com/airbytehq/airbyte/pull/74499) | Update dependencies | | 0.0.38 | 2026-02-24 | [73798](https://github.com/airbytehq/airbyte/pull/73798) | Update dependencies | From 9aca7522c879fd3e0b67882a7f3262fcb87ec6e8 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:27:41 +0000 Subject: [PATCH 240/379] =?UTF-8?q?deps(source-bitly):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75893)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-bitly/metadata.yaml | 4 ++-- docs/integrations/sources/bitly.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-bitly/metadata.yaml b/airbyte-integrations/connectors/source-bitly/metadata.yaml index b420719bfc80..fc210bf33e14 100644 --- a/airbyte-integrations/connectors/source-bitly/metadata.yaml +++ b/airbyte-integrations/connectors/source-bitly/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-bitly connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 3631f862-646b-4abf-abde-dc37acf3847c - dockerImageTag: 0.0.39 + dockerImageTag: 0.0.40 dockerRepository: airbyte/source-bitly githubIssueLabel: source-bitly icon: icon.svg diff --git a/docs/integrations/sources/bitly.md b/docs/integrations/sources/bitly.md index 335829e81137..cb8b435b4ce6 100644 --- a/docs/integrations/sources/bitly.md +++ b/docs/integrations/sources/bitly.md @@ -33,6 +33,7 @@ Generate API Key [here](https://app.bitly.com/settings/api/) or go to Settings | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.40 | 2026-03-31 | [75893](https://github.com/airbytehq/airbyte/pull/75893) | Update dependencies | | 0.0.39 | 2026-03-24 | [75013](https://github.com/airbytehq/airbyte/pull/75013) | Update dependencies | | 0.0.38 | 2026-03-10 | [74608](https://github.com/airbytehq/airbyte/pull/74608) | Update dependencies | | 0.0.37 | 2026-03-03 | [74198](https://github.com/airbytehq/airbyte/pull/74198) | Update dependencies | From 328d5af1d34efce4262a00b6b52946abd147aacf Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:27:47 +0000 Subject: [PATCH 241/379] =?UTF-8?q?deps(source-basecamp):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75892)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-basecamp/metadata.yaml | 4 ++-- docs/integrations/sources/basecamp.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-basecamp/metadata.yaml b/airbyte-integrations/connectors/source-basecamp/metadata.yaml index 35002589ea21..95304995f7bd 100644 --- a/airbyte-integrations/connectors/source-basecamp/metadata.yaml +++ b/airbyte-integrations/connectors/source-basecamp/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-basecamp connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 0abc340d-772c-4fa1-8d1d-ebf3be72ab51 - dockerImageTag: 0.0.33 + dockerImageTag: 0.0.34 dockerRepository: airbyte/source-basecamp githubIssueLabel: source-basecamp icon: icon.svg diff --git a/docs/integrations/sources/basecamp.md b/docs/integrations/sources/basecamp.md index 5129ee124cc5..ed973a6eaa5c 100644 --- a/docs/integrations/sources/basecamp.md +++ b/docs/integrations/sources/basecamp.md @@ -30,6 +30,7 @@ To obtain a refresh token, you'd need to register an [oauth application](https:/ | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.34 | 2026-03-31 | [75892](https://github.com/airbytehq/airbyte/pull/75892) | Update dependencies | | 0.0.33 | 2026-03-17 | [75000](https://github.com/airbytehq/airbyte/pull/75000) | Update dependencies | | 0.0.32 | 2026-02-24 | [73800](https://github.com/airbytehq/airbyte/pull/73800) | Update dependencies | | 0.0.31 | 2026-02-03 | [72685](https://github.com/airbytehq/airbyte/pull/72685) | Update dependencies | From 27d092a1ca8533fbf67d15a1f2a59def8bde5e2f Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:27:52 +0000 Subject: [PATCH 242/379] =?UTF-8?q?deps(source-beamer):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75891)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-beamer/metadata.yaml | 4 ++-- docs/integrations/sources/beamer.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-beamer/metadata.yaml b/airbyte-integrations/connectors/source-beamer/metadata.yaml index 3e363bf03b97..b4ea21d1ea66 100644 --- a/airbyte-integrations/connectors/source-beamer/metadata.yaml +++ b/airbyte-integrations/connectors/source-beamer/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-beamer connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: b928158d-4d2a-4ea6-a9c6-efa90f5c1e5d - dockerImageTag: 0.0.43 + dockerImageTag: 0.0.44 dockerRepository: airbyte/source-beamer githubIssueLabel: source-beamer icon: icon.svg diff --git a/docs/integrations/sources/beamer.md b/docs/integrations/sources/beamer.md index 6fc77ebeaf98..208aa020fbd6 100644 --- a/docs/integrations/sources/beamer.md +++ b/docs/integrations/sources/beamer.md @@ -20,6 +20,7 @@ Beamer NPS source | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.44 | 2026-03-31 | [75891](https://github.com/airbytehq/airbyte/pull/75891) | Update dependencies | | 0.0.43 | 2026-03-24 | [75018](https://github.com/airbytehq/airbyte/pull/75018) | Update dependencies | | 0.0.42 | 2026-02-24 | [73796](https://github.com/airbytehq/airbyte/pull/73796) | Update dependencies | | 0.0.41 | 2026-02-17 | [73397](https://github.com/airbytehq/airbyte/pull/73397) | Update dependencies | From 9dcba85d70a85a99b279fc889f0f216aa6212d1e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:28:00 +0000 Subject: [PATCH 243/379] =?UTF-8?q?deps(source-sparkpost):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75887)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-sparkpost/metadata.yaml | 4 ++-- docs/integrations/sources/sparkpost.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-sparkpost/metadata.yaml b/airbyte-integrations/connectors/source-sparkpost/metadata.yaml index 031cfd0dda41..6f9c6d11aefe 100644 --- a/airbyte-integrations/connectors/source-sparkpost/metadata.yaml +++ b/airbyte-integrations/connectors/source-sparkpost/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-sparkpost connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 5f3256c6-4247-4b6d-a8e4-1df61dc9322c - dockerImageTag: 0.0.46 + dockerImageTag: 0.0.47 dockerRepository: airbyte/source-sparkpost githubIssueLabel: source-sparkpost icon: icon.svg diff --git a/docs/integrations/sources/sparkpost.md b/docs/integrations/sources/sparkpost.md index 7f3c8c82d180..370c7771925a 100644 --- a/docs/integrations/sources/sparkpost.md +++ b/docs/integrations/sources/sparkpost.md @@ -27,6 +27,7 @@ The SparkPost connector for Airbyte enables seamless integration with SparkPost | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.47 | 2026-03-31 | [75887](https://github.com/airbytehq/airbyte/pull/75887) | Update dependencies | | 0.0.46 | 2026-03-24 | [75385](https://github.com/airbytehq/airbyte/pull/75385) | Update dependencies | | 0.0.45 | 2026-02-24 | [73974](https://github.com/airbytehq/airbyte/pull/73974) | Update dependencies | | 0.0.44 | 2026-02-17 | [73441](https://github.com/airbytehq/airbyte/pull/73441) | Update dependencies | From 4eb8303f32f79b08ca4d16e019b5c626e896dee5 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:28:05 +0000 Subject: [PATCH 244/379] =?UTF-8?q?deps(source-spotify-ads):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75886)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-spotify-ads/metadata.yaml | 4 ++-- docs/integrations/sources/spotify-ads.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-spotify-ads/metadata.yaml b/airbyte-integrations/connectors/source-spotify-ads/metadata.yaml index e6eadf68a576..dca541e38af7 100644 --- a/airbyte-integrations/connectors/source-spotify-ads/metadata.yaml +++ b/airbyte-integrations/connectors/source-spotify-ads/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-spotify-ads connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: f25bd959-d48b-4ca5-88d2-79c52a263185 - dockerImageTag: 0.0.26 + dockerImageTag: 0.0.27 dockerRepository: airbyte/source-spotify-ads githubIssueLabel: source-spotify-ads icon: icon.svg diff --git a/docs/integrations/sources/spotify-ads.md b/docs/integrations/sources/spotify-ads.md index aa05e0ed0cb7..c680e8e6d0f5 100644 --- a/docs/integrations/sources/spotify-ads.md +++ b/docs/integrations/sources/spotify-ads.md @@ -47,6 +47,7 @@ Valid Spotify Ad Account ID | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.27 | 2026-03-31 | [75886](https://github.com/airbytehq/airbyte/pull/75886) | Update dependencies | | 0.0.26 | 2026-03-17 | [75087](https://github.com/airbytehq/airbyte/pull/75087) | Update dependencies | | 0.0.25 | 2026-03-10 | [74571](https://github.com/airbytehq/airbyte/pull/74571) | Update dependencies | | 0.0.24 | 2026-02-24 | [73983](https://github.com/airbytehq/airbyte/pull/73983) | Update dependencies | From 270fd373fe9a99af35503b24362963b55456f499 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:28:11 +0000 Subject: [PATCH 245/379] =?UTF-8?q?deps(source-statsig):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75884)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-statsig/metadata.yaml | 4 ++-- docs/integrations/sources/statsig.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-statsig/metadata.yaml b/airbyte-integrations/connectors/source-statsig/metadata.yaml index 09cfa2e0bc28..cd4c3eaae480 100644 --- a/airbyte-integrations/connectors/source-statsig/metadata.yaml +++ b/airbyte-integrations/connectors/source-statsig/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-statsig connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: c8f77358-755a-4778-a1fc-c23c3cee7d83 - dockerImageTag: 0.0.46 + dockerImageTag: 0.0.47 dockerRepository: airbyte/source-statsig githubIssueLabel: source-statsig icon: icon.svg diff --git a/docs/integrations/sources/statsig.md b/docs/integrations/sources/statsig.md index 3e28cd258c6a..782b2f7ff581 100644 --- a/docs/integrations/sources/statsig.md +++ b/docs/integrations/sources/statsig.md @@ -43,6 +43,7 @@ See the [API docs](https://docs.statsig.com/http-api) for steps to generate the | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.47 | 2026-03-31 | [75884](https://github.com/airbytehq/airbyte/pull/75884) | Update dependencies | | 0.0.46 | 2026-03-17 | [74613](https://github.com/airbytehq/airbyte/pull/74613) | Update dependencies | | 0.0.45 | 2026-02-24 | [73959](https://github.com/airbytehq/airbyte/pull/73959) | Update dependencies | | 0.0.44 | 2026-02-17 | [73130](https://github.com/airbytehq/airbyte/pull/73130) | Update dependencies | From 9ec3d3bc1165a876bfaf224fd9339c7b755c1446 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:28:17 +0000 Subject: [PATCH 246/379] =?UTF-8?q?deps(source-apptivo):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75883)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-apptivo/metadata.yaml | 4 ++-- docs/integrations/sources/apptivo.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-apptivo/metadata.yaml b/airbyte-integrations/connectors/source-apptivo/metadata.yaml index 3bac9b04d60e..2e8c9423d4b8 100644 --- a/airbyte-integrations/connectors/source-apptivo/metadata.yaml +++ b/airbyte-integrations/connectors/source-apptivo/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-apptivo connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: eb41169b-b293-4690-b690-a1046cca0e3b - dockerImageTag: 0.0.44 + dockerImageTag: 0.0.45 dockerRepository: airbyte/source-apptivo githubIssueLabel: source-apptivo icon: icon.svg diff --git a/docs/integrations/sources/apptivo.md b/docs/integrations/sources/apptivo.md index 27cf5a4cdb6f..7875ecb473b5 100644 --- a/docs/integrations/sources/apptivo.md +++ b/docs/integrations/sources/apptivo.md @@ -24,6 +24,7 @@ Apptivo connector seamless data integration between Apptivo and various data wa | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.45 | 2026-03-31 | [75883](https://github.com/airbytehq/airbyte/pull/75883) | Update dependencies | | 0.0.44 | 2026-03-17 | [75005](https://github.com/airbytehq/airbyte/pull/75005) | Update dependencies | | 0.0.43 | 2026-03-10 | [74520](https://github.com/airbytehq/airbyte/pull/74520) | Update dependencies | | 0.0.42 | 2026-03-03 | [74171](https://github.com/airbytehq/airbyte/pull/74171) | Update dependencies | From 18a29d60d3be19cc92ca0697c873ad41566aa97a Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:28:24 +0000 Subject: [PATCH 247/379] =?UTF-8?q?deps(source-ashby):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75881)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-ashby/metadata.yaml | 4 ++-- docs/integrations/sources/ashby.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-ashby/metadata.yaml b/airbyte-integrations/connectors/source-ashby/metadata.yaml index 3b8823a7fbb0..726d7ebc7c8d 100644 --- a/airbyte-integrations/connectors/source-ashby/metadata.yaml +++ b/airbyte-integrations/connectors/source-ashby/metadata.yaml @@ -2,7 +2,7 @@ data: connectorSubtype: api connectorType: source definitionId: 4e8c9fa0-3634-499b-b948-11581b5c3efa - dockerImageTag: 0.3.4 + dockerImageTag: 0.3.5 dockerRepository: airbyte/source-ashby githubIssueLabel: source-ashby icon: ashby.svg @@ -37,7 +37,7 @@ data: connectorTestSuitesOptions: - suite: unitTests connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e externalDocumentationUrls: - title: API documentation url: https://developers.ashbyhq.com/ diff --git a/docs/integrations/sources/ashby.md b/docs/integrations/sources/ashby.md index 48d3473b4a0a..ad82bd571ba3 100644 --- a/docs/integrations/sources/ashby.md +++ b/docs/integrations/sources/ashby.md @@ -76,6 +76,7 @@ The Ashby connector should not run into Ashby API limitations under normal usage | Version | Date | Pull Request | Subject | |:--------| :--------- | :------------------------------------------------------- |:--------------------------------------------| +| 0.3.5 | 2026-03-31 | [75881](https://github.com/airbytehq/airbyte/pull/75881) | Update dependencies | | 0.3.4 | 2026-03-24 | [75325](https://github.com/airbytehq/airbyte/pull/75325) | Update dependencies | | 0.3.3 | 2026-03-10 | [74490](https://github.com/airbytehq/airbyte/pull/74490) | Update dependencies | | 0.3.2 | 2026-02-24 | [73805](https://github.com/airbytehq/airbyte/pull/73805) | Update dependencies | From 106a52095604cdafefa1c00927610068466b69a4 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:28:31 +0000 Subject: [PATCH 248/379] =?UTF-8?q?deps(source-bigmailer):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75880)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-bigmailer/metadata.yaml | 4 ++-- docs/integrations/sources/bigmailer.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-bigmailer/metadata.yaml b/airbyte-integrations/connectors/source-bigmailer/metadata.yaml index 99fcfcf9a1a9..8bef7d3518f0 100644 --- a/airbyte-integrations/connectors/source-bigmailer/metadata.yaml +++ b/airbyte-integrations/connectors/source-bigmailer/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-bigmailer connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: c448df04-e5ce-43e0-85cb-a4cfff936c3d - dockerImageTag: 0.0.45 + dockerImageTag: 0.0.46 dockerRepository: airbyte/source-bigmailer githubIssueLabel: source-bigmailer icon: icon.svg diff --git a/docs/integrations/sources/bigmailer.md b/docs/integrations/sources/bigmailer.md index 41f26ae83687..addb5605231c 100644 --- a/docs/integrations/sources/bigmailer.md +++ b/docs/integrations/sources/bigmailer.md @@ -28,6 +28,7 @@ An Airbyte connector for [BigMailer](https://bigmailer.com) would facilitate sea | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.46 | 2026-03-31 | [75880](https://github.com/airbytehq/airbyte/pull/75880) | Update dependencies | | 0.0.45 | 2026-03-24 | [75318](https://github.com/airbytehq/airbyte/pull/75318) | Update dependencies | | 0.0.44 | 2026-03-10 | [74485](https://github.com/airbytehq/airbyte/pull/74485) | Update dependencies | | 0.0.43 | 2026-02-24 | [73818](https://github.com/airbytehq/airbyte/pull/73818) | Update dependencies | From 005224610531ea1dc0a758af385d3793795da173 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:28:36 +0000 Subject: [PATCH 249/379] =?UTF-8?q?deps(source-apple-search-ads):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75879)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-apple-search-ads/metadata.yaml | 4 ++-- docs/integrations/sources/apple-search-ads.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-apple-search-ads/metadata.yaml b/airbyte-integrations/connectors/source-apple-search-ads/metadata.yaml index b5fe46fcec40..fc08fe7f9bcd 100644 --- a/airbyte-integrations/connectors/source-apple-search-ads/metadata.yaml +++ b/airbyte-integrations/connectors/source-apple-search-ads/metadata.yaml @@ -2,7 +2,7 @@ data: connectorSubtype: api connectorType: source definitionId: e59c8416-c2fa-4bd3-9e95-52677ea281c1 - dockerImageTag: 1.0.10 + dockerImageTag: 1.0.11 dockerRepository: airbyte/source-apple-search-ads githubIssueLabel: source-apple-search-ads icon: icon.svg @@ -47,7 +47,7 @@ data: alias: airbyte-connector-testing-secret-store supportLevel: community connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e externalDocumentationUrls: - title: API reference url: https://developer.apple.com/documentation/apple_search_ads diff --git a/docs/integrations/sources/apple-search-ads.md b/docs/integrations/sources/apple-search-ads.md index 7d45e73c6269..a7b1fb1d883d 100644 --- a/docs/integrations/sources/apple-search-ads.md +++ b/docs/integrations/sources/apple-search-ads.md @@ -70,6 +70,7 @@ However, at this moment and as indicated in the stream names, the connector only | Version | Date | Pull Request | Subject | |:--------|:-----------|:---------------------------------------------------------|:-------------------------------------------------------------------------------------| +| 1.0.11 | 2026-03-31 | [75879](https://github.com/airbytehq/airbyte/pull/75879) | Update dependencies | | 1.0.10 | 2026-03-24 | [75015](https://github.com/airbytehq/airbyte/pull/75015) | Update dependencies | | 1.0.9 | 2026-03-10 | [74512](https://github.com/airbytehq/airbyte/pull/74512) | Update dependencies | | 1.0.8 | 2026-03-03 | [74180](https://github.com/airbytehq/airbyte/pull/74180) | Update dependencies | From eaee933db8f0b6cb5a4bbeaf6d217212b0c7556f Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:28:42 +0000 Subject: [PATCH 250/379] =?UTF-8?q?deps(source-reddit):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75878)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-reddit/metadata.yaml | 4 ++-- docs/integrations/sources/reddit.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-reddit/metadata.yaml b/airbyte-integrations/connectors/source-reddit/metadata.yaml index e53a184b499e..84c6158421db 100644 --- a/airbyte-integrations/connectors/source-reddit/metadata.yaml +++ b/airbyte-integrations/connectors/source-reddit/metadata.yaml @@ -14,11 +14,11 @@ data: enabled: false packageName: airbyte-source-reddit connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 3ed344ac-4099-402c-bf83-1cfdc53295d9 - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-reddit githubIssueLabel: source-reddit icon: icon.svg diff --git a/docs/integrations/sources/reddit.md b/docs/integrations/sources/reddit.md index af73df15e4a6..a7cca86828df 100644 --- a/docs/integrations/sources/reddit.md +++ b/docs/integrations/sources/reddit.md @@ -65,6 +65,7 @@ Hit send to receive `api_key` in the response under `access_token` | Version | Date |Pull Request | Subject | |------------------|------------|--------------|----------------| +| 0.0.48 | 2026-03-31 | [75878](https://github.com/airbytehq/airbyte/pull/75878) | Update dependencies | | 0.0.47 | 2026-03-17 | [74911](https://github.com/airbytehq/airbyte/pull/74911) | Update dependencies | | 0.0.46 | 2026-02-24 | [73532](https://github.com/airbytehq/airbyte/pull/73532) | Update dependencies | | 0.0.45 | 2026-02-03 | [72651](https://github.com/airbytehq/airbyte/pull/72651) | Update dependencies | From 3c10d0c86357b147fa0fb869c83d48933dd3f729 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:28:47 +0000 Subject: [PATCH 251/379] =?UTF-8?q?deps(source-zapsign):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75877)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-zapsign/metadata.yaml | 4 ++-- docs/integrations/sources/zapsign.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-zapsign/metadata.yaml b/airbyte-integrations/connectors/source-zapsign/metadata.yaml index c788a6e5742b..e42b522b038f 100644 --- a/airbyte-integrations/connectors/source-zapsign/metadata.yaml +++ b/airbyte-integrations/connectors/source-zapsign/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-zapsign connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 4a1d519c-4703-4450-87db-d95816ba4f68 - dockerImageTag: 0.0.33 + dockerImageTag: 0.0.34 dockerRepository: airbyte/source-zapsign githubIssueLabel: source-zapsign icon: icon.svg diff --git a/docs/integrations/sources/zapsign.md b/docs/integrations/sources/zapsign.md index 3ebb2e7cbb98..c36cb6747806 100644 --- a/docs/integrations/sources/zapsign.md +++ b/docs/integrations/sources/zapsign.md @@ -24,6 +24,7 @@ API Reference: https://docs.zapsign.com.br/ | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.34 | 2026-03-31 | [75877](https://github.com/airbytehq/airbyte/pull/75877) | Update dependencies | | 0.0.33 | 2026-03-24 | [75376](https://github.com/airbytehq/airbyte/pull/75376) | Update dependencies | | 0.0.32 | 2026-02-24 | [73892](https://github.com/airbytehq/airbyte/pull/73892) | Update dependencies | | 0.0.31 | 2026-02-10 | [73154](https://github.com/airbytehq/airbyte/pull/73154) | Update dependencies | From 54c0dfed455448b30da14afca594e63f06e7062f Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:28:52 +0000 Subject: [PATCH 252/379] =?UTF-8?q?deps(source-wrike):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75876)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-wrike/metadata.yaml | 4 ++-- docs/integrations/sources/wrike.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-wrike/metadata.yaml b/airbyte-integrations/connectors/source-wrike/metadata.yaml index e8d41872eb2e..382b0a6fb63c 100644 --- a/airbyte-integrations/connectors/source-wrike/metadata.yaml +++ b/airbyte-integrations/connectors/source-wrike/metadata.yaml @@ -5,7 +5,7 @@ data: - app-eu*.wrike.com - www.wrike.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e remoteRegistries: pypi: enabled: false @@ -18,7 +18,7 @@ data: connectorSubtype: api connectorType: source definitionId: 9c13f986-a13b-4988-b808-4705badf71c2 - dockerImageTag: 0.3.51 + dockerImageTag: 0.3.52 dockerRepository: airbyte/source-wrike githubIssueLabel: source-wrike icon: wrike.svg diff --git a/docs/integrations/sources/wrike.md b/docs/integrations/sources/wrike.md index b6b8606319e3..1c11babf9207 100644 --- a/docs/integrations/sources/wrike.md +++ b/docs/integrations/sources/wrike.md @@ -50,6 +50,7 @@ The Wrike connector should not run into Wrike API limitations under normal usage | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- |:-----------------------------------------------------------------------| +| 0.3.52 | 2026-03-31 | [75876](https://github.com/airbytehq/airbyte/pull/75876) | Update dependencies | | 0.3.51 | 2026-03-24 | [75377](https://github.com/airbytehq/airbyte/pull/75377) | Update dependencies | | 0.3.50 | 2026-03-10 | [74667](https://github.com/airbytehq/airbyte/pull/74667) | Update dependencies | | 0.3.49 | 2026-02-24 | [73538](https://github.com/airbytehq/airbyte/pull/73538) | Update dependencies | From 3d05dd342e25e2ee5155b9cabfa5d96a6763eacd Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:28:58 +0000 Subject: [PATCH 253/379] =?UTF-8?q?deps(source-zendesk-sunshine):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75875)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-zendesk-sunshine/metadata.yaml | 4 ++-- docs/integrations/sources/zendesk-sunshine.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-zendesk-sunshine/metadata.yaml b/airbyte-integrations/connectors/source-zendesk-sunshine/metadata.yaml index c0508cda6801..fac010c143e4 100644 --- a/airbyte-integrations/connectors/source-zendesk-sunshine/metadata.yaml +++ b/airbyte-integrations/connectors/source-zendesk-sunshine/metadata.yaml @@ -6,11 +6,11 @@ data: hosts: - ${subdomain}.zendesk.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 325e0640-e7b3-4e24-b823-3361008f603f - dockerImageTag: 0.4.4 + dockerImageTag: 0.4.5 dockerRepository: airbyte/source-zendesk-sunshine documentationUrl: https://docs.airbyte.com/integrations/sources/zendesk-sunshine githubIssueLabel: source-zendesk-sunshine diff --git a/docs/integrations/sources/zendesk-sunshine.md b/docs/integrations/sources/zendesk-sunshine.md index 6365a5c2b2f5..ed53466b5f7b 100644 --- a/docs/integrations/sources/zendesk-sunshine.md +++ b/docs/integrations/sources/zendesk-sunshine.md @@ -76,6 +76,7 @@ To generate a legacy access token, follow Zendesk's [OAuth documentation](https: | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------ | +| 0.4.5 | 2026-03-31 | [75875](https://github.com/airbytehq/airbyte/pull/75875) | Update dependencies | | 0.4.4 | 2026-03-17 | [74393](https://github.com/airbytehq/airbyte/pull/74393) | Migrate to scopes object array format | | 0.4.3 | 2026-03-17 | [75115](https://github.com/airbytehq/airbyte/pull/75115) | Update dependencies | | 0.4.2 | 2026-02-24 | [73539](https://github.com/airbytehq/airbyte/pull/73539) | Update dependencies | From b48a74466f8e93729df6f8fe48623221608b4cd4 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:29:03 +0000 Subject: [PATCH 254/379] =?UTF-8?q?deps(source-you-need-a-budget-ynab):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75874)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-you-need-a-budget-ynab/metadata.yaml | 4 ++-- docs/integrations/sources/you-need-a-budget-ynab.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-you-need-a-budget-ynab/metadata.yaml b/airbyte-integrations/connectors/source-you-need-a-budget-ynab/metadata.yaml index 2cd2fff48238..a122c34e3f75 100644 --- a/airbyte-integrations/connectors/source-you-need-a-budget-ynab/metadata.yaml +++ b/airbyte-integrations/connectors/source-you-need-a-budget-ynab/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-you-need-a-budget-ynab connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: a60d9f16-e0bd-459f-9419-fd47f9788be1 - dockerImageTag: 0.0.51 + dockerImageTag: 0.0.52 dockerRepository: airbyte/source-you-need-a-budget-ynab githubIssueLabel: source-you-need-a-budget-ynab icon: icon.svg diff --git a/docs/integrations/sources/you-need-a-budget-ynab.md b/docs/integrations/sources/you-need-a-budget-ynab.md index 7202433eafea..83358f7f33e9 100644 --- a/docs/integrations/sources/you-need-a-budget-ynab.md +++ b/docs/integrations/sources/you-need-a-budget-ynab.md @@ -24,6 +24,7 @@ Replicates the budgets, accounts, categories, payees, transactions, and category | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.52 | 2026-03-31 | [75874](https://github.com/airbytehq/airbyte/pull/75874) | Update dependencies | | 0.0.51 | 2026-03-17 | [75089](https://github.com/airbytehq/airbyte/pull/75089) | Update dependencies | | 0.0.50 | 2026-03-10 | [74668](https://github.com/airbytehq/airbyte/pull/74668) | Update dependencies | | 0.0.49 | 2026-02-24 | [73537](https://github.com/airbytehq/airbyte/pull/73537) | Update dependencies | From fbe4544bf8aa30fa399cd88329b806d7f6688273 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:29:08 +0000 Subject: [PATCH 255/379] =?UTF-8?q?deps(source-productive):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75873)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-productive/metadata.yaml | 4 ++-- docs/integrations/sources/productive.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-productive/metadata.yaml b/airbyte-integrations/connectors/source-productive/metadata.yaml index c131c1a47c6c..9f73fdfca595 100644 --- a/airbyte-integrations/connectors/source-productive/metadata.yaml +++ b/airbyte-integrations/connectors/source-productive/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-productive connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 51766ab3-df25-4c8c-98a4-647440d0dfbb - dockerImageTag: 0.0.45 + dockerImageTag: 0.0.46 dockerRepository: airbyte/source-productive githubIssueLabel: source-productive icon: icon.svg diff --git a/docs/integrations/sources/productive.md b/docs/integrations/sources/productive.md index 0f1d41528f5d..29aeed9515c7 100644 --- a/docs/integrations/sources/productive.md +++ b/docs/integrations/sources/productive.md @@ -83,6 +83,7 @@ Visit `https://app.productive.io/ORG_ID-UUID/settings/api-integrations` for gett | Version | Date | Pull Request | Subject | | ------------------ | ------------ | -- | ---------------- | +| 0.0.46 | 2026-03-31 | [75873](https://github.com/airbytehq/airbyte/pull/75873) | Update dependencies | | 0.0.45 | 2026-03-24 | [75375](https://github.com/airbytehq/airbyte/pull/75375) | Update dependencies | | 0.0.44 | 2026-03-10 | [74624](https://github.com/airbytehq/airbyte/pull/74624) | Update dependencies | | 0.0.43 | 2026-02-24 | [73855](https://github.com/airbytehq/airbyte/pull/73855) | Update dependencies | From 7b2691cb1a9183f057d8b0da14847bfec5ee94a2 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:29:13 +0000 Subject: [PATCH 256/379] =?UTF-8?q?deps(source-pokeapi):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75872)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-pokeapi/metadata.yaml | 4 ++-- docs/integrations/sources/pokeapi.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-pokeapi/metadata.yaml b/airbyte-integrations/connectors/source-pokeapi/metadata.yaml index fe92142b8468..936d53d9f50d 100644 --- a/airbyte-integrations/connectors/source-pokeapi/metadata.yaml +++ b/airbyte-integrations/connectors/source-pokeapi/metadata.yaml @@ -18,11 +18,11 @@ data: # Please update to the latest version of the connector base image. # https://hub.docker.com/r/airbyte/python-connector-base # Please use the full address with sha256 hash to guarantee build reproducibility. - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 6371b14b-bc68-4236-bfbd-468e8df8e968 - dockerImageTag: 0.3.51 + dockerImageTag: 0.3.52 dockerRepository: airbyte/source-pokeapi githubIssueLabel: source-pokeapi icon: pokeapi.svg diff --git a/docs/integrations/sources/pokeapi.md b/docs/integrations/sources/pokeapi.md index df850613e6af..b73983166983 100644 --- a/docs/integrations/sources/pokeapi.md +++ b/docs/integrations/sources/pokeapi.md @@ -39,6 +39,7 @@ The PokéAPI uses the same [JSONSchema](https://json-schema.org/understanding-js | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :---------------------------------------------- | +| 0.3.52 | 2026-03-31 | [75872](https://github.com/airbytehq/airbyte/pull/75872) | Update dependencies | | 0.3.51 | 2026-03-24 | [75403](https://github.com/airbytehq/airbyte/pull/75403) | Update dependencies | | 0.3.50 | 2026-02-24 | [73837](https://github.com/airbytehq/airbyte/pull/73837) | Update dependencies | | 0.3.49 | 2026-02-10 | [73196](https://github.com/airbytehq/airbyte/pull/73196) | Update dependencies | From 4a4e9fe35244bcc4f03184aad54662d7fd9f3a37 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:29:19 +0000 Subject: [PATCH 257/379] =?UTF-8?q?deps(source-stockdata):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75871)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-stockdata/metadata.yaml | 4 ++-- docs/integrations/sources/stockdata.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-stockdata/metadata.yaml b/airbyte-integrations/connectors/source-stockdata/metadata.yaml index bed83c5ac923..e34091e59461 100644 --- a/airbyte-integrations/connectors/source-stockdata/metadata.yaml +++ b/airbyte-integrations/connectors/source-stockdata/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-stockdata connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: ca58f75d-3929-4fd3-a5b0-4dd92d275c8d - dockerImageTag: 0.0.48 + dockerImageTag: 0.0.49 dockerRepository: airbyte/source-stockdata githubIssueLabel: source-stockdata icon: icon.svg diff --git a/docs/integrations/sources/stockdata.md b/docs/integrations/sources/stockdata.md index 677cd2ddd512..1873cf248db2 100644 --- a/docs/integrations/sources/stockdata.md +++ b/docs/integrations/sources/stockdata.md @@ -28,6 +28,7 @@ With this connector we can extract data from EOD , Intraday and news feeds strea | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.49 | 2026-03-31 | [75871](https://github.com/airbytehq/airbyte/pull/75871) | Update dependencies | | 0.0.48 | 2026-03-24 | [75086](https://github.com/airbytehq/airbyte/pull/75086) | Update dependencies | | 0.0.47 | 2026-02-24 | [73942](https://github.com/airbytehq/airbyte/pull/73942) | Update dependencies | | 0.0.46 | 2026-02-17 | [73440](https://github.com/airbytehq/airbyte/pull/73440) | Update dependencies | From 9c7312fe433b45c3c6eb3b8f48e936549c2b4f58 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:29:24 +0000 Subject: [PATCH 258/379] =?UTF-8?q?deps(source-stigg):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75870)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-stigg/metadata.yaml | 4 ++-- docs/integrations/sources/stigg.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-stigg/metadata.yaml b/airbyte-integrations/connectors/source-stigg/metadata.yaml index f15d7c82e489..928bf80f9a05 100644 --- a/airbyte-integrations/connectors/source-stigg/metadata.yaml +++ b/airbyte-integrations/connectors/source-stigg/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-stigg connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: c3c0a577-29d7-4e31-8191-f2a346051c82 - dockerImageTag: 0.0.6 + dockerImageTag: 0.0.7 dockerRepository: airbyte/source-stigg githubIssueLabel: source-stigg icon: icon.svg diff --git a/docs/integrations/sources/stigg.md b/docs/integrations/sources/stigg.md index 9fe8648032ac..d825b5af4e2d 100644 --- a/docs/integrations/sources/stigg.md +++ b/docs/integrations/sources/stigg.md @@ -47,6 +47,7 @@ The Stigg source connector supports the following sync modes: | Version | Date | Pull Request | Subject | | :------ | :--------- | :----------------------------------------------------------- | :-------------- | +| 0.0.7 | 2026-03-31 | [75870](https://github.com/airbytehq/airbyte/pull/75870) | Update dependencies | | 0.0.6 | 2026-03-24 | [75392](https://github.com/airbytehq/airbyte/pull/75392) | Update dependencies | | 0.0.5 | 2026-02-24 | [73946](https://github.com/airbytehq/airbyte/pull/73946) | Update dependencies | | 0.0.4 | 2026-02-17 | [72773](https://github.com/airbytehq/airbyte/pull/72773) | Update dependencies | From 4e94a911ab628c665ae2f317bb5aac0e9ae43041 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:29:30 +0000 Subject: [PATCH 259/379] =?UTF-8?q?deps(source-poplar):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75869)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-poplar/metadata.yaml | 4 ++-- docs/integrations/sources/poplar.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-poplar/metadata.yaml b/airbyte-integrations/connectors/source-poplar/metadata.yaml index 867a1a59941a..4b563e6ef361 100644 --- a/airbyte-integrations/connectors/source-poplar/metadata.yaml +++ b/airbyte-integrations/connectors/source-poplar/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-poplar connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 2d9f2646-1e32-4336-abbe-7e5e113b479e - dockerImageTag: 0.0.34 + dockerImageTag: 0.0.35 dockerRepository: airbyte/source-poplar githubIssueLabel: source-poplar icon: icon.svg diff --git a/docs/integrations/sources/poplar.md b/docs/integrations/sources/poplar.md index 9b323b5cb796..6441992fb974 100644 --- a/docs/integrations/sources/poplar.md +++ b/docs/integrations/sources/poplar.md @@ -24,6 +24,7 @@ Documentation: https://developers.heypoplar.com/ | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.35 | 2026-03-31 | [75869](https://github.com/airbytehq/airbyte/pull/75869) | Update dependencies | | 0.0.34 | 2026-03-17 | [74932](https://github.com/airbytehq/airbyte/pull/74932) | Update dependencies | | 0.0.33 | 2026-03-10 | [74643](https://github.com/airbytehq/airbyte/pull/74643) | Update dependencies | | 0.0.32 | 2026-02-24 | [73844](https://github.com/airbytehq/airbyte/pull/73844) | Update dependencies | From 73a97d1e45418cddb2b51062bf1650f2dbae36cd Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:29:34 +0000 Subject: [PATCH 260/379] =?UTF-8?q?deps(source-solarwinds-service-desk):?= =?UTF-8?q?=20=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#7586?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-solarwinds-service-desk/metadata.yaml | 4 ++-- docs/integrations/sources/solarwinds-service-desk.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-solarwinds-service-desk/metadata.yaml b/airbyte-integrations/connectors/source-solarwinds-service-desk/metadata.yaml index 84062139be6a..37e112fb0a65 100644 --- a/airbyte-integrations/connectors/source-solarwinds-service-desk/metadata.yaml +++ b/airbyte-integrations/connectors/source-solarwinds-service-desk/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-solarwinds-service-desk connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 7fc8e411-25e6-4c8a-aab0-0b662a833c8c - dockerImageTag: 0.0.50 + dockerImageTag: 0.0.51 dockerRepository: airbyte/source-solarwinds-service-desk githubIssueLabel: source-solarwinds-service-desk icon: icon.svg diff --git a/docs/integrations/sources/solarwinds-service-desk.md b/docs/integrations/sources/solarwinds-service-desk.md index 1598cf95afdd..69d85c0806da 100644 --- a/docs/integrations/sources/solarwinds-service-desk.md +++ b/docs/integrations/sources/solarwinds-service-desk.md @@ -45,6 +45,7 @@ Documentation: https://apidoc.samanage.com/#section/General-Concepts | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.51 | 2026-03-31 | [75868](https://github.com/airbytehq/airbyte/pull/75868) | Update dependencies | | 0.0.50 | 2026-03-24 | [75381](https://github.com/airbytehq/airbyte/pull/75381) | Update dependencies | | 0.0.49 | 2026-03-10 | [74580](https://github.com/airbytehq/airbyte/pull/74580) | Update dependencies | | 0.0.48 | 2026-02-24 | [73953](https://github.com/airbytehq/airbyte/pull/73953) | Update dependencies | From ca3fb1e9611080e2af6e12f7845637d0a9af866e Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:29:41 +0000 Subject: [PATCH 261/379] =?UTF-8?q?deps(source-productboard):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75867)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-productboard/metadata.yaml | 4 ++-- docs/integrations/sources/productboard.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-productboard/metadata.yaml b/airbyte-integrations/connectors/source-productboard/metadata.yaml index f310412bc146..7d783ee69bd1 100644 --- a/airbyte-integrations/connectors/source-productboard/metadata.yaml +++ b/airbyte-integrations/connectors/source-productboard/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-productboard connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 43ae66ee-e3df-4fb7-bff5-9625d25cdc14 - dockerImageTag: 0.0.53 + dockerImageTag: 0.0.54 dockerRepository: airbyte/source-productboard githubIssueLabel: source-productboard icon: icon.svg diff --git a/docs/integrations/sources/productboard.md b/docs/integrations/sources/productboard.md index fdf8d15ab240..7d284a71356f 100644 --- a/docs/integrations/sources/productboard.md +++ b/docs/integrations/sources/productboard.md @@ -36,6 +36,7 @@ A manifest only source for Productboard. https://www.productboard.com/ | Version | Date | Pull Request | Subject | |---------|------------|----------------------------------------------------------|-------------------------------------------------------------------------------------------| +| 0.0.54 | 2026-03-31 | [75867](https://github.com/airbytehq/airbyte/pull/75867) | Update dependencies | | 0.0.53 | 2026-03-17 | [74930](https://github.com/airbytehq/airbyte/pull/74930) | Update dependencies | | 0.0.52 | 2026-03-10 | [74617](https://github.com/airbytehq/airbyte/pull/74617) | Update dependencies | | 0.0.51 | 2026-03-03 | [74218](https://github.com/airbytehq/airbyte/pull/74218) | Update dependencies | From 70cd414713bc61244ef4428ec852bbbdac66dd00 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:29:53 +0000 Subject: [PATCH 262/379] =?UTF-8?q?deps(source-smartreach):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75865)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-smartreach/metadata.yaml | 4 ++-- docs/integrations/sources/smartreach.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-smartreach/metadata.yaml b/airbyte-integrations/connectors/source-smartreach/metadata.yaml index ab7f3714b831..e0cea9b90785 100644 --- a/airbyte-integrations/connectors/source-smartreach/metadata.yaml +++ b/airbyte-integrations/connectors/source-smartreach/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-smartreach connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 896dc0b3-9b46-4ff4-8ba6-cfd7460a3895 - dockerImageTag: 0.0.42 + dockerImageTag: 0.0.43 dockerRepository: airbyte/source-smartreach githubIssueLabel: source-smartreach icon: icon.svg diff --git a/docs/integrations/sources/smartreach.md b/docs/integrations/sources/smartreach.md index ca30fb750d40..c48b09d7c8b0 100644 --- a/docs/integrations/sources/smartreach.md +++ b/docs/integrations/sources/smartreach.md @@ -23,6 +23,7 @@ Docs : https://smartreach.io/api_docs#smartreach-api | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.43 | 2026-03-31 | [75865](https://github.com/airbytehq/airbyte/pull/75865) | Update dependencies | | 0.0.42 | 2026-03-17 | [75108](https://github.com/airbytehq/airbyte/pull/75108) | Update dependencies | | 0.0.41 | 2026-02-24 | [73937](https://github.com/airbytehq/airbyte/pull/73937) | Update dependencies | | 0.0.40 | 2026-02-17 | [73201](https://github.com/airbytehq/airbyte/pull/73201) | Update dependencies | From d1995731b7386827625adf62775f4bd4553f575f Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:29:59 +0000 Subject: [PATCH 263/379] =?UTF-8?q?deps(source-stripe):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75864)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-stripe/metadata.yaml | 4 ++-- docs/integrations/sources/stripe.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-stripe/metadata.yaml b/airbyte-integrations/connectors/source-stripe/metadata.yaml index bcab470cf44a..1cd845e04231 100644 --- a/airbyte-integrations/connectors/source-stripe/metadata.yaml +++ b/airbyte-integrations/connectors/source-stripe/metadata.yaml @@ -6,11 +6,11 @@ data: hosts: - api.stripe.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: e094cb9a-26de-4645-8761-65c0c425d1de - dockerImageTag: 5.15.22 + dockerImageTag: 5.15.23 dockerRepository: airbyte/source-stripe documentationUrl: https://docs.airbyte.com/integrations/sources/stripe erdUrl: https://dbdocs.io/airbyteio/source-stripe?view=relationships diff --git a/docs/integrations/sources/stripe.md b/docs/integrations/sources/stripe.md index 43131fd304a4..5bf8649b2cc6 100644 --- a/docs/integrations/sources/stripe.md +++ b/docs/integrations/sources/stripe.md @@ -313,6 +313,7 @@ Each record is marked with `is_deleted` flag when the appropriate event happens | Version | Date | Pull Request | Subject | |:------------|:-----------|:-------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 5.15.23 | 2026-03-31 | [75864](https://github.com/airbytehq/airbyte/pull/75864) | Update dependencies | | 5.15.22 | 2026-03-12 | [74770](https://github.com/airbytehq/airbyte/pull/74770) | Upgrade CDK to 7.13.0 | | 5.15.21 | 2026-03-06 | [74342](https://github.com/airbytehq/airbyte/pull/74342) | Promoting release candidate 5.15.21-rc.5 to a main version. | | 5.15.21-rc.5 | 2026-03-06 | [74337](https://github.com/airbytehq/airbyte/pull/74337) | Make API data retention validation optional per stream via new `api_retention_streams` config field, upgrade CDK to 7.8.1.post54 | From bf6642cf7d9487d9c720ffaeb09a172c60128649 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:30:04 +0000 Subject: [PATCH 264/379] =?UTF-8?q?deps(source-strava):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75863)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-strava/metadata.yaml | 4 ++-- docs/integrations/sources/strava.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-strava/metadata.yaml b/airbyte-integrations/connectors/source-strava/metadata.yaml index f29b87adc2b5..6848a534040b 100644 --- a/airbyte-integrations/connectors/source-strava/metadata.yaml +++ b/airbyte-integrations/connectors/source-strava/metadata.yaml @@ -6,11 +6,11 @@ data: hosts: - strava.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 7a4327c4-315a-11ec-8d3d-0242ac130003 - dockerImageTag: 0.3.44 + dockerImageTag: 0.3.45 dockerRepository: airbyte/source-strava documentationUrl: https://docs.airbyte.com/integrations/sources/strava githubIssueLabel: source-strava diff --git a/docs/integrations/sources/strava.md b/docs/integrations/sources/strava.md index f3590cda8658..4de040e29bbb 100644 --- a/docs/integrations/sources/strava.md +++ b/docs/integrations/sources/strava.md @@ -127,6 +127,7 @@ More information about Strava rate limits and adjustments to those limits can be | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------ | +| 0.3.45 | 2026-03-31 | [75863](https://github.com/airbytehq/airbyte/pull/75863) | Update dependencies | | 0.3.44 | 2026-03-17 | [75088](https://github.com/airbytehq/airbyte/pull/75088) | Update dependencies | | 0.3.43 | 2026-03-10 | [74577](https://github.com/airbytehq/airbyte/pull/74577) | Update dependencies | | 0.3.42 | 2026-03-03 | [73975](https://github.com/airbytehq/airbyte/pull/73975) | Update dependencies | From 82aa7ea8ab815261b408efcd77a909364e6243b4 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:30:13 +0000 Subject: [PATCH 265/379] =?UTF-8?q?deps(source-workflowmax):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75862)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-workflowmax/metadata.yaml | 4 ++-- docs/integrations/sources/workflowmax.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-workflowmax/metadata.yaml b/airbyte-integrations/connectors/source-workflowmax/metadata.yaml index 84fff6a2a8bd..ebbe09a0fdca 100644 --- a/airbyte-integrations/connectors/source-workflowmax/metadata.yaml +++ b/airbyte-integrations/connectors/source-workflowmax/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-workflowmax connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: a3eb6410-f3c3-48ba-8b27-29a56de1e9db - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-workflowmax githubIssueLabel: source-workflowmax icon: icon.svg diff --git a/docs/integrations/sources/workflowmax.md b/docs/integrations/sources/workflowmax.md index 9d4e49e306f7..1352bba3dc97 100644 --- a/docs/integrations/sources/workflowmax.md +++ b/docs/integrations/sources/workflowmax.md @@ -60,6 +60,7 @@ Then authorize your source with the required information. | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.48 | 2026-03-31 | [75862](https://github.com/airbytehq/airbyte/pull/75862) | Update dependencies | | 0.0.47 | 2026-03-17 | [75093](https://github.com/airbytehq/airbyte/pull/75093) | Update dependencies | | 0.0.46 | 2026-03-03 | [73913](https://github.com/airbytehq/airbyte/pull/73913) | Update dependencies | | 0.0.45 | 2026-02-17 | [73530](https://github.com/airbytehq/airbyte/pull/73530) | Update dependencies | From 4fc612054283c5dc5784c3dbe1d5d603be482b7b Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:30:19 +0000 Subject: [PATCH 266/379] =?UTF-8?q?deps(source-wordpress):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75861)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-wordpress/metadata.yaml | 4 ++-- docs/integrations/sources/wordpress.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-wordpress/metadata.yaml b/airbyte-integrations/connectors/source-wordpress/metadata.yaml index 04494bbce16e..5f8b1e8c6507 100644 --- a/airbyte-integrations/connectors/source-wordpress/metadata.yaml +++ b/airbyte-integrations/connectors/source-wordpress/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-wordpress connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: c71d6f95-a912-432b-ad96-73ded4be7b9c - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-wordpress githubIssueLabel: source-wordpress icon: icon.svg diff --git a/docs/integrations/sources/wordpress.md b/docs/integrations/sources/wordpress.md index a7e83e91a634..4bde70073e7f 100644 --- a/docs/integrations/sources/wordpress.md +++ b/docs/integrations/sources/wordpress.md @@ -38,6 +38,7 @@ The WordPress connector enables seamless data synchronization between your WordP | Version | Date | Pull Request | Subject | | ------- | ---------- | ------------ | ------------------------------------------------------------------------------------- | +| 0.0.48 | 2026-03-31 | [75861](https://github.com/airbytehq/airbyte/pull/75861) | Update dependencies | | 0.0.47 | 2026-03-24 | [74691](https://github.com/airbytehq/airbyte/pull/74691) | Update dependencies | | 0.0.46 | 2026-03-03 | [74149](https://github.com/airbytehq/airbyte/pull/74149) | Update dependencies | | 0.0.45 | 2026-02-17 | [73511](https://github.com/airbytehq/airbyte/pull/73511) | Update dependencies | From 683fce7a80a6b9e53b2ce3835b7907c8803b5496 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:30:25 +0000 Subject: [PATCH 267/379] =?UTF-8?q?deps(source-savvycal):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75860)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-savvycal/metadata.yaml | 4 ++-- docs/integrations/sources/savvycal.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-savvycal/metadata.yaml b/airbyte-integrations/connectors/source-savvycal/metadata.yaml index 6e0a46fcc169..72336b8807bf 100644 --- a/airbyte-integrations/connectors/source-savvycal/metadata.yaml +++ b/airbyte-integrations/connectors/source-savvycal/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-savvycal connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: a554ed06-74e2-4c60-9510-d63f7dc463b6 - dockerImageTag: 0.0.50 + dockerImageTag: 0.0.51 dockerRepository: airbyte/source-savvycal githubIssueLabel: source-savvycal icon: icon.svg diff --git a/docs/integrations/sources/savvycal.md b/docs/integrations/sources/savvycal.md index 7c849e69f15c..144487971635 100644 --- a/docs/integrations/sources/savvycal.md +++ b/docs/integrations/sources/savvycal.md @@ -21,6 +21,7 @@ Sync your scheduled meetings and scheduling links from SavvyCal! | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.51 | 2026-03-31 | [75860](https://github.com/airbytehq/airbyte/pull/75860) | Update dependencies | | 0.0.50 | 2026-03-24 | [75343](https://github.com/airbytehq/airbyte/pull/75343) | Update dependencies | | 0.0.49 | 2026-03-10 | [74692](https://github.com/airbytehq/airbyte/pull/74692) | Update dependencies | | 0.0.48 | 2026-03-03 | [74229](https://github.com/airbytehq/airbyte/pull/74229) | Update dependencies | From 4cbf79669eca2f7166ff06ebc4cf67ddad531d40 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:30:32 +0000 Subject: [PATCH 268/379] =?UTF-8?q?deps(source-wufoo):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75859)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-wufoo/metadata.yaml | 4 ++-- docs/integrations/sources/wufoo.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-wufoo/metadata.yaml b/airbyte-integrations/connectors/source-wufoo/metadata.yaml index 6e0599a9ed38..decedb3c7133 100644 --- a/airbyte-integrations/connectors/source-wufoo/metadata.yaml +++ b/airbyte-integrations/connectors/source-wufoo/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-wufoo connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 2e5fb207-5215-43ee-8b4f-88f6490e204e - dockerImageTag: 0.0.49 + dockerImageTag: 0.0.50 dockerRepository: airbyte/source-wufoo githubIssueLabel: source-wufoo icon: icon.svg diff --git a/docs/integrations/sources/wufoo.md b/docs/integrations/sources/wufoo.md index 8f655200b738..458760556ec5 100644 --- a/docs/integrations/sources/wufoo.md +++ b/docs/integrations/sources/wufoo.md @@ -28,6 +28,7 @@ The Airbyte connector for [Wufoo](https://www.wufoo.com/) enables seamless data | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.50 | 2026-03-31 | [75859](https://github.com/airbytehq/airbyte/pull/75859) | Update dependencies | | 0.0.49 | 2026-03-24 | [75373](https://github.com/airbytehq/airbyte/pull/75373) | Update dependencies | | 0.0.48 | 2026-03-10 | [74669](https://github.com/airbytehq/airbyte/pull/74669) | Update dependencies | | 0.0.47 | 2026-03-03 | [74158](https://github.com/airbytehq/airbyte/pull/74158) | Update dependencies | From 81ca620afebd55a87d03a0077f70b00e56da411d Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:30:38 +0000 Subject: [PATCH 269/379] =?UTF-8?q?deps(source-zendesk-chat):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75858)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-zendesk-chat/metadata.yaml | 4 ++-- docs/integrations/sources/zendesk-chat.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-zendesk-chat/metadata.yaml b/airbyte-integrations/connectors/source-zendesk-chat/metadata.yaml index 066cbb1e3e4f..4506e3bf3501 100644 --- a/airbyte-integrations/connectors/source-zendesk-chat/metadata.yaml +++ b/airbyte-integrations/connectors/source-zendesk-chat/metadata.yaml @@ -6,11 +6,11 @@ data: hosts: - "*.zendesk.com" connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 40d24d0f-b8f9-4fe0-9e6c-b06c0f3f45e4 - dockerImageTag: 1.3.7 + dockerImageTag: 1.3.8 dockerRepository: airbyte/source-zendesk-chat documentationUrl: https://docs.airbyte.com/integrations/sources/zendesk-chat externalDocumentationUrls: diff --git a/docs/integrations/sources/zendesk-chat.md b/docs/integrations/sources/zendesk-chat.md index 22d3fb36e8e8..6acb362a937f 100644 --- a/docs/integrations/sources/zendesk-chat.md +++ b/docs/integrations/sources/zendesk-chat.md @@ -84,6 +84,7 @@ The Zendesk Chat API enforces a rate limit of [200 requests per minute](https:// | Version | Date | Pull Request | Subject | |:--------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 1.3.8 | 2026-03-31 | [75858](https://github.com/airbytehq/airbyte/pull/75858) | Update dependencies | | 1.3.7 | 2026-03-17 | [74324](https://github.com/airbytehq/airbyte/pull/74324) | Migrate to scopes object array format | | 1.3.6 | 2026-03-17 | [75116](https://github.com/airbytehq/airbyte/pull/75116) | Update dependencies | | 1.3.5 | 2026-03-10 | [74671](https://github.com/airbytehq/airbyte/pull/74671) | Update dependencies | From fb945d024deeefc7c28d8ae59389a0f75495007d Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:30:44 +0000 Subject: [PATCH 270/379] =?UTF-8?q?deps(source-scryfall):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75857)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-scryfall/metadata.yaml | 4 ++-- docs/integrations/sources/scryfall.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-scryfall/metadata.yaml b/airbyte-integrations/connectors/source-scryfall/metadata.yaml index a4fdd5b0dc3d..bd22665df04a 100644 --- a/airbyte-integrations/connectors/source-scryfall/metadata.yaml +++ b/airbyte-integrations/connectors/source-scryfall/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-scryfall connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: f76b7649-322b-44a0-8cef-23aeaae89c42 - dockerImageTag: 0.0.47 + dockerImageTag: 0.0.48 dockerRepository: airbyte/source-scryfall githubIssueLabel: source-scryfall icon: icon.svg diff --git a/docs/integrations/sources/scryfall.md b/docs/integrations/sources/scryfall.md index cb78a7a3beec..5af49f8aa1b5 100644 --- a/docs/integrations/sources/scryfall.md +++ b/docs/integrations/sources/scryfall.md @@ -20,6 +20,7 @@ For Magic The Gathering fans. Here is a simple data source for all the cards and | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.48 | 2026-03-31 | [75857](https://github.com/airbytehq/airbyte/pull/75857) | Update dependencies | | 0.0.47 | 2026-03-17 | [74963](https://github.com/airbytehq/airbyte/pull/74963) | Update dependencies | | 0.0.46 | 2026-02-24 | [73747](https://github.com/airbytehq/airbyte/pull/73747) | Update dependencies | | 0.0.45 | 2026-02-03 | [72553](https://github.com/airbytehq/airbyte/pull/72553) | Update dependencies | From 54996dd06e5b3953e27f1de2de7fe1b7aed2f313 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:30:51 +0000 Subject: [PATCH 271/379] =?UTF-8?q?deps(source-pylon):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75855)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-pylon/metadata.yaml | 4 ++-- docs/integrations/sources/pylon.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-pylon/metadata.yaml b/airbyte-integrations/connectors/source-pylon/metadata.yaml index b918c933d7dc..c652556b5fc9 100644 --- a/airbyte-integrations/connectors/source-pylon/metadata.yaml +++ b/airbyte-integrations/connectors/source-pylon/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-pylon connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: f2e53e88-3c6b-4e5a-b7c2-a1d9c5e8f4b6 - dockerImageTag: 0.0.4 + dockerImageTag: 0.0.5 dockerRepository: airbyte/source-pylon githubIssueLabel: source-pylon icon: icon.svg diff --git a/docs/integrations/sources/pylon.md b/docs/integrations/sources/pylon.md index a7e2d50bfc5a..13fa07643a3d 100644 --- a/docs/integrations/sources/pylon.md +++ b/docs/integrations/sources/pylon.md @@ -73,6 +73,7 @@ The Pylon API enforces per-endpoint rate limits. The Issues endpoint allows 10 r | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :----------------------------- | +| 0.0.5 | 2026-03-31 | [75855](https://github.com/airbytehq/airbyte/pull/75855) | Update dependencies | | 0.0.4 | 2026-03-17 | [74921](https://github.com/airbytehq/airbyte/pull/74921) | Update dependencies | | 0.0.3 | 2026-02-24 | [73850](https://github.com/airbytehq/airbyte/pull/73850) | Update dependencies | | 0.0.2 | 2026-02-20 | [73693](https://github.com/airbytehq/airbyte/pull/73693) | Make start_date optional, default to 1 month ago | From 4237b4f5d6cbf2662dafda3df905a34f5332f89b Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:30:59 +0000 Subject: [PATCH 272/379] =?UTF-8?q?deps(source-retailexpress-by-maropost):?= =?UTF-8?q?=20=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#7585?= =?UTF-8?q?4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-retailexpress-by-maropost/metadata.yaml | 4 ++-- docs/integrations/sources/retailexpress-by-maropost.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-retailexpress-by-maropost/metadata.yaml b/airbyte-integrations/connectors/source-retailexpress-by-maropost/metadata.yaml index 215f2aedf65f..b1cc2e16cffb 100644 --- a/airbyte-integrations/connectors/source-retailexpress-by-maropost/metadata.yaml +++ b/airbyte-integrations/connectors/source-retailexpress-by-maropost/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-retailexpress-by-maropost connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 73c01e46-6b1d-434f-8f15-b9a0e67c8999 - dockerImageTag: 0.0.38 + dockerImageTag: 0.0.39 dockerRepository: airbyte/source-retailexpress-by-maropost githubIssueLabel: source-retailexpress-by-maropost icon: icon.svg diff --git a/docs/integrations/sources/retailexpress-by-maropost.md b/docs/integrations/sources/retailexpress-by-maropost.md index 7efa9f585cf7..0e1f6fd3b53b 100644 --- a/docs/integrations/sources/retailexpress-by-maropost.md +++ b/docs/integrations/sources/retailexpress-by-maropost.md @@ -108,6 +108,7 @@ It is unclear what populates this API and the sandbox environment does not provi | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.39 | 2026-03-31 | [75854](https://github.com/airbytehq/airbyte/pull/75854) | Update dependencies | | 0.0.38 | 2026-03-24 | [74972](https://github.com/airbytehq/airbyte/pull/74972) | Update dependencies | | 0.0.37 | 2026-03-10 | [74697](https://github.com/airbytehq/airbyte/pull/74697) | Update dependencies | | 0.0.36 | 2026-03-03 | [74234](https://github.com/airbytehq/airbyte/pull/74234) | Update dependencies | From 7866de67bc44b034c40235b0716a4d0474086fbf Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:31:06 +0000 Subject: [PATCH 273/379] =?UTF-8?q?deps(source-woocommerce):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75853)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-woocommerce/metadata.yaml | 4 ++-- docs/integrations/sources/woocommerce.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-woocommerce/metadata.yaml b/airbyte-integrations/connectors/source-woocommerce/metadata.yaml index f0802118f78c..c7c59b950e7d 100644 --- a/airbyte-integrations/connectors/source-woocommerce/metadata.yaml +++ b/airbyte-integrations/connectors/source-woocommerce/metadata.yaml @@ -8,7 +8,7 @@ data: connectorSubtype: api connectorType: source definitionId: 2a2552ca-9f78-4c1c-9eb7-4d0dc66d72df - dockerImageTag: 0.5.33 + dockerImageTag: 0.5.34 dockerRepository: airbyte/source-woocommerce documentationUrl: https://docs.airbyte.com/integrations/sources/woocommerce githubIssueLabel: source-woocommerce @@ -49,7 +49,7 @@ data: type: GSM alias: airbyte-connector-testing-secret-store connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e externalDocumentationUrls: - title: WooCommerce REST API url: https://woocommerce.github.io/woocommerce-rest-api-docs/ diff --git a/docs/integrations/sources/woocommerce.md b/docs/integrations/sources/woocommerce.md index c9698052197c..026db987a3a5 100644 --- a/docs/integrations/sources/woocommerce.md +++ b/docs/integrations/sources/woocommerce.md @@ -122,6 +122,7 @@ maximum number of seconds between API calls. | Version | Date | Pull Request | Subject | |:--------| :--------- |:---------------------------------------------------------|:-----------------------------------------------------------------------| +| 0.5.34 | 2026-03-31 | [75853](https://github.com/airbytehq/airbyte/pull/75853) | Update dependencies | | 0.5.33 | 2026-03-24 | [75380](https://github.com/airbytehq/airbyte/pull/75380) | Update dependencies | | 0.5.32 | 2026-03-10 | [74674](https://github.com/airbytehq/airbyte/pull/74674) | Update dependencies | | 0.5.31 | 2026-02-24 | [73889](https://github.com/airbytehq/airbyte/pull/73889) | Update dependencies | From 71847995b8c442e65f221a74314addbba0b580db Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:31:13 +0000 Subject: [PATCH 274/379] =?UTF-8?q?deps(source-rootly):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75852)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-rootly/metadata.yaml | 4 ++-- docs/integrations/sources/rootly.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-rootly/metadata.yaml b/airbyte-integrations/connectors/source-rootly/metadata.yaml index 61db58978f4e..540c2004271f 100644 --- a/airbyte-integrations/connectors/source-rootly/metadata.yaml +++ b/airbyte-integrations/connectors/source-rootly/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-rootly connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 2f111b00-0b92-4329-8481-6d7aa27a3991 - dockerImageTag: 0.0.50 + dockerImageTag: 0.0.51 dockerRepository: airbyte/source-rootly githubIssueLabel: source-rootly icon: icon.svg diff --git a/docs/integrations/sources/rootly.md b/docs/integrations/sources/rootly.md index ef607a5c91f3..63c63958eefe 100644 --- a/docs/integrations/sources/rootly.md +++ b/docs/integrations/sources/rootly.md @@ -52,6 +52,7 @@ Documentation: https://rootly.com/api#/ | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.51 | 2026-03-31 | [75852](https://github.com/airbytehq/airbyte/pull/75852) | Update dependencies | | 0.0.50 | 2026-03-17 | [74970](https://github.com/airbytehq/airbyte/pull/74970) | Update dependencies | | 0.0.49 | 2026-03-10 | [74690](https://github.com/airbytehq/airbyte/pull/74690) | Update dependencies | | 0.0.48 | 2026-02-24 | [73742](https://github.com/airbytehq/airbyte/pull/73742) | Update dependencies | From f733be4233794eb3d730e73dd27840fab34e5166 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:31:18 +0000 Subject: [PATCH 275/379] =?UTF-8?q?deps(source-referralhero):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75851)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-referralhero/metadata.yaml | 4 ++-- docs/integrations/sources/referralhero.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-referralhero/metadata.yaml b/airbyte-integrations/connectors/source-referralhero/metadata.yaml index d27a21774ad7..ccfac378e56f 100644 --- a/airbyte-integrations/connectors/source-referralhero/metadata.yaml +++ b/airbyte-integrations/connectors/source-referralhero/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-referralhero connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 4a0df9e1-dadc-4828-a88d-afd8b3c0106d - dockerImageTag: 0.0.38 + dockerImageTag: 0.0.39 dockerRepository: airbyte/source-referralhero githubIssueLabel: source-referralhero icon: icon.svg diff --git a/docs/integrations/sources/referralhero.md b/docs/integrations/sources/referralhero.md index 4d5f927a8225..cce4e578e442 100644 --- a/docs/integrations/sources/referralhero.md +++ b/docs/integrations/sources/referralhero.md @@ -30,6 +30,7 @@ Please follow the instructions in the following [referralhero](https://support.r | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.39 | 2026-03-31 | [75851](https://github.com/airbytehq/airbyte/pull/75851) | Update dependencies | | 0.0.38 | 2026-03-17 | [74928](https://github.com/airbytehq/airbyte/pull/74928) | Update dependencies | | 0.0.37 | 2026-03-10 | [74614](https://github.com/airbytehq/airbyte/pull/74614) | Update dependencies | | 0.0.36 | 2026-03-03 | [73885](https://github.com/airbytehq/airbyte/pull/73885) | Update dependencies | From 5b43d512fb218fe70a3141cb1f94c129c2f43e69 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:31:25 +0000 Subject: [PATCH 276/379] =?UTF-8?q?deps(source-paypal-transaction):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75850)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-paypal-transaction/metadata.yaml | 4 ++-- docs/integrations/sources/paypal-transaction.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-paypal-transaction/metadata.yaml b/airbyte-integrations/connectors/source-paypal-transaction/metadata.yaml index d63b144abc97..f5a5285d6611 100644 --- a/airbyte-integrations/connectors/source-paypal-transaction/metadata.yaml +++ b/airbyte-integrations/connectors/source-paypal-transaction/metadata.yaml @@ -7,11 +7,11 @@ data: - api-m.paypal.com - api-m.sandbox.paypal.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: d913b0f2-cc51-4e55-a44c-8ba1697b9239 - dockerImageTag: 2.6.29 + dockerImageTag: 2.6.30 dockerRepository: airbyte/source-paypal-transaction documentationUrl: https://docs.airbyte.com/integrations/sources/paypal-transaction githubIssueLabel: source-paypal-transaction diff --git a/docs/integrations/sources/paypal-transaction.md b/docs/integrations/sources/paypal-transaction.md index 449c856e17a6..d79ad59fb40c 100644 --- a/docs/integrations/sources/paypal-transaction.md +++ b/docs/integrations/sources/paypal-transaction.md @@ -264,6 +264,7 @@ The below table contains the configuraiton parameters available for this connect | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------- | +| 2.6.30 | 2026-03-31 | [75850](https://github.com/airbytehq/airbyte/pull/75850) | Update dependencies | | 2.6.29 | 2026-03-24 | [75396](https://github.com/airbytehq/airbyte/pull/75396) | Update dependencies | | 2.6.28 | 2026-03-10 | [74484](https://github.com/airbytehq/airbyte/pull/74484) | Update dependencies | | 2.6.27 | 2026-03-03 | [73875](https://github.com/airbytehq/airbyte/pull/73875) | Update dependencies | From b65cc1d4db70b6b4ec514bd5b20f903e2bb7b575 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:31:31 +0000 Subject: [PATCH 277/379] =?UTF-8?q?deps(source-younium):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75849)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-younium/metadata.yaml | 4 ++-- docs/integrations/sources/younium.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-younium/metadata.yaml b/airbyte-integrations/connectors/source-younium/metadata.yaml index 11ab35dc7912..c5e579c0442a 100644 --- a/airbyte-integrations/connectors/source-younium/metadata.yaml +++ b/airbyte-integrations/connectors/source-younium/metadata.yaml @@ -12,11 +12,11 @@ data: # Please update to the latest version of the connector base image. # https://hub.docker.com/r/airbyte/python-connector-base # Please use the full address with sha256 hash to guarantee build reproducibility. - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 9c74c2d7-531a-4ebf-b6d8-6181f805ecdc - dockerImageTag: 0.4.44 + dockerImageTag: 0.4.45 dockerRepository: airbyte/source-younium githubIssueLabel: source-younium icon: younium.svg diff --git a/docs/integrations/sources/younium.md b/docs/integrations/sources/younium.md index 7c02011c605b..a153cb743a86 100644 --- a/docs/integrations/sources/younium.md +++ b/docs/integrations/sources/younium.md @@ -46,6 +46,7 @@ The Younium source connector supports the following [sync modes](https://docs.ai | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :--------------------------------------------------------- | +| 0.4.45 | 2026-03-31 | [75849](https://github.com/airbytehq/airbyte/pull/75849) | Update dependencies | | 0.4.44 | 2026-03-17 | [75095](https://github.com/airbytehq/airbyte/pull/75095) | Update dependencies | | 0.4.43 | 2026-03-10 | [74672](https://github.com/airbytehq/airbyte/pull/74672) | Update dependencies | | 0.4.42 | 2026-03-03 | [73912](https://github.com/airbytehq/airbyte/pull/73912) | Update dependencies | From aa587f7a7c1946db9594b49aab484f612a172c7a Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:31:39 +0000 Subject: [PATCH 278/379] =?UTF-8?q?deps(source-pypi):=20=F0=9F=90=99=20upd?= =?UTF-8?q?ate=20dependencies=20[2026-03-31]=20(#75848)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-pypi/metadata.yaml | 4 ++-- docs/integrations/sources/pypi.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-pypi/metadata.yaml b/airbyte-integrations/connectors/source-pypi/metadata.yaml index a603290fcbe5..9007d23d5ede 100644 --- a/airbyte-integrations/connectors/source-pypi/metadata.yaml +++ b/airbyte-integrations/connectors/source-pypi/metadata.yaml @@ -3,11 +3,11 @@ data: ql: 100 sl: 100 connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 88ecd3a8-5f5b-11ed-9b6a-0242ac120002 - dockerImageTag: 0.2.48 + dockerImageTag: 0.2.49 dockerRepository: airbyte/source-pypi documentationUrl: https://docs.airbyte.com/integrations/sources/pypi githubIssueLabel: source-pypi diff --git a/docs/integrations/sources/pypi.md b/docs/integrations/sources/pypi.md index d2b8c7fe4526..654a7e007c15 100644 --- a/docs/integrations/sources/pypi.md +++ b/docs/integrations/sources/pypi.md @@ -31,6 +31,7 @@ Try not to make a lot of requests (thousands) in a short amount of time (minutes | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------ | +| 0.2.49 | 2026-03-31 | [75848](https://github.com/airbytehq/airbyte/pull/75848) | Update dependencies | | 0.2.48 | 2026-03-17 | [74913](https://github.com/airbytehq/airbyte/pull/74913) | Update dependencies | | 0.2.47 | 2026-03-10 | [74641](https://github.com/airbytehq/airbyte/pull/74641) | Update dependencies | | 0.2.46 | 2026-03-03 | [74211](https://github.com/airbytehq/airbyte/pull/74211) | Update dependencies | From b7abf84e5f62a0d6879256ff9bbcef364fb84ec4 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:31:45 +0000 Subject: [PATCH 279/379] =?UTF-8?q?deps(source-ruddr):=20=F0=9F=90=99=20up?= =?UTF-8?q?date=20dependencies=20[2026-03-31]=20(#75847)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-ruddr/metadata.yaml | 4 ++-- docs/integrations/sources/ruddr.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-ruddr/metadata.yaml b/airbyte-integrations/connectors/source-ruddr/metadata.yaml index 24cc4b2155f7..e0fcbaed5749 100644 --- a/airbyte-integrations/connectors/source-ruddr/metadata.yaml +++ b/airbyte-integrations/connectors/source-ruddr/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-ruddr connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 6e87d8e2-47bc-4a0a-a175-62e2b926bb07 - dockerImageTag: 0.0.43 + dockerImageTag: 0.0.44 dockerRepository: airbyte/source-ruddr githubIssueLabel: source-ruddr icon: icon.svg diff --git a/docs/integrations/sources/ruddr.md b/docs/integrations/sources/ruddr.md index f2b7478c6e25..e0f817c47e8c 100644 --- a/docs/integrations/sources/ruddr.md +++ b/docs/integrations/sources/ruddr.md @@ -31,6 +31,7 @@ Ruddr connector enables seamless data synchronization from Ruddr to various data | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.44 | 2026-03-31 | [75847](https://github.com/airbytehq/airbyte/pull/75847) | Update dependencies | | 0.0.43 | 2026-03-24 | [75341](https://github.com/airbytehq/airbyte/pull/75341) | Update dependencies | | 0.0.42 | 2026-03-10 | [74700](https://github.com/airbytehq/airbyte/pull/74700) | Update dependencies | | 0.0.41 | 2026-02-24 | [73772](https://github.com/airbytehq/airbyte/pull/73772) | Update dependencies | From 7849943cd0749f6ba5f25bceaec084f5bcd6430d Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:31:52 +0000 Subject: [PATCH 280/379] =?UTF-8?q?deps(source-picqer):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75846)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-picqer/metadata.yaml | 4 ++-- docs/integrations/sources/picqer.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-picqer/metadata.yaml b/airbyte-integrations/connectors/source-picqer/metadata.yaml index ea8f2db22ea4..c26733560bbb 100644 --- a/airbyte-integrations/connectors/source-picqer/metadata.yaml +++ b/airbyte-integrations/connectors/source-picqer/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-picqer connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 860ca029-c88c-4c0a-a7d8-08ce6e84729c - dockerImageTag: 0.0.51 + dockerImageTag: 0.0.52 dockerRepository: airbyte/source-picqer githubIssueLabel: source-picqer icon: icon.svg diff --git a/docs/integrations/sources/picqer.md b/docs/integrations/sources/picqer.md index c3b45c6951e9..f0cc00971158 100644 --- a/docs/integrations/sources/picqer.md +++ b/docs/integrations/sources/picqer.md @@ -42,6 +42,7 @@ Configure the API key as your username and leave password field as blank | Version | Date | Pull Request | Subject | | ------------------ | ------------ | --- | ---------------- | +| 0.0.52 | 2026-03-31 | [75846](https://github.com/airbytehq/airbyte/pull/75846) | Update dependencies | | 0.0.51 | 2026-03-17 | [74458](https://github.com/airbytehq/airbyte/pull/74458) | Update dependencies | | 0.0.50 | 2026-03-03 | [73199](https://github.com/airbytehq/airbyte/pull/73199) | Update dependencies | | 0.0.49 | 2026-02-03 | [72648](https://github.com/airbytehq/airbyte/pull/72648) | Update dependencies | From fbeb7e3d9f5830783336827100183ec89cccc545 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:31:59 +0000 Subject: [PATCH 281/379] =?UTF-8?q?deps(source-qualaroo):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75845)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-qualaroo/metadata.yaml | 4 ++-- docs/integrations/sources/qualaroo.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-qualaroo/metadata.yaml b/airbyte-integrations/connectors/source-qualaroo/metadata.yaml index 34075862fe2c..3ca697f95523 100644 --- a/airbyte-integrations/connectors/source-qualaroo/metadata.yaml +++ b/airbyte-integrations/connectors/source-qualaroo/metadata.yaml @@ -14,7 +14,7 @@ data: connectorSubtype: api connectorType: source definitionId: eb655362-28a8-4311-8806-4fcc612734a7 - dockerImageTag: 0.4.42 + dockerImageTag: 0.4.43 dockerRepository: airbyte/source-qualaroo githubIssueLabel: source-qualaroo icon: qualaroo.svg @@ -41,7 +41,7 @@ data: type: GSM alias: airbyte-connector-testing-secret-store connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e externalDocumentationUrls: - title: Qualaroo API documentation url: https://help.qualaroo.com/hc/en-us/articles/201969438-The-Qualaroo-API diff --git a/docs/integrations/sources/qualaroo.md b/docs/integrations/sources/qualaroo.md index 6c0bc2ee7e6f..93dbe85ff992 100644 --- a/docs/integrations/sources/qualaroo.md +++ b/docs/integrations/sources/qualaroo.md @@ -46,6 +46,7 @@ Please read [How to get your APIs Token and Key](https://help.qualaroo.com/hc/en | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------------------------------------------------- | +| 0.4.43 | 2026-03-31 | [75845](https://github.com/airbytehq/airbyte/pull/75845) | Update dependencies | | 0.4.42 | 2026-03-17 | [74954](https://github.com/airbytehq/airbyte/pull/74954) | Update dependencies | | 0.4.41 | 2026-03-10 | [74645](https://github.com/airbytehq/airbyte/pull/74645) | Update dependencies | | 0.4.40 | 2026-02-24 | [73842](https://github.com/airbytehq/airbyte/pull/73842) | Update dependencies | From 6e8e23dfea3ea680b2c3aea6d632a24655a1b6bc Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:32:07 +0000 Subject: [PATCH 282/379] =?UTF-8?q?deps(source-planhat):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75844)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-planhat/metadata.yaml | 4 ++-- docs/integrations/sources/planhat.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-planhat/metadata.yaml b/airbyte-integrations/connectors/source-planhat/metadata.yaml index f993ac80ed40..2ec81d66e101 100644 --- a/airbyte-integrations/connectors/source-planhat/metadata.yaml +++ b/airbyte-integrations/connectors/source-planhat/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-planhat connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 03fdd212-bd09-4e7b-b472-5b8f1b73969b - dockerImageTag: 0.0.51 + dockerImageTag: 0.0.52 dockerRepository: airbyte/source-planhat githubIssueLabel: source-planhat icon: icon.svg diff --git a/docs/integrations/sources/planhat.md b/docs/integrations/sources/planhat.md index 9d125a7dce26..c32c93560426 100644 --- a/docs/integrations/sources/planhat.md +++ b/docs/integrations/sources/planhat.md @@ -54,6 +54,7 @@ This Source is capable of syncing the following core Streams: | Version | Date | Pull Request | Subject | | ------- | ---------- | ------------ | ---------------------------------------------------- | +| 0.0.52 | 2026-03-31 | [75844](https://github.com/airbytehq/airbyte/pull/75844) | Update dependencies | | 0.0.51 | 2026-03-17 | [75025](https://github.com/airbytehq/airbyte/pull/75025) | Update dependencies | | 0.0.50 | 2026-03-03 | [73878](https://github.com/airbytehq/airbyte/pull/73878) | Update dependencies | | 0.0.49 | 2026-02-17 | [73195](https://github.com/airbytehq/airbyte/pull/73195) | Update dependencies | From 39a3b8357afd5e8c530f245889ea5dd028ff85f8 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:32:13 +0000 Subject: [PATCH 283/379] =?UTF-8?q?deps(source-pretix):=20=F0=9F=90=99=20u?= =?UTF-8?q?pdate=20dependencies=20[2026-03-31]=20(#75843)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-pretix/metadata.yaml | 4 ++-- docs/integrations/sources/pretix.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-pretix/metadata.yaml b/airbyte-integrations/connectors/source-pretix/metadata.yaml index cdbba86fadac..0c0003e0dcc1 100644 --- a/airbyte-integrations/connectors/source-pretix/metadata.yaml +++ b/airbyte-integrations/connectors/source-pretix/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-pretix connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: c32e6012-96cf-45f7-8c09-ac9a32484d96 - dockerImageTag: 0.0.51 + dockerImageTag: 0.0.52 dockerRepository: airbyte/source-pretix githubIssueLabel: source-pretix icon: icon.svg diff --git a/docs/integrations/sources/pretix.md b/docs/integrations/sources/pretix.md index 68d3bcefc3c0..56cbf094b5d6 100644 --- a/docs/integrations/sources/pretix.md +++ b/docs/integrations/sources/pretix.md @@ -41,6 +41,7 @@ | Version | Date | Pull Request | Subject | |---------|-------------------|--------------|----------------| +| 0.0.52 | 2026-03-31 | [75843](https://github.com/airbytehq/airbyte/pull/75843) | Update dependencies | | 0.0.51 | 2026-03-17 | [74925](https://github.com/airbytehq/airbyte/pull/74925) | Update dependencies | | 0.0.50 | 2026-03-10 | [74618](https://github.com/airbytehq/airbyte/pull/74618) | Update dependencies | | 0.0.49 | 2026-03-03 | [74210](https://github.com/airbytehq/airbyte/pull/74210) | Update dependencies | From dcce73934af6961d764b558ffd2a4368bae51e80 Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:34:36 +0000 Subject: [PATCH 284/379] =?UTF-8?q?deps(source-paystack):=20=F0=9F=90=99?= =?UTF-8?q?=20update=20dependencies=20[2026-03-31]=20(#75842)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-paystack/metadata.yaml | 4 ++-- docs/integrations/sources/paystack.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-paystack/metadata.yaml b/airbyte-integrations/connectors/source-paystack/metadata.yaml index 2740c1b4692f..dfb0d56a6243 100644 --- a/airbyte-integrations/connectors/source-paystack/metadata.yaml +++ b/airbyte-integrations/connectors/source-paystack/metadata.yaml @@ -5,7 +5,7 @@ data: connectorSubtype: api connectorType: source definitionId: 193bdcb8-1dd9-48d1-aade-91cadfd74f9b - dockerImageTag: 1.1.27 + dockerImageTag: 1.1.28 dockerRepository: airbyte/source-paystack githubIssueLabel: source-paystack icon: paystack.svg @@ -51,7 +51,7 @@ data: type: GSM alias: airbyte-connector-testing-secret-store connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e externalDocumentationUrls: - title: Paystack API reference url: https://paystack.com/docs/api/ diff --git a/docs/integrations/sources/paystack.md b/docs/integrations/sources/paystack.md index 5fa6b4efb1dc..00ae3f5a3536 100644 --- a/docs/integrations/sources/paystack.md +++ b/docs/integrations/sources/paystack.md @@ -68,6 +68,7 @@ The Paystack connector should not run into Paystack API limitations under normal | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :------------------------------------------------------------- | +| 1.1.28 | 2026-03-31 | [75842](https://github.com/airbytehq/airbyte/pull/75842) | Update dependencies | | 1.1.27 | 2026-03-24 | [75399](https://github.com/airbytehq/airbyte/pull/75399) | Update dependencies | | 1.1.26 | 2026-03-10 | [74504](https://github.com/airbytehq/airbyte/pull/74504) | Update dependencies | | 1.1.25 | 2026-02-24 | [73876](https://github.com/airbytehq/airbyte/pull/73876) | Update dependencies | From e5978cd0c5151177a8437486c182df49665ce1bd Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:35:16 +0000 Subject: [PATCH 285/379] =?UTF-8?q?deps(source-rollbar):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#75348)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-rollbar/metadata.yaml | 4 ++-- docs/integrations/sources/rollbar.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-rollbar/metadata.yaml b/airbyte-integrations/connectors/source-rollbar/metadata.yaml index e783e0877f05..fe584e288b8d 100644 --- a/airbyte-integrations/connectors/source-rollbar/metadata.yaml +++ b/airbyte-integrations/connectors/source-rollbar/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-rollbar connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.10.1@sha256:bd69f6b52bdd92ce06c30786d67546427b828ffb553363c8950b2816c552d6e0 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: 8d518856-6bfa-4d92-80ca-796b0338e341 - dockerImageTag: 0.0.45 + dockerImageTag: 0.0.46 dockerRepository: airbyte/source-rollbar githubIssueLabel: source-rollbar icon: icon.svg diff --git a/docs/integrations/sources/rollbar.md b/docs/integrations/sources/rollbar.md index 17ec91d7d5f1..df9516abee50 100644 --- a/docs/integrations/sources/rollbar.md +++ b/docs/integrations/sources/rollbar.md @@ -36,6 +36,7 @@ Follow [this guide](https://docs.rollbar.com/reference/getting-started-1#authent | Version | Date | Pull Request | Subject | |---------|------|--------------|---------| +| 0.0.46 | 2026-03-31 | [75348](https://github.com/airbytehq/airbyte/pull/75348) | Update dependencies | | 0.0.45 | 2026-02-24 | [73181](https://github.com/airbytehq/airbyte/pull/73181) | Update dependencies | | 0.0.44 | 2026-02-03 | [72569](https://github.com/airbytehq/airbyte/pull/72569) | Update dependencies | | 0.0.43 | 2026-01-20 | [72151](https://github.com/airbytehq/airbyte/pull/72151) | Update dependencies | From 76f3333e0e494acd6efca1a4baf53a2408a06f0c Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:35:26 +0000 Subject: [PATCH 286/379] =?UTF-8?q?deps(source-sage-hr):=20=F0=9F=90=99=20?= =?UTF-8?q?update=20dependencies=20[2026-03-31]=20(#74967)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-sage-hr/metadata.yaml | 4 ++-- docs/integrations/sources/sage-hr.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-sage-hr/metadata.yaml b/airbyte-integrations/connectors/source-sage-hr/metadata.yaml index 53aabbb43d59..53f27ce1b483 100644 --- a/airbyte-integrations/connectors/source-sage-hr/metadata.yaml +++ b/airbyte-integrations/connectors/source-sage-hr/metadata.yaml @@ -13,11 +13,11 @@ data: enabled: false packageName: airbyte-source-sage-hr connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.10.4@sha256:2f551a3fb5d580b34f4253aa1904d26c309364b09538f0b0fef3d8a98546f795 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: d8384215-9de6-4268-bbea-40c636ee14c7 - dockerImageTag: 0.0.51 + dockerImageTag: 0.0.52 dockerRepository: airbyte/source-sage-hr githubIssueLabel: source-sage-hr icon: icon.svg diff --git a/docs/integrations/sources/sage-hr.md b/docs/integrations/sources/sage-hr.md index 21beb6ec0b3b..29913cab280e 100644 --- a/docs/integrations/sources/sage-hr.md +++ b/docs/integrations/sources/sage-hr.md @@ -31,6 +31,7 @@ The Sage HR Airbyte Connector enables seamless data integration, allowing you to | Version | Date | Pull Request | Subject | |------------------|-------------------|--------------|----------------| +| 0.0.52 | 2026-03-31 | [74967](https://github.com/airbytehq/airbyte/pull/74967) | Update dependencies | | 0.0.51 | 2026-03-10 | [74676](https://github.com/airbytehq/airbyte/pull/74676) | Update dependencies | | 0.0.50 | 2026-02-24 | [73484](https://github.com/airbytehq/airbyte/pull/73484) | Update dependencies | | 0.0.49 | 2026-02-10 | [73182](https://github.com/airbytehq/airbyte/pull/73182) | Update dependencies | From db30e2d44ac3f1b0d04ee98b1436d0c5f5a7e88a Mon Sep 17 00:00:00 2001 From: Daryna Ishchenko Date: Tue, 31 Mar 2026 14:47:46 +0300 Subject: [PATCH 287/379] chore(source-amplitude): upgrade CDK to v7.14.0, use weight-based rate limiting for Dashboard REST API (#75406) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Aaron ("AJ") Steers --- .../connectors/source-amplitude/manifest.yaml | 62 +++++++++++++++---- .../connectors/source-amplitude/metadata.yaml | 4 +- docs/integrations/sources/amplitude.md | 1 + 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/airbyte-integrations/connectors/source-amplitude/manifest.yaml b/airbyte-integrations/connectors/source-amplitude/manifest.yaml index 708798fbe2ec..a47d728a8995 100644 --- a/airbyte-integrations/connectors/source-amplitude/manifest.yaml +++ b/airbyte-integrations/connectors/source-amplitude/manifest.yaml @@ -1040,11 +1040,35 @@ spec: According to Amplitude documentation, grouping by `Country` is optional. If you face issues fetching the stream or checking the connection please set this field to `False`. default: true -# Amplitude API rate limits: -# - Dashboard REST API: 5 concurrent requests, 108,000 cost/hour -# - Export API: No explicit rate limits documented, but large exports may timeout -# See: https://amplitude.com/docs/apis/analytics/dashboard-rest#rate-limits -# Using conservative limits to avoid rate limiting issues +# Amplitude API rate limits (see https://amplitude.com/docs/apis/analytics/dashboard-rest#rate-limits): +# +# Dashboard REST API has three limits: +# 1. Concurrent requests: 5 simultaneous requests across all Dashboard REST API endpoints. +# Enforced via concurrency_level below (CDK doesn't support per-endpoint concurrency in api_budget). +# 2. Burst limit: 1,000 cost per 5-minute window. +# Note: Amplitude docs label this "Concurrent Limit" but it functions as a short-term rate limit +# (cost budget over a time window), not a true concurrency constraint. +# 3. Hourly limit: 108,000 cost per hour. +# +# Cost formula: (# of days) * (# of conditions) * (query type cost) +# +# Export API: No explicit rate limits documented, but large exports may timeout. +# Chart Annotations & Behavioral Cohorts APIs: No separate rate limits documented. +# +# Per-stream cost estimates (based on connector's slice sizes and query parameters): +# /2/sessions/average (average_session_length): 15 days * 1 condition * 4 (User Sessions) = 60 cost/request +# /2/users (active_users, group_by=country): 30 days * 4 (group-by) * 1 = 120 cost/request +# /2/users (active_users, no group-by): 30 days * 1 * 1 = 30 cost/request +# /2/events/list (events_list): full refresh, no date range, cost = 1 +# +# Note: /2/events/list is not given a specific policy because its cost is trivially low (1 per request) +# and it only makes a single request per sync (full refresh, no date slicing). +# Other endpoints (annotations, cohorts, export) have no documented rate limits from Amplitude. +# +# Both endpoints share Amplitude's budget. With CDK v7.14.0+ weight-based rate limiting, +# each matcher specifies its per-request weight (cost), and the policy limits are set to +# Amplitude's actual budgets. The CDK deducts the matched weight from the shared budget +# on each request, accurately tracking cost consumption across endpoints. concurrency_level: type: ConcurrencyLevel default_concurrency: 5 @@ -1052,9 +1076,25 @@ concurrency_level: api_budget: type: HTTPAPIBudget policies: - - type: FixedWindowCallRatePolicy - period: PT1M - # Conservative limit based on Amplitude's concurrent request limit - # Amplitude allows 5 concurrent requests for Dashboard REST API - call_limit: 60 - matchers: [] + # Shared Dashboard REST API budget using Amplitude's actual cost limits. + # Each matcher specifies a weight equal to the per-request cost for that endpoint. + # The CDK deducts the matched weight from the shared budget on each request. + - type: MovingWindowCallRatePolicy + rates: + - limit: 108000 + interval: PT1H + - limit: 1000 + interval: PT5M + matchers: + # /2/sessions/average: 15 days * 1 condition * 4 (User Sessions query type) = 60 cost/request + - type: HttpRequestRegexMatcher + method: GET + url_path_pattern: "/2/sessions/average" + weight: 60 + # /2/users: cost depends on active_users_group_by_country config: + # group_by=true (default): 30 days * 4 (group-by segments) * 1 = 120 cost/request + # group_by=false: 30 days * 1 * 1 = 30 cost/request + - type: HttpRequestRegexMatcher + method: GET + url_path_pattern: "/2/users" + weight: "{{ 120 if config.get('active_users_group_by_country', true) else 30 }}" diff --git a/airbyte-integrations/connectors/source-amplitude/metadata.yaml b/airbyte-integrations/connectors/source-amplitude/metadata.yaml index 00dc2e07c64f..c2b5e0a77ebe 100644 --- a/airbyte-integrations/connectors/source-amplitude/metadata.yaml +++ b/airbyte-integrations/connectors/source-amplitude/metadata.yaml @@ -7,11 +7,11 @@ data: - amplitude.com - analytics.eu.amplitude.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.6.5@sha256:a5ef859b9f6dde52bd914fbcddb088d4f1ccae4887ffb58b2282b80f119fdcbe + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: fa9f58c6-2d03-4237-aaa4-07d75e0c1396 - dockerImageTag: 0.7.29 + dockerImageTag: 0.7.30 dockerRepository: airbyte/source-amplitude documentationUrl: https://docs.airbyte.com/integrations/sources/amplitude githubIssueLabel: source-amplitude diff --git a/docs/integrations/sources/amplitude.md b/docs/integrations/sources/amplitude.md index 464170027cda..b38a1c827d1f 100644 --- a/docs/integrations/sources/amplitude.md +++ b/docs/integrations/sources/amplitude.md @@ -58,6 +58,7 @@ The Amplitude connector ideally should gracefully handle Amplitude API limitatio | Version | Date | Pull Request | Subject | |:-----------|:-----------| :------------------------------------------------------- |:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0.7.30 | 2026-03-31 | [75406](https://github.com/airbytehq/airbyte/pull/75406) | Upgrade CDK to v7.14.0 and use weight-based rate limiting for Dashboard REST API streams | | 0.7.29 | 2026-03-02 | [70841](https://github.com/airbytehq/airbyte/pull/70841) | feat(source-amplitude): Add HTTPAPIBudget and concurrency_level (AI-Triage PR) | | 0.7.28 | 2026-01-20 | [71912](https://github.com/airbytehq/airbyte/pull/71912) | Update dependencies | | 0.7.27 | 2026-01-14 | [71434](https://github.com/airbytehq/airbyte/pull/71434) | Update dependencies | From cfbda7ad825a821f523143f39686505e9e0ae82c Mon Sep 17 00:00:00 2001 From: "octavia-bot-hoard[bot]" <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 12:26:23 +0000 Subject: [PATCH 288/379] =?UTF-8?q?deps(source-microsoft-teams):=20?= =?UTF-8?q?=F0=9F=90=99=20update=20dependencies=20[2026-03-31]=20(#75805)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: octavia-bot-hoard[bot] <230633153+octavia-bot-hoard[bot]@users.noreply.github.com> --- .../connectors/source-microsoft-teams/metadata.yaml | 4 ++-- docs/integrations/sources/microsoft-teams.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-microsoft-teams/metadata.yaml b/airbyte-integrations/connectors/source-microsoft-teams/metadata.yaml index 3a5141171cc9..265228aa2f63 100644 --- a/airbyte-integrations/connectors/source-microsoft-teams/metadata.yaml +++ b/airbyte-integrations/connectors/source-microsoft-teams/metadata.yaml @@ -15,11 +15,11 @@ data: # Please update to the latest version of the connector base image. # https://hub.docker.com/r/airbyte/python-connector-base # Please use the full address with sha256 hash to guarantee build reproducibility. - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0@sha256:949b0f3efefbd66e6222f279f36b2fb1c796b06e0e712b1a80124b49769862c4 + baseImage: docker.io/airbyte/source-declarative-manifest:7.14.0@sha256:5b95dd9e71defeece4a1efb27688b15e482f18c82c745498611846466b72403e connectorSubtype: api connectorType: source definitionId: eaf50f04-21dd-4620-913b-2a83f5635227 - dockerImageTag: 1.2.14 + dockerImageTag: 1.2.15 dockerRepository: airbyte/source-microsoft-teams githubIssueLabel: source-microsoft-teams icon: microsoft-teams.svg diff --git a/docs/integrations/sources/microsoft-teams.md b/docs/integrations/sources/microsoft-teams.md index 06b02183c756..72b18861f202 100644 --- a/docs/integrations/sources/microsoft-teams.md +++ b/docs/integrations/sources/microsoft-teams.md @@ -164,6 +164,7 @@ Token acquiring implemented by [instantiate](https://docs.microsoft.com/en-us/az | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :----------------------------- | +| 1.2.15 | 2026-03-31 | [75805](https://github.com/airbytehq/airbyte/pull/75805) | Update dependencies | | 1.2.14 | 2026-03-17 | [74567](https://github.com/airbytehq/airbyte/pull/74567) | Update dependencies | | 1.2.13 | 2026-03-03 | [73414](https://github.com/airbytehq/airbyte/pull/73414) | Update dependencies | | 1.2.12 | 2026-02-10 | [73207](https://github.com/airbytehq/airbyte/pull/73207) | Update dependencies | From cb501d3ccbced9cab93ce4679878bce0753c1144 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Tue, 31 Mar 2026 10:52:43 -0500 Subject: [PATCH 289/379] deps(source-typeform): update CDK to 7.15.0 (#75898) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-typeform/metadata.yaml | 4 ++-- docs/integrations/sources/typeform.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-typeform/metadata.yaml b/airbyte-integrations/connectors/source-typeform/metadata.yaml index 808a7b46682e..6a305cd804fd 100644 --- a/airbyte-integrations/connectors/source-typeform/metadata.yaml +++ b/airbyte-integrations/connectors/source-typeform/metadata.yaml @@ -6,11 +6,11 @@ data: hosts: - api.typeform.com connectorBuildOptions: - baseImage: docker.io/airbyte/source-declarative-manifest:7.13.0.post30.dev23303933335@sha256:266dda691d2928e00adc6401ac43823be107b5ae39364047ce03d4031c95e1cd + baseImage: docker.io/airbyte/source-declarative-manifest:7.15.0@sha256:eecde84a1c8efced5b35f04900ed983eb306028d262cdb0673f26526aaabd7fc connectorSubtype: api connectorType: source definitionId: e7eff203-90bf-43e5-a240-19ea3056c474 - dockerImageTag: 1.4.7-rc.1 + dockerImageTag: 1.4.7-rc.2 dockerRepository: airbyte/source-typeform documentationUrl: https://docs.airbyte.com/integrations/sources/typeform externalDocumentationUrls: diff --git a/docs/integrations/sources/typeform.md b/docs/integrations/sources/typeform.md index 9440fabdf7e2..d02ec0c5dbb8 100644 --- a/docs/integrations/sources/typeform.md +++ b/docs/integrations/sources/typeform.md @@ -99,6 +99,7 @@ The connector makes an additional API call per sync to fetch the list of form ID | Version | Date | Pull Request | Subject | |:--------|:-----------|:---------------------------------------------------------|:------------------------------------------------------------------------------------------------| +| 1.4.7-rc.2 | 2026-03-31 | [75898](https://github.com/airbytehq/airbyte/pull/75898) | Update CDK to 7.15.0 | | 1.4.7-rc.1 | 2026-03-26 | [75506](https://github.com/airbytehq/airbyte/pull/75506) | Upgrade CDK version to 7.13.0 | | 1.4.6 | 2026-03-03 | [61473](https://github.com/airbytehq/airbyte/pull/61473) | Update dependencies | | 1.4.5 | 2026-01-22 | [72261](https://github.com/airbytehq/airbyte/pull/72261) | Update CDK version from 7.0.1 to 7.6.5 | From 96192f9aef09d97ee5939bf56dcc82bc67682e36 Mon Sep 17 00:00:00 2001 From: Serhii Lazebnyi Date: Tue, 31 Mar 2026 17:24:37 +0100 Subject: [PATCH 290/379] feat(source-salesforce): add oauth_connector_input_specification for declarative OAuth (#75579) --- .../connectors/source-salesforce/metadata.yaml | 2 +- .../connectors/source-salesforce/pyproject.toml | 2 +- .../source-salesforce/source_salesforce/spec.yaml | 13 +++++++++++++ docs/integrations/sources/salesforce.md | 1 + 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-salesforce/metadata.yaml b/airbyte-integrations/connectors/source-salesforce/metadata.yaml index 41e583a46089..b36d12d4fb30 100644 --- a/airbyte-integrations/connectors/source-salesforce/metadata.yaml +++ b/airbyte-integrations/connectors/source-salesforce/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: api connectorType: source definitionId: b117307c-14b6-41aa-9422-947e34922962 - dockerImageTag: 2.7.18 + dockerImageTag: 2.7.19 releases: rolloutConfiguration: enableProgressiveRollout: false diff --git a/airbyte-integrations/connectors/source-salesforce/pyproject.toml b/airbyte-integrations/connectors/source-salesforce/pyproject.toml index d1978478f2b3..9aa8fe0b0d9a 100644 --- a/airbyte-integrations/connectors/source-salesforce/pyproject.toml +++ b/airbyte-integrations/connectors/source-salesforce/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "2.7.18" +version = "2.7.19" name = "source-salesforce" description = "Source implementation for Salesforce." authors = [ "Airbyte ",] diff --git a/airbyte-integrations/connectors/source-salesforce/source_salesforce/spec.yaml b/airbyte-integrations/connectors/source-salesforce/source_salesforce/spec.yaml index 76740e6492fd..dacc42bb3ad8 100644 --- a/airbyte-integrations/connectors/source-salesforce/source_salesforce/spec.yaml +++ b/airbyte-integrations/connectors/source-salesforce/source_salesforce/spec.yaml @@ -123,6 +123,19 @@ advanced_auth: - auth_type predicate_value: Client oauth_config_specification: + oauth_connector_input_specification: + consent_url: "https://{% if is_sandbox %}test{% else %}login{% endif %}.salesforce.com/services/oauth2/authorize?{{client_id_param}}&{{redirect_uri_param}}&response_type=code&{{state_param}}" + access_token_url: "https://{% if is_sandbox %}test{% else %}login{% endif %}.salesforce.com/services/oauth2/token" + access_token_headers: + Content-Type: "application/x-www-form-urlencoded" + access_token_params: + grant_type: "authorization_code" + code: "{{ auth_code_value }}" + client_id: "{{ client_id_value }}" + client_secret: "{{ client_secret_value }}" + redirect_uri: "{{ redirect_uri_value }}" + extract_output: + - refresh_token oauth_user_input_from_connector_config_specification: type: object additionalProperties: false diff --git a/docs/integrations/sources/salesforce.md b/docs/integrations/sources/salesforce.md index 3182f4da1994..cac50b5488f7 100644 --- a/docs/integrations/sources/salesforce.md +++ b/docs/integrations/sources/salesforce.md @@ -274,6 +274,7 @@ The lookback window uses the ISO 8601 duration format. The format is `PT | Version | Date | Pull Request | Subject | |:------------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 2.7.19 | 2026-03-30 | [75579](https://github.com/airbytehq/airbyte/pull/75579) | Add `oauth_connector_input_specification` for declarative OAuth with sandbox/production URL switching | | 2.7.18 | 2026-02-25 | [73501](https://github.com/airbytehq/airbyte/pull/73501) | fix(source-salesforce): skip time-based slicing for full_refresh syncs (AI-Triage PR) | | 2.7.17 | 2026-02-10 | [73235](https://github.com/airbytehq/airbyte/pull/73235) | Make lookback window configurable to address Salesforce API eventual consistency | | 2.7.16 | 2025-10-29 | [69078](https://github.com/airbytehq/airbyte/pull/69078) | Promoting release candidate 2.7.16-rc.1 to a main version. | From 13c07faa67b7aa9b83766ae5c3b71f1f67e66fed Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 16:27:21 +0000 Subject: [PATCH 291/379] docs(source-typeform): add EU data center limitation and improve performance docs (#75901) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- docs/integrations/sources/typeform.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/integrations/sources/typeform.md b/docs/integrations/sources/typeform.md index d02ec0c5dbb8..713b80667a59 100644 --- a/docs/integrations/sources/typeform.md +++ b/docs/integrations/sources/typeform.md @@ -81,6 +81,10 @@ Skip this step. Airbyte Cloud uses OAuth to authenticate with Typeform. | Images | id | No | https://developer.typeform.com/create/reference/retrieve-images-collection/ | | Themes | id | No | https://developer.typeform.com/create/reference/retrieve-themes/ | +## Limitations + +This connector uses the Typeform US API endpoint (`api.typeform.com`). If your Typeform account stores responses in the [EU Data Center](https://www.typeform.com/developers/get-started/responses-data-center/), the Responses stream returns empty results. The Forms, Webhooks, Workspaces, Images, and Themes streams work regardless of data center region. + ## Performance considerations The Typeform API enforces a rate limit of 2 requests per second per account. The connector respects this limit automatically. For more information, see the [Typeform API rate limits documentation](https://developer.typeform.com/get-started/#rate-limits). @@ -89,8 +93,11 @@ Page size limits per stream: - Forms: 200 - Responses: 1000 +- Workspaces: 200 +- Images: 200 +- Themes: 200 -The connector makes an additional API call per sync to fetch the list of form IDs in your account using the [retrieve forms endpoint](https://developer.typeform.com/create/reference/retrieve-forms/). +The Forms, Responses, and Webhooks streams make separate API calls for each form in your account. The connector first fetches the list of form IDs using the [retrieve forms endpoint](https://developer.typeform.com/create/reference/retrieve-forms/), then queries each form individually. If you have many forms, consider using the **Form IDs** configuration option to limit the sync to only the forms you need. ## Changelog From cb99810b50c73c880fa8df96b8703f4c7024d457 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 10:46:39 -0700 Subject: [PATCH 292/379] ci(finalize_rollout): compose existing CLI commands in workflow (#75238) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/finalize_rollout.yml | 232 ++++++++++++++++++++++--- 1 file changed, 209 insertions(+), 23 deletions(-) diff --git a/.github/workflows/finalize_rollout.yml b/.github/workflows/finalize_rollout.yml index af72829293fd..f4ed78d86eba 100644 --- a/.github/workflows/finalize_rollout.yml +++ b/.github/workflows/finalize_rollout.yml @@ -1,12 +1,11 @@ -name: Finalize connector rollout -# This workflow is called by the backend Temporal workflow "finalizeRollout" -# as a part of its response to calls to `/connector_rollout/manual_finalize`, -# or in response to automatic fallback/finalization. +name: Finalize Progressive Rollout +# Dispatched by the platform's Temporal connector-rollout worker +# (PromoteOrRollbackActivityImpl) after a promote/rollback decision. +# After this workflow completes, verifyDefaultVersionActivity polls +# for up to 3 hours for the GA version to become default, then +# finalizeRolloutActivity unpins actors. # -# The workflow performs these tasks: -# 1. Generate an `auto-merge/bypass`-labeled PR to version-bump forward -# the named connector, including changelog entry. -# 2. Delete the `.../release_candidate` subdirectory in the GCS Registry Store. +# See: airbyte-platform-internal/.../connector-rollout-worker/ on: repository_dispatch: @@ -19,40 +18,41 @@ on: action: description: "Action to perform" required: true + type: choice options: ["promote", "rollback"] + +permissions: + contents: write + pull-requests: write + +# --------------------------------------------------------------------------- +# Job 1: Registry cleanup (runs for both promote and rollback) +# --------------------------------------------------------------------------- jobs: - finalize_rollout: - name: Finalize connector rollout for ${{ github.event.inputs.connector_name }} + rc-registry-cleanup: + name: "Registry cleanup (${{ github.event_name == 'workflow_dispatch' && github.event.inputs.action || github.event.client_payload.action }})" runs-on: ubuntu-24.04 env: ACTION: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.action || github.event.client_payload.action }} CONNECTOR_NAME: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.connector_name || github.event.client_payload.connector_name }} steps: - - name: Check action value + - name: Validate action run: | if [[ "${ACTION}" != "promote" && "${ACTION}" != "rollback" ]]; then - echo "Invalid action: ${ACTION}" + echo "::error::Invalid action: '${ACTION}'. Must be 'promote' or 'rollback'." exit 1 fi shell: bash - - name: Checkout Airbyte repo - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - name: Install uv uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0 - name: Install Ops CLI run: uv tool install airbyte-internal-ops - # Delete the release_candidate/ metadata marker from GCS. - # This is the same operation for both promote and rollback: - # it removes the RC pointer so the platform knows the rollout - # is finalized. The versioned blob (e.g. 1.2.3-rc.1/) is - # intentionally preserved as an audit trail. - - name: "GCS cleanup: delete RC metadata marker" + # Deletes the release_candidate/ metadata marker from GCS. + # The versioned blob (e.g. 1.2.3-rc.1/) is preserved as audit trail. + - name: "Delete RC metadata marker" shell: bash env: GCS_CREDENTIALS: ${{ secrets.METADATA_SERVICE_PROD_GCS_CREDENTIALS }} @@ -61,3 +61,189 @@ jobs: airbyte-ops registry rc cleanup --name "${CONNECTOR_NAME}" --store "${REGISTRY_STORE}" + + # Recompile the registry JSON indexes so the RC entry is removed. + - name: "Recompile registry for connector" + shell: bash + env: + GCS_CREDENTIALS: ${{ secrets.METADATA_SERVICE_PROD_GCS_CREDENTIALS }} + REGISTRY_STORE: "coral:prod" + run: > + airbyte-ops registry store compile + --store "${REGISTRY_STORE}" + --connector-name "${CONNECTOR_NAME}" + + # --- Notifications --- + - name: Notify Slack on rollback success + if: success() && env.ACTION == 'rollback' + uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 + env: + SLACK_WEBHOOK_URL: ${{ secrets.PUBLISH_ON_MERGE_SLACK_WEBHOOK }} + with: + payload: | + { + "channel": "#connector-publish-failures", + "username": "Connectors CI/CD Bot", + "text": "↩️ Successfully rolled back RC for `${{ env.CONNECTOR_NAME }}` — GCS marker deleted:\n${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + } + + - name: Notify Slack on failure + if: failure() + uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 + env: + SLACK_WEBHOOK_URL: ${{ secrets.PUBLISH_ON_MERGE_SLACK_WEBHOOK }} + with: + payload: | + { + "channel": "#connector-publish-failures", + "username": "Connectors CI/CD Bot", + "text": "🚨 Registry cleanup failed for `${{ env.CONNECTOR_NAME }}` (${{ env.ACTION }}):\n${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + } + + # --------------------------------------------------------------------------- + # Job 2: Create and merge cleanup PR (promote only) + # --------------------------------------------------------------------------- + create-promotion-pr: + name: "Create and Merge Promotion PR" + needs: rc-registry-cleanup + if: >- + github.event.inputs.action == 'promote' + || github.event.client_payload.action == 'promote' + runs-on: ubuntu-24.04 + env: + CONNECTOR_NAME: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.connector_name || github.event.client_payload.connector_name }} + steps: + # Authenticate as OCTAVIA_BOT so PRs trigger downstream CI. + - name: Authenticate as GitHub App + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 + id: get-app-token + with: + owner: "airbytehq" + repositories: "airbyte" + app-id: ${{ secrets.OCTAVIA_BOT_APP_ID }} + private-key: ${{ secrets.OCTAVIA_BOT_PRIVATE_KEY }} + + - name: Configure git identity + run: | + git config --global user.name "Octavia Squidington III" + git config --global user.email "octavia-squidington-iii@users.noreply.github.com" + + - name: Checkout Airbyte repo + uses: actions/checkout@v4 + with: + token: ${{ steps.get-app-token.outputs.token }} + fetch-depth: 1 + + - name: Install uv + uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0 + + - name: Install Ops CLI + run: uv tool install airbyte-internal-ops + + # bump-version --bump-type promote strips -rc.N suffix, sets + # enableProgressiveRollout to false, and bumps the version. + # --no-changelog because we don't have a PR number yet. + - name: "Version bump and cleanup" + shell: bash + run: > + airbyte-ops local connector bump-version + --name "${CONNECTOR_NAME}" + --repo-path "${{ github.workspace }}" + --bump-type promote + --no-changelog + + # Commits cleanup changes (version bump + progressive rollout + # flag removal) and opens a draft PR. This gives us a PR + # number for the changelog entry. + - name: Create cleanup PR + id: create-pr + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 + with: + token: ${{ steps.get-app-token.outputs.token }} + commit-message: "chore: finalize promote for ${{ env.CONNECTOR_NAME }}" + branch: "finalize-rollout/promote/${{ env.CONNECTOR_NAME }}" + base: ${{ github.event.repository.default_branch }} + delete-branch: true + title: "chore: finalize promote for ${{ env.CONNECTOR_NAME }}" + body: | + Automated cleanup after connector rollout **promote** for `${{ env.CONNECTOR_NAME }}`. + + Generated by [`finalize_rollout` workflow](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}). + labels: | + area/connectors + auto-merge/bypass-ci-checks + draft: true + + # changelog add reads the current version from metadata.yaml + # (already bumped to GA by the promote step above) and writes + # a changelog entry — no version files are modified. + - name: "Add changelog entry" + if: steps.create-pr.outputs.pull-request-number + shell: bash + run: > + airbyte-ops local connector changelog add + --connector-name "${CONNECTOR_NAME}" + --repo-path "${{ github.workspace }}" + --message "Promoted release candidate to GA" + --pr-number "${{ steps.create-pr.outputs.pull-request-number }}" + + # Second create-pull-request call pushes the changelog commit + # to the existing PR branch. + - name: "Push changelog to PR" + if: steps.create-pr.outputs.pull-request-number + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 + with: + token: ${{ steps.get-app-token.outputs.token }} + commit-message: "chore: add changelog for ${{ env.CONNECTOR_NAME }}" + branch: "finalize-rollout/promote/${{ env.CONNECTOR_NAME }}" + base: ${{ github.event.repository.default_branch }} + title: "chore: finalize promote for ${{ env.CONNECTOR_NAME }}" + body: | + Automated cleanup after connector rollout **promote** for `${{ env.CONNECTOR_NAME }}`. + + Generated by [`finalize_rollout` workflow](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}). + + # The merge triggers the publish pipeline that + # verifyDefaultVersionActivity is waiting for. + - name: Mark PR ready for review + if: steps.create-pr.outputs.pull-request-number + env: + GH_TOKEN: ${{ steps.get-app-token.outputs.token }} + run: gh pr ready "${{ steps.create-pr.outputs.pull-request-number }}" + + - name: Force-merge cleanup PR + if: steps.create-pr.outputs.pull-request-number + env: + GH_TOKEN: ${{ steps.get-app-token.outputs.token }} + run: | + gh pr merge "${{ steps.create-pr.outputs.pull-request-number }}" \ + --repo "${{ github.repository }}" \ + --squash \ + --admin + + # --- Notifications --- + - name: Notify Slack on promote success + if: success() && steps.create-pr.outputs.pull-request-number + uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 + env: + SLACK_WEBHOOK_URL: ${{ secrets.PUBLISH_ON_MERGE_SLACK_WEBHOOK }} + with: + payload: | + { + "channel": "#connector-publish-failures", + "username": "Connectors CI/CD Bot", + "text": "↗️ Successfully promoted `${{ env.CONNECTOR_NAME }}` — cleanup PR merged:\n${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + } + + - name: Notify Slack on failure + if: failure() + uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0 + env: + SLACK_WEBHOOK_URL: ${{ secrets.PUBLISH_ON_MERGE_SLACK_WEBHOOK }} + with: + payload: | + { + "channel": "#connector-publish-failures", + "username": "Connectors CI/CD Bot", + "text": "🚨 Promote PR failed for `${{ env.CONNECTOR_NAME }}`:\n${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + } From 93bf3c1ef0ae31034eb519d2eb9ecbb0f929e383 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 12:21:48 -0700 Subject: [PATCH 293/379] ci: update `/bump-progressive-rollout-version` to call `/bump-version`, update Welcome Message documentation (#75914) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/pr-welcome-internal.md | 7 +- ...mp-progressive-rollout-version-command.yml | 156 ++---------------- .github/workflows/bump-version-command.yml | 49 ++++-- 3 files changed, 58 insertions(+), 154 deletions(-) diff --git a/.github/pr-welcome-internal.md b/.github/pr-welcome-internal.md index 749254d2184d..1488e1ea8967 100644 --- a/.github/pr-welcome-internal.md +++ b/.github/pr-welcome-internal.md @@ -12,14 +12,17 @@ Airbyte Maintainers (that's you!) can execute the following slash commands on yo - 🛠️ Quick Fixes - `/format-fix` - Fixes most formatting issues. - `/bump-version` - Bumps connector versions, scraping `changelog` description from the PR title. + - Bump types: `patch` (default), `minor`, `major`, `major_rc`, `rc`, `promote`. + - The `rc` type is a smart default: applies `minor_rc` if stable, or bumps the RC number if already RC. + - The `promote` type strips the RC suffix to finalize a release. + - Example: `/bump-version type=rc` or `/bump-version type=minor` + - `/bump-progressive-rollout-version` - Alias for `/bump-version type=rc`. Bumps with an RC suffix and enables progressive rollout. - ❇️ AI Testing and Review (internal link: [AI-SDLC Docs](https://github.com/airbytehq/ai-skills/blob/main/docs/hydra/)): - `/ai-prove-fix` - Runs prerelease readiness checks, including testing against customer connections. - `/ai-canary-prerelease` - Rolls out prerelease to 5-10 connections for canary testing. - `/ai-review` - AI-powered PR review for connector safety and quality gates. - 🚀 Connector Releases: - `/publish-connectors-prerelease` - Publishes pre-release connector builds (tagged as `{version}-preview.{git-sha}`) for all modified connectors in the PR. - - `/bump-progressive-rollout-version` - Bumps connector version with an RC suffix (`2.16.10-rc.1`) for progressive rollouts (`enableProgressiveRollout: true`). - - Example: `/bump-progressive-rollout-version changelog="Add new feature for progressive rollout"` - ☕️ JVM connectors: - `/update-connector-cdk-version connector=` - Updates the specified connector to the latest CDK version. Example: `/update-connector-cdk-version connector=destination-bigquery` diff --git a/.github/workflows/bump-progressive-rollout-version-command.yml b/.github/workflows/bump-progressive-rollout-version-command.yml index 541973020ced..a3f1f5f4c62c 100644 --- a/.github/workflows/bump-progressive-rollout-version-command.yml +++ b/.github/workflows/bump-progressive-rollout-version-command.yml @@ -11,11 +11,6 @@ on: description: "Optional. The comment-id of the slash command. Used to update the comment with the status." required: false - type: - description: "The type of bump to perform. One of 'major', 'minor', or 'patch'." - required: false - default: "patch" - changelog: description: "Optional. The comment to add to the changelog. If not provided, the PR title will be used." required: false @@ -31,6 +26,11 @@ on: description: "Ref (Ignored)" required: false +permissions: + contents: read + issues: write + pull-requests: write + run-name: "Bump connector version for progressive rollout in PR: #${{ github.event.inputs.pr }}" concurrency: group: ${{ github.workflow }}-${{ github.event.inputs.pr }} @@ -39,140 +39,12 @@ concurrency: jobs: bump-progressive-rollout-version: - name: "Bump version of connectors for progressive rollout in this PR" - runs-on: ubuntu-24.04 - steps: - - name: Get job variables - id: job-vars - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - shell: bash - run: | - PR_JSON=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.inputs.pr }}) - echo "repo=$(echo "$PR_JSON" | jq -r .head.repo.full_name)" >> $GITHUB_OUTPUT - echo "branch=$(echo "$PR_JSON" | jq -r .head.ref)" >> $GITHUB_OUTPUT - echo "pr_title=$(echo "$PR_JSON" | jq -r .title)" >> $GITHUB_OUTPUT - echo "run-url=https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" >> $GITHUB_OUTPUT - - # NOTE: We still use a PAT here (rather than a GitHub App) because the workflow needs - # permissions to add commits to our main repo as well as forks. This will only work on - # forks if the user installs the app into their fork. Until we document this as a clear - # path, we will have to keep using the PAT. - - name: Checkout Airbyte - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - with: - repository: ${{ steps.job-vars.outputs.repo }} - ref: ${{ steps.job-vars.outputs.branch }} - fetch-depth: 1 - # Important that token is a PAT so that CI checks are triggered again. - # Without this we would be forever waiting on required checks to pass. - token: ${{ secrets.GH_PAT_APPROVINGTON_OCTAVIA }} - - - name: Append comment with job run link - # If comment-id is not provided, this will create a new - # comment with the job run link. - id: first-comment-action - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 - with: - comment-id: ${{ github.event.inputs.comment-id }} - issue-number: ${{ github.event.inputs.pr }} - body: | - - > **Progressive Rollout Version Bump Started** - > - > This will bump the connector version with an RC suffix and enable progressive rollout. - > [Check job output.][1] - - [1]: ${{ steps.job-vars.outputs.run-url }} - - - name: Log changelog source - run: | - if [ -n "${{ github.event.inputs.changelog }}" ]; then - echo "Using user-provided changelog: ${{ github.event.inputs.changelog }}" - else - echo "Using PR title as changelog: ${{ steps.job-vars.outputs.pr_title }}" - fi - - - name: Run airbyte-ci connectors --modified bump-version with --rc flag - uses: ./.github/actions/run-airbyte-ci - continue-on-error: true - with: - context: "manual" - gcs_credentials: ${{ secrets.METADATA_SERVICE_PROD_GCS_CREDENTIALS }} - sentry_dsn: ${{ secrets.SENTRY_AIRBYTE_CI_DSN }} - github_token: ${{ secrets.GH_PAT_APPROVINGTON_OCTAVIA }} - git_repo_url: https://github.com/${{ steps.job-vars.outputs.repo }}.git - subcommand: | - connectors --modified bump-version \ - ${{ github.event.inputs.type }} \ - "${{ github.event.inputs.changelog != '' && github.event.inputs.changelog || steps.job-vars.outputs.pr_title }}" \ - --pr-number ${{ github.event.inputs.pr }} \ - --rc - - # This is helpful in the case that we change a previously committed generated file to be ignored by git. - - name: Remove any files that have been gitignored - run: git ls-files -i -c --exclude-from=.gitignore | xargs -r git rm --cached - - # Check for changes in git - - name: Check for changes - id: git-diff - run: | - git diff --quiet && echo "No changes to commit" || echo "changes=true" >> $GITHUB_OUTPUT - shell: bash - - # Commit changes (if any) - - name: Commit changes - id: commit-step - if: steps.git-diff.outputs.changes == 'true' - run: | - git config --global user.name "Octavia Squidington III" - git config --global user.email "octavia-squidington-iii@users.noreply.github.com" - git add . - git commit -m "chore: bump-version for progressive rollout" - echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT - - - name: Push changes to '(${{ steps.job-vars.outputs.repo }})' - if: steps.git-diff.outputs.changes == 'true' - run: | - git remote add contributor https://github.com/${{ steps.job-vars.outputs.repo }}.git - git push contributor HEAD:'${{ steps.job-vars.outputs.branch }}' - - - name: Append success comment - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 - if: steps.git-diff.outputs.changes == 'true' - with: - comment-id: ${{ steps.first-comment-action.outputs.comment-id }} - reactions: hooray - body: | - > **Progressive Rollout Version Bump: SUCCESS** - > - > The connector version has been bumped with an RC suffix (e.g., `X.Y.Z-rc.1`). - > Changes applied successfully. (${{ steps.commit-step.outputs.sha }}) - > - > **Next steps:** - > 1. Merge this PR to publish the RC version - > 2. Monitor the progressive rollout in production - > 3. When ready to promote, use the `finalize_rollout` workflow with `action=promote` - > 4. If issues arise, use `action=rollback` instead - - - name: Append success comment (no-op) - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 - if: steps.git-diff.outputs.changes != 'true' - with: - comment-id: ${{ steps.first-comment-action.outputs.comment-id }} - reactions: "-1" - body: | - > Job completed successfully (no changes detected). - > - > This might happen if: - > - The connector already has an RC version - > - No modified connectors were detected in this PR - - - name: Append failure comment - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 - if: failure() - with: - comment-id: ${{ steps.first-comment-action.outputs.comment-id }} - reactions: confused - body: | - > Job failed. Check the [workflow logs](${{ steps.job-vars.outputs.run-url }}) for details. + # Delegate to the bump-version workflow with type=rc. + uses: ./.github/workflows/bump-version-command.yml + with: + pr: ${{ github.event.inputs.pr }} + comment-id: ${{ github.event.inputs.comment-id }} + type: "rc" + changelog: ${{ github.event.inputs.changelog }} + secrets: + GH_PAT_APPROVINGTON_OCTAVIA: ${{ secrets.GH_PAT_APPROVINGTON_OCTAVIA }} diff --git a/.github/workflows/bump-version-command.yml b/.github/workflows/bump-version-command.yml index 6a049e01f973..a217c2a8d7cf 100644 --- a/.github/workflows/bump-version-command.yml +++ b/.github/workflows/bump-version-command.yml @@ -1,6 +1,30 @@ name: Bump versions for connectors in a PR on: + workflow_call: + inputs: + pr: + description: "Pull request number. This PR will be referenced in the changelog line." + type: string + required: false + comment-id: + description: "Optional. The comment-id of the slash command. Used to update the comment with the status." + type: string + required: false + type: + description: "The type of bump to perform. One of 'major', 'minor', or 'patch'." + type: string + required: false + default: "patch" + changelog: + description: "Optional. The comment to add to the changelog. If not provided, the PR title will be used." + type: string + required: false + default: "" + secrets: + GH_PAT_APPROVINGTON_OCTAVIA: + required: true + workflow_dispatch: inputs: pr: @@ -32,9 +56,14 @@ on: description: "Ref (Ignored)" required: false -run-name: "Bump connector versions in PR: #${{ github.event.inputs.pr }}" +permissions: + contents: read + issues: write + pull-requests: write + +run-name: "Bump connector versions in PR: #${{ inputs.pr }}" concurrency: - group: ${{ github.workflow }}-${{ github.event.inputs.pr }} + group: ${{ github.workflow }}-${{ inputs.pr }} # Cancel any previous runs on the same branch if they are still in progress cancel-in-progress: true @@ -47,7 +76,7 @@ jobs: id: job-vars env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PR_NUMBER: ${{ github.event.inputs.pr }} + PR_NUMBER: ${{ inputs.pr }} shell: bash run: | PR_JSON=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUMBER") @@ -76,8 +105,8 @@ jobs: id: first-comment-action uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 with: - comment-id: ${{ github.event.inputs.comment-id }} - issue-number: ${{ github.event.inputs.pr }} + comment-id: ${{ inputs.comment-id }} + issue-number: ${{ inputs.pr }} body: | > Bump Version job started... [Check job output.][1] @@ -93,7 +122,7 @@ jobs: - name: Detect modified connectors id: detect-connectors env: - PR_NUMBER: ${{ github.event.inputs.pr }} + PR_NUMBER: ${{ inputs.pr }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | CONNECTORS=$( @@ -125,10 +154,10 @@ jobs: - name: Bump versions for modified connectors if: steps.detect-connectors.outputs.connectors != '' env: - BUMP_TYPE: ${{ github.event.inputs.type }} - CHANGELOG_MSG: ${{ github.event.inputs.changelog }} + BUMP_TYPE: ${{ inputs.type }} + CHANGELOG_MSG: ${{ inputs.changelog }} PR_TITLE: ${{ steps.job-vars.outputs.pr_title }} - PR_NUMBER: ${{ github.event.inputs.pr }} + PR_NUMBER: ${{ inputs.pr }} CONNECTORS: ${{ steps.detect-connectors.outputs.connectors }} run: | MSG="${CHANGELOG_MSG:-$PR_TITLE}" @@ -163,7 +192,7 @@ jobs: id: commit-step if: steps.git-diff.outputs.changes == 'true' env: - BUMP_TYPE: ${{ github.event.inputs.type }} + BUMP_TYPE: ${{ inputs.type }} run: | git config --global user.name "Octavia Squidington III" git config --global user.email "octavia-squidington-iii@users.noreply.github.com" From 8e934cbf5a8d62e35bac000310c37b1dedd53ba6 Mon Sep 17 00:00:00 2001 From: Matt Bayley Date: Tue, 31 Mar 2026 12:26:05 -0700 Subject: [PATCH 294/379] feat(bulk-cdk): changes for source-postgres rewrite (#75636) --- airbyte-cdk/bulk/core/extract/build.gradle | 3 +- airbyte-cdk/bulk/core/extract/changelog.md | 11 +- .../airbyte/cdk/discover/DiscoverOperation.kt | 2 +- .../airbyte/cdk/discover/DiscoveredStream.kt | 2 +- .../kotlin/io/airbyte/cdk/discover/Field.kt | 25 +- .../cdk/discover/MetaFieldDecorator.kt | 2 +- .../airbyte/cdk/discover/MetadataQuerier.kt | 2 +- .../io/airbyte/cdk/output/NativeRecord.kt | 13 +- .../airbyte/cdk/output/OutputMessageRouter.kt | 10 +- .../main/kotlin/io/airbyte/cdk/read/Feed.kt | 14 +- .../io/airbyte/cdk/read/FeedBootstrap.kt | 12 +- .../airbyte/cdk/read/StateManagerFactory.kt | 25 +- .../NativeRecordProtobufEncoderTest.kt | 6 +- .../io/airbyte/cdk/read/FeedBootstrapTest.kt | 6 +- .../cdk/read/StreamStatusManagerTest.kt | 6 +- .../ResourceDrivenMetadataQuerierFactory.kt | 8 +- .../bulk/core/extract/version.properties | 2 +- .../cdk/read/cdc/CdcPartitionReader.kt | 8 +- .../CdcPartitionReaderDebeziumOperations.kt | 2 +- .../cdk/read/cdc/CdcPartitionsCreator.kt | 8 +- .../CdcPartitionsCreatorDebeziumOperations.kt | 21 +- .../read/cdc/CdcPartitionsCreatorFactory.kt | 10 +- .../cdk/read/cdc/DebeziumOperations.kt | 2 +- .../cdk/read/cdc/DebeziumPropertiesBuilder.kt | 3 + .../cdk/read/cdc/DeserializedRecord.kt | 4 +- .../airbyte/cdk/read/cdc/PartiallyOrdered.kt | 35 +++ .../read/cdc/CdcPartitionReaderMongoTest.kt | 38 ++- .../read/cdc/CdcPartitionReaderMySQLTest.kt | 4 +- .../cdc/CdcPartitionReaderPostgresTest.kt | 24 +- .../cdk/read/cdc/CdcPartitionsCreatorTest.kt | 26 +- .../read/cdc/DebeziumPropertiesBuilderTest.kt | 17 +- .../cdc/AbstractCdcPartitionReaderTest.kt | 12 +- .../cdk/discover/JdbcAirbyteStreamFactory.kt | 9 +- .../cdk/discover/JdbcMetadataQuerier.kt | 18 +- .../airbyte/cdk/jdbc/DefaultJdbcConstants.kt | 2 + .../io/airbyte/cdk/jdbc/JdbcAccessor.kt | 39 ++- .../airbyte/cdk/jdbc/JdbcConnectionFactory.kt | 2 +- .../io/airbyte/cdk/jdbc/JdbcFieldTypes.kt | 2 +- .../airbyte/cdk/read/DefaultJdbcPartition.kt | 47 ++-- .../cdk/read/DefaultJdbcPartitionFactory.kt | 28 ++- .../cdk/read/DefaultJdbcStreamStateValue.kt | 10 +- .../io/airbyte/cdk/read/JdbcPartition.kt | 3 +- .../airbyte/cdk/read/JdbcPartitionReader.kt | 18 +- .../airbyte/cdk/read/JdbcPartitionsCreator.kt | 29 ++- .../io/airbyte/cdk/read/JdbcStreamState.kt | 6 + .../io/airbyte/cdk/read/SelectQuerier.kt | 81 ++++-- .../kotlin/io/airbyte/cdk/read/SelectQuery.kt | 4 +- .../io/airbyte/cdk/read/SelectQuerySpec.kt | 37 +-- .../discover/JdbcAirbyteStreamFactoryTest.kt | 9 +- .../read/DefaultJdbcPartitionFactoryTest.kt | 30 +-- .../cdk/read/JdbcPartitionsCreatorTest.kt | 46 +--- .../airbyte/cdk/read/JdbcSelectQuerierTest.kt | 5 +- .../io/airbyte/cdk/read/TestFixtures.kt | 31 ++- .../kotlin/io/airbyte/cdk/TriggerPartition.kt | 48 ++-- .../io/airbyte/cdk/TriggerPartitionFactory.kt | 28 ++- .../io/airbyte/cdk/TriggerPartitionReader.kt | 8 +- .../airbyte/cdk/TriggerPartitionsCreator.kt | 18 +- .../io/airbyte/cdk/TriggerTableConfig.kt | 24 +- .../cdk/operations/TriggerStreamFactory.kt | 4 +- .../legacy/AbstractSourceConnectorTest.kt | 3 + .../legacy/AbstractSourceDatabaseTypeTest.kt | 22 +- .../fixtures/legacy/ConnectorConfigUpdater.kt | 23 +- .../test/fixtures/legacy/ContainerFactory.kt | 17 +- .../fixtures/legacy/DefaultAirbyteSource.kt | 25 +- .../legacy/DefaultAirbyteStreamFactory.kt | 22 +- .../DefaultCheckConnectionTestHarness.kt | 24 +- .../DefaultDiscoverCatalogTestHarness.kt | 20 +- .../legacy/DefaultGetSpecTestHarness.kt | 16 +- .../fixtures/legacy/DockerProcessFactory.kt | 29 +-- .../fixtures/legacy/EntrypointEnvChecker.kt | 3 +- .../airbyte/cdk/test/fixtures/legacy/IOs.kt | 1 - .../airbyte/cdk/test/fixtures/legacy/Jsons.kt | 1 - .../test/fixtures/legacy/ProcessFactory.kt | 4 +- .../fixtures/legacy/SourceAcceptanceTest.kt | 22 +- .../fixtures/legacy/SshBastionContainer.kt | 57 ++--- .../cdk/test/fixtures/legacy/TestDatabase.kt | 24 +- .../test/fixtures/legacy/TestEnvConfigs.kt | 15 +- .../resources/ssh-tunnel-spec.json | 2 +- .../connector/IntegrationTestOperations.kt | 7 + .../test/fixtures/tests/BaseConnectorTest.kt | 4 +- .../fixtures/tests/CursorBasedSyncTest.kt | 233 ++++++++++++++++++ .../fixtures/tests/FieldTypeMapperTest.kt | 191 ++++++++++++-- 82 files changed, 1128 insertions(+), 586 deletions(-) create mode 100644 airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/PartiallyOrdered.kt create mode 100644 airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/tests/CursorBasedSyncTest.kt diff --git a/airbyte-cdk/bulk/core/extract/build.gradle b/airbyte-cdk/bulk/core/extract/build.gradle index fd6d04516f5e..1e6c78af7601 100644 --- a/airbyte-cdk/bulk/core/extract/build.gradle +++ b/airbyte-cdk/bulk/core/extract/build.gradle @@ -1,7 +1,8 @@ dependencies { - api "io.airbyte.bulk-cdk:bulk-cdk-core-base:1.0.1" + api "io.airbyte.bulk-cdk:bulk-cdk-core-base:1.0.2" implementation 'org.apache.commons:commons-lang3:3.17.0' implementation 'hu.webarticum:tree-printer:3.2.1' + // TODO: Use a published version. Use a variable to share the version with the api dependency. testFixturesApi testFixtures(project(':airbyte-cdk:bulk:core:bulk-cdk-core-base')) } diff --git a/airbyte-cdk/bulk/core/extract/changelog.md b/airbyte-cdk/bulk/core/extract/changelog.md index 38ebc0142fbf..6f67815b07aa 100644 --- a/airbyte-cdk/bulk/core/extract/changelog.md +++ b/airbyte-cdk/bulk/core/extract/changelog.md @@ -7,11 +7,12 @@ The Extract CDK provides functionality for source connectors including schema di
Expand to review -| Version | Date | Pull Request | Subject | -|---------|------------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 1.0.2 | 2026-02-24 | [74007](https://github.com/airbytehq/airbyte/pull/74007) | Fix infinite loop when cursor-based incremental sync encounters an empty table with prior state by caching NULL cursor upper bound values (toolkit). | -| 1.0.1 | 2026-02-24 | | Bump bulk-cdk-core-base to 1.0.1 to pick up CVE fixes (CVE-2021-47621, CVE-2022-36944). | -| 1.0.0 | 2026-02-02 | [#72376](https://github.com/airbytehq/airbyte/pull/72376) | Initial independent release of bulk-cdk-core-extract. Separate versioning for extract package begins. | +| Version | Date | Pull Request | Subject | +|---------|------------|-----------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------| +| 1.1.0 | 2026-03-30 | [75636](https://github.com/airbytehq/airbyte/pull/75636) | CDC positions are partially ordered. Added optional CDC startup hook. Field is now EmittedField. | +| 1.0.2 | 2026-02-24 | [74007](https://github.com/airbytehq/airbyte/pull/74007) | Fix infinite loop when cursor-based incremental sync encounters an empty table with prior state by caching NULL cursor upper bound values (toolkit). | +| 1.0.1 | 2026-02-24 | | Bump bulk-cdk-core-base to 1.0.1 to pick up CVE fixes (CVE-2021-47621, CVE-2022-36944). | +| 1.0.0 | 2026-02-02 | [#72376](https://github.com/airbytehq/airbyte/pull/72376) | Initial independent release of bulk-cdk-core-extract. Separate versioning for extract package begins. |
diff --git a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/DiscoverOperation.kt b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/DiscoverOperation.kt index 11828abb1fbf..e236ef5b7183 100644 --- a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/DiscoverOperation.kt +++ b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/DiscoverOperation.kt @@ -28,7 +28,7 @@ class DiscoverOperation( listOf(null) + metadataQuerier.streamNamespaces() for (namespace in namespaces) { for (streamID in metadataQuerier.streamNames(namespace)) { - val fields: List = metadataQuerier.fields(streamID) + val fields: List = metadataQuerier.fields(streamID) if (fields.isEmpty()) { log.info { "Ignoring stream '${streamID.name}' in '${namespace ?: ""}' because no fields were discovered." diff --git a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/DiscoveredStream.kt b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/DiscoveredStream.kt index ec22807fb60a..b295705670a5 100644 --- a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/DiscoveredStream.kt +++ b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/DiscoveredStream.kt @@ -8,6 +8,6 @@ import io.airbyte.cdk.StreamIdentifier data class DiscoveredStream( val id: StreamIdentifier, - val columns: List, + val columns: List, val primaryKeyColumnIDs: List>, ) diff --git a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/Field.kt b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/Field.kt index 6fa15b4f20ab..1a64a82df34d 100644 --- a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/Field.kt +++ b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/Field.kt @@ -13,11 +13,16 @@ import io.airbyte.cdk.data.OffsetDateTimeCodec import java.time.OffsetDateTime /** Internal equivalent of a [io.airbyte.protocol.models.Field]. */ -sealed interface FieldOrMetaField { +sealed interface DataOrMetaField { val id: String val type: FieldType } +@Deprecated( + message = "Use `DataOrMetaField` directly instead.", + replaceWith = ReplaceWith("DataOrMetaField") +) +typealias FieldOrMetaField = DataOrMetaField /** * Root of our own type hierarchy for Airbyte record fields. * @@ -40,20 +45,32 @@ interface LosslessFieldType : FieldType { val jsonDecoder: JsonDecoder<*> } +interface DataField : DataOrMetaField + +@Deprecated( + message = "Use `EmittedField` directly instead.", + replaceWith = ReplaceWith("EmittedField") +) +typealias Field = EmittedField /** * Internal equivalent of [io.airbyte.protocol.models.Field] for values which come from the source * itself, instead of being generated by the connector during its operation. */ -data class Field( +data class EmittedField( + override val id: String, + override val type: FieldType, +) : DataField + +data class NonEmittedField( override val id: String, override val type: FieldType, -) : FieldOrMetaField +) : DataField /** * Internal equivalent of [io.airbyte.protocol.models.Field] for values which are generated by the * connector itself during its operation, instead of coming from the source. */ -interface MetaField : FieldOrMetaField { +interface MetaField : DataOrMetaField { companion object { const val META_PREFIX = "_ab_" diff --git a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/MetaFieldDecorator.kt b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/MetaFieldDecorator.kt index 5b436f87ee65..1c62ec4b9812 100644 --- a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/MetaFieldDecorator.kt +++ b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/MetaFieldDecorator.kt @@ -15,7 +15,7 @@ import java.time.OffsetDateTime interface MetaFieldDecorator { /** [MetaField] to use as a global cursor, if applicable. */ - val globalCursor: FieldOrMetaField? + val globalCursor: DataOrMetaField? /** * All [MetaField]s to be found in [Global] stream records. diff --git a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/MetadataQuerier.kt b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/MetadataQuerier.kt index 83d6f2e0e331..36258750a612 100644 --- a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/MetadataQuerier.kt +++ b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/discover/MetadataQuerier.kt @@ -14,7 +14,7 @@ interface MetadataQuerier : AutoCloseable { fun streamNames(streamNamespace: String?): List /** Returns all available fields in the given stream. */ - fun fields(streamID: StreamIdentifier): List + fun fields(streamID: StreamIdentifier): List /** Returns the primary key for the given stream, if it exists; empty list otherwise. */ fun primaryKey(streamID: StreamIdentifier): List> diff --git a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/output/NativeRecord.kt b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/output/NativeRecord.kt index 593e68c22554..4420eec3277a 100644 --- a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/output/NativeRecord.kt +++ b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/output/NativeRecord.kt @@ -10,11 +10,12 @@ import io.airbyte.cdk.data.ArrayEncoder import io.airbyte.cdk.data.BigDecimalIntegerCodec import io.airbyte.cdk.data.ByteCodec import io.airbyte.cdk.data.CdcOffsetDateTimeCodec +import io.airbyte.cdk.data.JsonCodec import io.airbyte.cdk.data.JsonEncoder import io.airbyte.cdk.data.NullCodec import io.airbyte.cdk.data.OffsetDateTimeCodec import io.airbyte.cdk.data.UrlCodec -import io.airbyte.cdk.discover.FieldOrMetaField +import io.airbyte.cdk.discover.DataOrMetaField import io.airbyte.cdk.protocol.AirbyteValueProtobufEncoder import io.airbyte.cdk.util.Jsons import io.airbyte.protocol.protobuf.AirbyteRecordMessage @@ -43,6 +44,10 @@ fun NativeRecordPayload.toJson(parentNode: ObjectNode = Jsons.objectNode()): Obj return parentNode } +interface ProtobufAwareCustomConnectorJsonCodec : JsonCodec { + fun valueForProtobufEncoding(v: T): Any? +} + /** * Transforms a field value into a protobuf-compatible representation. Handles special conversions * for types that need preprocessing before protobuf encoding, such as ByteBuffer -> Base64 String, @@ -57,13 +62,17 @@ fun valueForProtobufEncoding(fve: FieldValueEncoder): Any? { is CdcOffsetDateTimeCodec -> (value as OffsetDateTime).format(OffsetDateTimeCodec.formatter) is ArrayEncoder<*> -> fve.encode().toString() + is ProtobufAwareCustomConnectorJsonCodec<*> -> + (fve.jsonEncoder as ProtobufAwareCustomConnectorJsonCodec).valueForProtobufEncoding( + value + ) else -> value } } } fun NativeRecordPayload.toProtobuf( - schema: Set, + schema: Set, recordMessageBuilder: AirbyteRecordMessageProtobuf.Builder, valueBuilder: AirbyteRecordMessage.AirbyteValueProtobuf.Builder ): AirbyteRecordMessageProtobuf.Builder { diff --git a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/output/OutputMessageRouter.kt b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/output/OutputMessageRouter.kt index 1e1772688e81..ab1cc72a319a 100644 --- a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/output/OutputMessageRouter.kt +++ b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/output/OutputMessageRouter.kt @@ -6,7 +6,7 @@ package io.airbyte.cdk.output import edu.umd.cs.findbugs.annotations.SuppressFBWarnings import io.airbyte.cdk.StreamIdentifier -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.output.sockets.NativeRecordPayload import io.airbyte.cdk.output.sockets.SocketJsonOutputConsumer import io.airbyte.cdk.output.sockets.SocketProtobufOutputConsumer @@ -40,7 +40,7 @@ class OutputMessageRouter( Map.ProtoEfficientStreamRecordConsumer> private lateinit var simpleEfficientStreamConsumers: Map var recordAcceptors: - Map?) -> Unit> + Map?) -> Unit> init { when (recordsDataChannelMedium) { @@ -64,7 +64,7 @@ class OutputMessageRouter( it.key to { record: NativeRecordPayload, - changes: Map? -> + changes: Map? -> it.value.accept(record, changes) } } @@ -90,7 +90,7 @@ class OutputMessageRouter( it.key to { record: NativeRecordPayload, - changes: Map? -> + changes: Map? -> it.value.accept(record, changes) } } @@ -106,7 +106,7 @@ class OutputMessageRouter( it.key to { record: NativeRecordPayload, - changes: Map? -> + changes: Map? -> it.value.accept(record, changes) } } diff --git a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/read/Feed.kt b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/read/Feed.kt index d921a7456d9e..ccbd773abcdd 100644 --- a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/read/Feed.kt +++ b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/read/Feed.kt @@ -2,8 +2,8 @@ package io.airbyte.cdk.read import io.airbyte.cdk.StreamIdentifier -import io.airbyte.cdk.discover.Field -import io.airbyte.cdk.discover.FieldOrMetaField +import io.airbyte.cdk.discover.DataOrMetaField +import io.airbyte.cdk.discover.EmittedField /** * [Feed] identifies part of the data consumed during a READ operation. @@ -30,10 +30,10 @@ data class Global( */ data class Stream( val id: StreamIdentifier, - val schema: Set, + val schema: Set, val configuredSyncMode: ConfiguredSyncMode, - val configuredPrimaryKey: List?, - val configuredCursor: FieldOrMetaField?, + val configuredPrimaryKey: List?, + val configuredCursor: DataOrMetaField?, ) : Feed { val name: String get() = id.name @@ -44,8 +44,8 @@ data class Stream( override val label: String get() = id.toString() - val fields: List - get() = schema.filterIsInstance() + val fields: List + get() = schema.filterIsInstance() } /** List of [Stream]s this [Feed] emits records for. */ diff --git a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/read/FeedBootstrap.kt b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/read/FeedBootstrap.kt index 20026ab07feb..3377b177e18b 100644 --- a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/read/FeedBootstrap.kt +++ b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/read/FeedBootstrap.kt @@ -8,7 +8,7 @@ import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.node.ObjectNode import io.airbyte.cdk.StreamIdentifier import io.airbyte.cdk.command.OpaqueStateValue -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.discover.MetaFieldDecorator import io.airbyte.cdk.output.DataChannelFormat import io.airbyte.cdk.output.DataChannelMedium @@ -116,13 +116,13 @@ sealed class FeedBootstrap( override fun accept( recordData: NativeRecordPayload, - changes: Map? + changes: Map? ) { if (changes.isNullOrEmpty()) { acceptWithoutChanges(recordData.toJson()) } else { val protocolChanges: List = - changes.map { (field: Field, fieldValueChange: FieldValueChange) -> + changes.map { (field: EmittedField, fieldValueChange: FieldValueChange) -> AirbyteRecordMessageMetaChange() .withField(field.id) .withChange(fieldValueChange.protocolChange()) @@ -230,7 +230,7 @@ sealed class FeedBootstrap( val valueVBuilder = AirbyteValueProtobuf.newBuilder()!! override fun accept( recordData: NativeRecordPayload, - changes: Map? + changes: Map? ) { if (changes.isNullOrEmpty()) { acceptWithoutChanges( @@ -240,7 +240,7 @@ sealed class FeedBootstrap( val rm = AirbyteRecordMessageMetaOuterClass.AirbyteRecordMessageMeta.newBuilder() val c = AirbyteRecordMessageMetaOuterClass.AirbyteRecordMessageMetaChange.newBuilder() - changes.forEach { (field: Field, fieldValueChange: FieldValueChange) -> + changes.forEach { (field: EmittedField, fieldValueChange: FieldValueChange) -> c.clear() .setField(field.id) .setChange(fieldValueChange.protobufChange()) @@ -493,7 +493,7 @@ interface StreamRecordConsumer { val stream: Stream - fun accept(recordData: NativeRecordPayload, changes: Map?) + fun accept(recordData: NativeRecordPayload, changes: Map?) fun close() } diff --git a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/read/StateManagerFactory.kt b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/read/StateManagerFactory.kt index e378c8036d3a..7fc4d70dcab3 100644 --- a/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/read/StateManagerFactory.kt +++ b/airbyte-cdk/bulk/core/extract/src/main/kotlin/io/airbyte/cdk/read/StateManagerFactory.kt @@ -14,8 +14,8 @@ import io.airbyte.cdk.command.StreamInputState import io.airbyte.cdk.data.AirbyteSchemaType import io.airbyte.cdk.data.ArrayAirbyteSchemaType import io.airbyte.cdk.data.LeafAirbyteSchemaType -import io.airbyte.cdk.discover.Field -import io.airbyte.cdk.discover.FieldOrMetaField +import io.airbyte.cdk.discover.DataOrMetaField +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.discover.MetaField import io.airbyte.cdk.discover.MetaFieldDecorator import io.airbyte.cdk.discover.MetadataQuerier @@ -197,16 +197,16 @@ class StateManagerFactory( jsonSchemaProperties.properties().associate { (id: String, schema: JsonNode) -> id to airbyteTypeFromJsonSchema(schema) } - val actualDataColumns: Map = + val actualDataColumns: Map = metadataQuerier.fields(streamID).associateBy { it.id } - fun dataColumnOrNull(id: String): Field? { + fun dataColumnOrNull(id: String): EmittedField? { if (MetaField.isMetaFieldID(id)) { // Ignore airbyte metadata columns. // These aren't actually present in the table. return null } - val actualColumn: Field? = actualDataColumns[id] + val actualColumn: EmittedField? = actualDataColumns[id] if (actualColumn == null) { handler.accept(FieldNotFound(streamID, id)) return null @@ -226,7 +226,7 @@ class StateManagerFactory( } return actualColumn } - val streamFields: List = + val streamFields: List = expectedSchema.keys.toList().filterNot(MetaField::isMetaFieldID).map { dataColumnOrNull(it) ?: return@toStream null } @@ -241,13 +241,13 @@ class StateManagerFactory( return null } - fun pkOrNull(pkColumnIDComponents: List>): List? { + fun pkOrNull(pkColumnIDComponents: List>): List? { if (pkColumnIDComponents.isEmpty()) { return null } val pkColumnIDs: List = pkColumnIDComponents.map { it.joinToString(separator = ".") } - val pk: List = pkColumnIDs.mapNotNull(::dataColumnOrNull) + val pk: List = pkColumnIDs.mapNotNull(::dataColumnOrNull) if (pk.size < pkColumnIDComponents.size) { handler.accept(InvalidPrimaryKey(streamID, pkColumnIDs)) return null @@ -255,7 +255,7 @@ class StateManagerFactory( return pk } - fun cursorOrNull(cursorColumnIDComponents: List): FieldOrMetaField? { + fun cursorOrNull(cursorColumnIDComponents: List): DataOrMetaField? { if (cursorColumnIDComponents.isEmpty()) { return null } @@ -265,14 +265,15 @@ class StateManagerFactory( } return dataColumnOrNull(cursorColumnID) } - val configuredPrimaryKey: List? = + val configuredPrimaryKey: List? = configuredStream.primaryKey?.asSequence()?.let { pkOrNull(it.toList()) } - val configuredCursor: FieldOrMetaField? = + val configuredCursor: DataOrMetaField? = configuredStream.cursorField?.asSequence()?.let { cursorOrNull(it.toList()) } + val sourceDefinedCursor = configuredStream.stream.sourceDefinedCursor val configuredSyncMode: ConfiguredSyncMode = when (configuredStream.syncMode) { SyncMode.INCREMENTAL -> - if (configuredCursor == null) { + if (configuredCursor == null && sourceDefinedCursor.not()) { handler.accept(InvalidIncrementalSyncMode(streamID)) ConfiguredSyncMode.FULL_REFRESH } else { diff --git a/airbyte-cdk/bulk/core/extract/src/test/kotlin/io/airbyte/cdk/output/sockets/NativeRecordProtobufEncoderTest.kt b/airbyte-cdk/bulk/core/extract/src/test/kotlin/io/airbyte/cdk/output/sockets/NativeRecordProtobufEncoderTest.kt index 73667ba0221a..313ae5aca566 100644 --- a/airbyte-cdk/bulk/core/extract/src/test/kotlin/io/airbyte/cdk/output/sockets/NativeRecordProtobufEncoderTest.kt +++ b/airbyte-cdk/bulk/core/extract/src/test/kotlin/io/airbyte/cdk/output/sockets/NativeRecordProtobufEncoderTest.kt @@ -26,7 +26,7 @@ import io.airbyte.cdk.data.OffsetTimeCodec import io.airbyte.cdk.data.ShortCodec import io.airbyte.cdk.data.TextCodec import io.airbyte.cdk.data.UrlCodec -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.discover.FieldType import io.airbyte.cdk.protocol.AirbyteValueProtobufDecoder import io.airbyte.protocol.protobuf.AirbyteRecordMessage.AirbyteRecordMessageProtobuf @@ -77,8 +77,8 @@ class NativeRecordProtobufEncoderTest { val protoBuilder = AirbyteRecordMessageProtobuf.newBuilder().also { it.addData(0, valBuilder.clear()) } - fun fieldOf(airbyteSchemaType: AirbyteSchemaType, jsonEncoder: JsonEncoder<*>): Field = - Field( + fun fieldOf(airbyteSchemaType: AirbyteSchemaType, jsonEncoder: JsonEncoder<*>): EmittedField = + EmittedField( "id", object : FieldType { override val airbyteSchemaType = airbyteSchemaType diff --git a/airbyte-cdk/bulk/core/extract/src/test/kotlin/io/airbyte/cdk/read/FeedBootstrapTest.kt b/airbyte-cdk/bulk/core/extract/src/test/kotlin/io/airbyte/cdk/read/FeedBootstrapTest.kt index 257edf297fb3..547ff7c98a4b 100644 --- a/airbyte-cdk/bulk/core/extract/src/test/kotlin/io/airbyte/cdk/read/FeedBootstrapTest.kt +++ b/airbyte-cdk/bulk/core/extract/src/test/kotlin/io/airbyte/cdk/read/FeedBootstrapTest.kt @@ -12,7 +12,7 @@ import io.airbyte.cdk.data.LocalDateTimeCodec import io.airbyte.cdk.data.NullCodec import io.airbyte.cdk.data.TextCodec import io.airbyte.cdk.discover.CommonMetaField -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.discover.IntFieldType import io.airbyte.cdk.discover.StringFieldType import io.airbyte.cdk.discover.TestMetaFieldDecorator @@ -37,8 +37,8 @@ class FeedBootstrapTest { @Inject lateinit var metaFieldDecorator: TestMetaFieldDecorator - val k = Field("k", IntFieldType) - val v = Field("v", StringFieldType) + val k = EmittedField("k", IntFieldType) + val v = EmittedField("v", StringFieldType) val stream: Stream = Stream( id = StreamIdentifier.from(StreamDescriptor().withName("tbl").withNamespace("ns")), diff --git a/airbyte-cdk/bulk/core/extract/src/test/kotlin/io/airbyte/cdk/read/StreamStatusManagerTest.kt b/airbyte-cdk/bulk/core/extract/src/test/kotlin/io/airbyte/cdk/read/StreamStatusManagerTest.kt index 0a06c9af9936..3fc7115583d5 100644 --- a/airbyte-cdk/bulk/core/extract/src/test/kotlin/io/airbyte/cdk/read/StreamStatusManagerTest.kt +++ b/airbyte-cdk/bulk/core/extract/src/test/kotlin/io/airbyte/cdk/read/StreamStatusManagerTest.kt @@ -5,7 +5,7 @@ package io.airbyte.cdk.read import io.airbyte.cdk.StreamIdentifier -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.discover.IntFieldType import io.airbyte.protocol.models.v0.AirbyteStreamStatusTraceMessage import io.airbyte.protocol.models.v0.StreamDescriptor @@ -17,7 +17,7 @@ class StreamStatusManagerTest { val streamIncremental = Stream( id = StreamIdentifier.from(StreamDescriptor().withName("streamIncremental")), - schema = setOf(Field("v", IntFieldType)), + schema = setOf(EmittedField("v", IntFieldType)), configuredSyncMode = ConfiguredSyncMode.INCREMENTAL, configuredPrimaryKey = null, configuredCursor = null, @@ -25,7 +25,7 @@ class StreamStatusManagerTest { val streamFullRefresh = Stream( id = StreamIdentifier.from(StreamDescriptor().withName("streamFullRefresh")), - schema = setOf(Field("v", IntFieldType)), + schema = setOf(EmittedField("v", IntFieldType)), configuredSyncMode = ConfiguredSyncMode.FULL_REFRESH, configuredPrimaryKey = null, configuredCursor = null, diff --git a/airbyte-cdk/bulk/core/extract/src/testFixtures/kotlin/io/airbyte/cdk/discover/ResourceDrivenMetadataQuerierFactory.kt b/airbyte-cdk/bulk/core/extract/src/testFixtures/kotlin/io/airbyte/cdk/discover/ResourceDrivenMetadataQuerierFactory.kt index be430854814c..c76277c516fb 100644 --- a/airbyte-cdk/bulk/core/extract/src/testFixtures/kotlin/io/airbyte/cdk/discover/ResourceDrivenMetadataQuerierFactory.kt +++ b/airbyte-cdk/bulk/core/extract/src/testFixtures/kotlin/io/airbyte/cdk/discover/ResourceDrivenMetadataQuerierFactory.kt @@ -33,11 +33,11 @@ class ResourceDrivenMetadataQuerierFactory( val streamID: StreamIdentifier = StreamIdentifier.from(desc) map[streamID] = null val level2: Level2 = level1.metadata ?: continue - val columns: List = + val columns: List = level2.columns.map { (id: String, fullyQualifiedClassName: String) -> val fieldType: FieldType = Class.forName(fullyQualifiedClassName).kotlin.objectInstance as FieldType - Field(id, fieldType) + EmittedField(id, fieldType) } map[streamID] = TestStreamMetadata(columns, level2.primaryKeys) } @@ -60,7 +60,7 @@ class ResourceDrivenMetadataQuerierFactory( override fun fields( streamID: StreamIdentifier, - ): List { + ): List { if (isClosed) throw IllegalStateException() return metadata[streamID]?.fields ?: throw SQLException("query failed", "tbl") } @@ -81,7 +81,7 @@ class ResourceDrivenMetadataQuerierFactory( } data class TestStreamMetadata( - val fields: List, + val fields: List, val primaryKeys: List>, ) diff --git a/airbyte-cdk/bulk/core/extract/version.properties b/airbyte-cdk/bulk/core/extract/version.properties index 325db2cfb7dc..de652dbcca18 100644 --- a/airbyte-cdk/bulk/core/extract/version.properties +++ b/airbyte-cdk/bulk/core/extract/version.properties @@ -1 +1 @@ -version=1.0.2 +version=1.1.0 diff --git a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReader.kt b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReader.kt index 8f74623bf412..2d079de39a41 100644 --- a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReader.kt +++ b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReader.kt @@ -46,7 +46,7 @@ import org.apache.kafka.connect.source.SourceRecord /** [PartitionReader] implementation for CDC with Debezium. */ @SuppressFBWarnings(value = ["NP_NONNULL_RETURN_VIOLATION"], justification = "Micronaut DI") -class CdcPartitionReader>( +class CdcPartitionReader>( val resourceAcquirer: ResourceAcquirer, val readerOps: CdcPartitionReaderDebeziumOperations, val upperBound: T, @@ -413,7 +413,9 @@ class CdcPartitionReader>( if (currentPosition == null) { return null } - val isProgressing = lastHeartbeatPosition?.let { currentPosition > it } ?: true + val isProgressing = + lastHeartbeatPosition == null || + currentPosition.isGreater(lastHeartbeatPosition) if (isProgressing) { lastHeartbeatPosition = currentPosition lastHeartbeatTime = now @@ -433,7 +435,7 @@ class CdcPartitionReader>( } } - if (currentPosition == null || currentPosition < upperBound) { + if (upperBound.isGreater(currentPosition)) { return null } // Close because the current event is past the sync upper bound. diff --git a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderDebeziumOperations.kt b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderDebeziumOperations.kt index 516176f80c09..5b67d1380c5e 100644 --- a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderDebeziumOperations.kt +++ b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderDebeziumOperations.kt @@ -8,7 +8,7 @@ import io.airbyte.cdk.command.OpaqueStateValue import io.airbyte.cdk.read.Stream import org.apache.kafka.connect.source.SourceRecord -interface CdcPartitionReaderDebeziumOperations> { +interface CdcPartitionReaderDebeziumOperations> { /** * Transforms a [DebeziumRecordKey] and a [DebeziumRecordValue] into a [DeserializedRecord]. diff --git a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreator.kt b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreator.kt index 0c39ab4f3601..e0c2537d844e 100644 --- a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreator.kt +++ b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreator.kt @@ -16,7 +16,7 @@ import io.github.oshai.kotlinlogging.KotlinLogging import java.util.concurrent.atomic.AtomicReference /** [PartitionsCreator] implementation for CDC with Debezium. */ -class CdcPartitionsCreator>( +class CdcPartitionsCreator>( val concurrencyResource: ConcurrencyResource, val resourceAcquirer: ResourceAcquirer, val feedBootstrap: GlobalFeedBootstrap, @@ -105,6 +105,8 @@ class CdcPartitionsCreator>( startingSchemaHistory = null } } + // Optional startup hook + creatorOps.runStartup(startingOffset) // Build and return PartitionReader instance, if applicable. val partitionReader = CdcPartitionReader( @@ -125,14 +127,14 @@ class CdcPartitionsCreator>( log.info { "Current offset is synthetic." } return listOf(partitionReader) } - if (upperBound <= lowerBound) { + if (lowerBound.isGreaterOrEqual(upperBound)) { // Handle completion due to reaching the WAL position upper bound. log.info { "Current position '$lowerBound' equals or exceeds target position '$upperBound'." } return emptyList() } - if (lowerBoundInPreviousRound != null && lowerBound <= lowerBoundInPreviousRound) { + if (lowerBoundInPreviousRound.isGreaterOrEqual(lowerBound)) { // Handle completion due to stalling. log.info { "Current position '$lowerBound' has not increased in the last round, " + diff --git a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreatorDebeziumOperations.kt b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreatorDebeziumOperations.kt index 6666779db9c0..e49207657167 100644 --- a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreatorDebeziumOperations.kt +++ b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreatorDebeziumOperations.kt @@ -6,8 +6,27 @@ package io.airbyte.cdk.read.cdc import io.airbyte.cdk.command.OpaqueStateValue import io.airbyte.cdk.read.Stream +import java.util.concurrent.atomic.AtomicBoolean -interface CdcPartitionsCreatorDebeziumOperations> { +interface CdcPartitionsCreatorDebeziumOperations> { + + companion object { + private val hasRunStartup = AtomicBoolean(false) + + fun shouldRunStartup(): Boolean { + return hasRunStartup.compareAndSet(false, true) + } + } + + /** Run optional startup hook if it hasn't already been run */ + fun runStartup(offset: DebeziumOffset) { + if (shouldRunStartup()) { + startup(offset) + } + } + + /** Optional startup hook. */ + fun startup(offset: DebeziumOffset) {} /** Extracts the WAL position from a [DebeziumOffset]. */ fun position(offset: DebeziumOffset): T diff --git a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreatorFactory.kt b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreatorFactory.kt index fc347ee772a2..da14c54c992d 100644 --- a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreatorFactory.kt +++ b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreatorFactory.kt @@ -18,7 +18,7 @@ import java.util.concurrent.atomic.AtomicReference @Singleton @Order(10) /** [PartitionsCreatorFactory] implementation for CDC with Debezium. */ -class CdcPartitionsCreatorFactory>( +class CdcPartitionsCreatorFactory>( val concurrencyResource: ConcurrencyResource, val resourceAcquirer: ResourceAcquirer, val cdcPartitionsCreatorDbzOps: CdcPartitionsCreatorDebeziumOperations, @@ -60,8 +60,8 @@ class CdcPartitionsCreatorFactory>( } @Singleton -class CdcPartitionsCreatorFactorySupplier, C : Comparable>( - val factory: T -) : PartitionsCreatorFactorySupplier { - override fun get(): T = factory +class CdcPartitionsCreatorFactorySupplier< + F : CdcPartitionsCreatorFactory

, P : PartiallyOrdered

>(val factory: F) : + PartitionsCreatorFactorySupplier { + override fun get(): F = factory } diff --git a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/DebeziumOperations.kt b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/DebeziumOperations.kt index a90b8390a386..992dd5063bd5 100644 --- a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/DebeziumOperations.kt +++ b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/DebeziumOperations.kt @@ -6,5 +6,5 @@ package io.airbyte.cdk.read.cdc /** Stateless connector-specific Debezium operations. */ @Deprecated("Implement the two interfaces separately") -interface DebeziumOperations> : +interface DebeziumOperations> : CdcPartitionsCreatorDebeziumOperations, CdcPartitionReaderDebeziumOperations diff --git a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/DebeziumPropertiesBuilder.kt b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/DebeziumPropertiesBuilder.kt index 5f74adbb9d75..7563196d5a7d 100644 --- a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/DebeziumPropertiesBuilder.kt +++ b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/DebeziumPropertiesBuilder.kt @@ -159,6 +159,9 @@ class DebeziumPropertiesBuilder(private val props: Properties = Properties()) { } } + fun withHeartbeatTimeout(timeout: Duration): DebeziumPropertiesBuilder = + with(AIRBYTE_HEARTBEAT_TIMEOUT_SECONDS, timeout.seconds.toString()) + companion object { private const val BYTE_VALUE_256_MB = (256 * 1024 * 1024).toString() diff --git a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/DeserializedRecord.kt b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/DeserializedRecord.kt index 240a07a99d6e..79d70a94ce11 100644 --- a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/DeserializedRecord.kt +++ b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/DeserializedRecord.kt @@ -4,12 +4,12 @@ package io.airbyte.cdk.read.cdc -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.output.sockets.NativeRecordPayload import io.airbyte.cdk.read.FieldValueChange /** [DeserializedRecord]s are used to generate Airbyte RECORD messages. */ data class DeserializedRecord( val data: NativeRecordPayload, - val changes: Map, + val changes: Map, ) diff --git a/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/PartiallyOrdered.kt b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/PartiallyOrdered.kt new file mode 100644 index 000000000000..c5e86d0b2561 --- /dev/null +++ b/airbyte-cdk/bulk/toolkits/extract-cdc/src/main/kotlin/io/airbyte/cdk/read/cdc/PartiallyOrdered.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Airbyte, Inc., all rights reserved. + */ + +package io.airbyte.cdk.read.cdc + +/** + * Represents the mathematical concept of partial ordering. Unlike Comparable, the compareTo method + * can return null when the two elements don't have a natural ordering. + * + * We use this interface to compare CDC positions to see when we have reached the target offset or + * to determine whether we are still making progress. We need partial ordering rather than a full + * ordering like Comparable because sometimes we are missing some fields in the offset and can't + * determine whether one offset is beyond another. In these cases, we typically continue until we + * encounter a fully populated offset. + * + * The supplied convenience methods handle the null checking and allow us to make these kinds of + * comparisons ergonomically. + */ +fun interface PartiallyOrdered { + fun compareTo(other: T): Int? +} + +// Convenience methods +fun > T?.isGreater(other: T?): Boolean { + if (this == null || other == null) return false + val comparison = this.compareTo(other) + return comparison != null && comparison > 0 +} + +fun > T?.isGreaterOrEqual(other: T?): Boolean { + if (this == null || other == null) return false + val comparison = this.compareTo(other) + return comparison != null && comparison >= 0 +} diff --git a/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderMongoTest.kt b/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderMongoTest.kt index 20ef01c8953b..8299734a0fd4 100644 --- a/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderMongoTest.kt +++ b/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderMongoTest.kt @@ -27,9 +27,17 @@ import org.bson.Document import org.bson.conversions.Bson import org.junit.jupiter.api.Disabled +data class BsonTimestampPosition(val timestamp: BsonTimestamp) : + PartiallyOrdered { + override fun compareTo(other: BsonTimestampPosition): Int? { + val timeCmp = timestamp.time.compareTo(other.timestamp.time) + return if (timeCmp != 0) timeCmp else timestamp.inc.compareTo(other.timestamp.inc) + } +} + @Disabled class CdcPartitionReaderMongoTest : - AbstractCdcPartitionReaderTest( + AbstractCdcPartitionReaderTest( namespace = "test", ) { @@ -83,16 +91,19 @@ class CdcPartitionReaderMongoTest : } override fun createCdcPartitionsCreatorDbzOps(): - CdcPartitionsCreatorDebeziumOperations = TestCdcPartitionsCreatorDbzOps() + CdcPartitionsCreatorDebeziumOperations = + TestCdcPartitionsCreatorDbzOps() override fun createCdcPartitionReaderDbzOps(): - CdcPartitionReaderDebeziumOperations = TestCdcPartitionReaderDbzOps() + CdcPartitionReaderDebeziumOperations = TestCdcPartitionReaderDbzOps() inner class TestCdcPartitionsCreatorDbzOps : - AbstractCdcPartitionsCreatorDbzOps() { - override fun position(offset: DebeziumOffset): BsonTimestamp { + AbstractCdcPartitionsCreatorDbzOps() { + override fun position(offset: DebeziumOffset): BsonTimestampPosition { val offsetValue: ObjectNode = offset.wrapped.values.first() as ObjectNode - return BsonTimestamp(offsetValue["sec"].asInt(), offsetValue["ord"].asInt()) + return BsonTimestampPosition( + BsonTimestamp(offsetValue["sec"].asInt(), offsetValue["ord"].asInt()) + ) } override fun generateColdStartOffset(): DebeziumOffset { @@ -146,17 +157,22 @@ class CdcPartitionReaderMongoTest : } } - inner class TestCdcPartitionReaderDbzOps : AbstractCdcPartitionReaderDbzOps() { - override fun position(recordValue: DebeziumRecordValue): BsonTimestamp? { + inner class TestCdcPartitionReaderDbzOps : + AbstractCdcPartitionReaderDbzOps() { + override fun position(recordValue: DebeziumRecordValue): BsonTimestampPosition? { val resumeToken: String = recordValue.source["resume_token"]?.takeIf { it.isTextual }?.asText() ?: return null - return ResumeTokens.getTimestamp(ResumeTokens.fromData(resumeToken)) + return BsonTimestampPosition( + ResumeTokens.getTimestamp(ResumeTokens.fromData(resumeToken)) + ) } - override fun position(sourceRecord: SourceRecord): BsonTimestamp? { + override fun position(sourceRecord: SourceRecord): BsonTimestampPosition? { val offset: Map = sourceRecord.sourceOffset() val resumeTokenBase64: String = offset["resume_token"] as? String ?: return null - return ResumeTokens.getTimestamp(ResumeTokens.fromBase64(resumeTokenBase64)) + return BsonTimestampPosition( + ResumeTokens.getTimestamp(ResumeTokens.fromBase64(resumeTokenBase64)) + ) } override fun deserializeRecord( diff --git a/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderMySQLTest.kt b/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderMySQLTest.kt index 1000b7f87480..13c410139335 100644 --- a/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderMySQLTest.kt +++ b/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderMySQLTest.kt @@ -24,8 +24,8 @@ class CdcPartitionReaderMySQLTest : namespace = "test", ) { - data class Position(val file: String, val pos: Long) : Comparable { - override fun compareTo(other: Position): Int = + data class Position(val file: String, val pos: Long) : PartiallyOrdered { + override fun compareTo(other: Position): Int? = file.compareTo(other.file).takeUnless { it == 0 } ?: pos.compareTo(other.pos) } diff --git a/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderPostgresTest.kt b/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderPostgresTest.kt index 74eff950da29..d09c3796ecc4 100644 --- a/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderPostgresTest.kt +++ b/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionReaderPostgresTest.kt @@ -18,8 +18,12 @@ import org.postgresql.replication.LogSequenceNumber import org.testcontainers.containers.PostgreSQLContainer import org.testcontainers.utility.DockerImageName +data class LsnPosition(val lsn: LogSequenceNumber) : PartiallyOrdered { + override fun compareTo(other: LsnPosition): Int? = lsn.asLong().compareTo(other.lsn.asLong()) +} + class CdcPartitionReaderPostgresTest : - AbstractCdcPartitionReaderTest>( + AbstractCdcPartitionReaderTest>( namespace = "public", ) { @@ -77,11 +81,10 @@ class CdcPartitionReaderPostgresTest : override fun createCdcPartitionReaderDbzOps() = TestCdcPartitionReaderDbzOps() - inner class TestCdcPartitionsCreatorDbzOps : - AbstractCdcPartitionsCreatorDbzOps() { - override fun position(offset: DebeziumOffset): LogSequenceNumber { + inner class TestCdcPartitionsCreatorDbzOps : AbstractCdcPartitionsCreatorDbzOps() { + override fun position(offset: DebeziumOffset): LsnPosition { val offsetValue: ObjectNode = offset.wrapped.values.first() as ObjectNode - return LogSequenceNumber.valueOf(offsetValue["lsn"].asLong()) + return LsnPosition(LogSequenceNumber.valueOf(offsetValue["lsn"].asLong())) } override fun generateWarmStartProperties(streams: List): Map = @@ -131,18 +134,17 @@ class CdcPartitionReaderPostgresTest : } } - inner class TestCdcPartitionReaderDbzOps : - AbstractCdcPartitionReaderDbzOps() { - override fun position(recordValue: DebeziumRecordValue): LogSequenceNumber? { + inner class TestCdcPartitionReaderDbzOps : AbstractCdcPartitionReaderDbzOps() { + override fun position(recordValue: DebeziumRecordValue): LsnPosition? { val lsn: Long = recordValue.source["lsn"]?.takeIf { it.isIntegralNumber }?.asLong() ?: return null - return LogSequenceNumber.valueOf(lsn) + return LsnPosition(LogSequenceNumber.valueOf(lsn)) } - override fun position(sourceRecord: SourceRecord): LogSequenceNumber? { + override fun position(sourceRecord: SourceRecord): LsnPosition? { val offset: Map = sourceRecord.sourceOffset() val lsn: Long = offset["lsn"] as? Long ?: return null - return LogSequenceNumber.valueOf(lsn) + return LsnPosition(LogSequenceNumber.valueOf(lsn)) } } } diff --git a/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreatorTest.kt b/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreatorTest.kt index e7c93a81efa0..c09855c5a693 100644 --- a/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreatorTest.kt +++ b/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/CdcPartitionsCreatorTest.kt @@ -6,7 +6,7 @@ package io.airbyte.cdk.read.cdc import io.airbyte.cdk.ConfigErrorException import io.airbyte.cdk.StreamIdentifier -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.discover.StringFieldType import io.airbyte.cdk.discover.TestMetaFieldDecorator import io.airbyte.cdk.read.ConcurrencyResource @@ -18,9 +18,11 @@ import io.airbyte.cdk.read.ResourceAcquirer import io.airbyte.cdk.read.Stream import io.airbyte.cdk.util.Jsons import io.airbyte.protocol.models.v0.StreamDescriptor +import io.mockk.Runs import io.mockk.every import io.mockk.impl.annotations.MockK import io.mockk.junit5.MockKExtension +import io.mockk.just import java.util.concurrent.atomic.AtomicReference import kotlinx.coroutines.runBlocking import org.junit.Assert.assertThrows @@ -29,7 +31,9 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith -typealias CreatorPosition = Long +data class CreatorPosition(val value: Long) : PartiallyOrdered { + override fun compareTo(other: CreatorPosition): Int? = value.compareTo(other.value) +} /** These unit tests play out the scenarios possible in [CdcPartitionsCreator.run]. */ @ExtendWith(MockKExtension::class) @@ -46,7 +50,8 @@ class CdcPartitionsCreatorTest { val stream = Stream( id = StreamIdentifier.from(StreamDescriptor().withName("test")), - schema = setOf(Field("test", StringFieldType), TestMetaFieldDecorator.GlobalCursor), + schema = + setOf(EmittedField("test", StringFieldType), TestMetaFieldDecorator.GlobalCursor), configuredSyncMode = ConfiguredSyncMode.INCREMENTAL, configuredPrimaryKey = null, configuredCursor = TestMetaFieldDecorator.GlobalCursor, @@ -79,8 +84,9 @@ class CdcPartitionsCreatorTest { every { globalFeedBootstrap.feed } returns global every { globalFeedBootstrap.feeds } returns listOf(global, stream) every { globalFeedBootstrap.streamRecordConsumers() } returns emptyMap() - every { creatorOps.position(syntheticOffset) } returns 123L - every { creatorOps.position(incumbentOffset) } returns 123L + every { creatorOps.position(syntheticOffset) } returns CreatorPosition(123L) + every { creatorOps.position(incumbentOffset) } returns CreatorPosition(123L) + every { creatorOps.runStartup(any()) } just Runs every { creatorOps.generateColdStartOffset() } returns syntheticOffset every { creatorOps.generateColdStartProperties(streams) } returns emptyMap() every { creatorOps.generateWarmStartProperties(streams) } returns emptyMap() @@ -91,13 +97,13 @@ class CdcPartitionsCreatorTest { every { globalFeedBootstrap.currentState } returns null every { globalFeedBootstrap.currentState(stream) } returns null val syntheticOffset = DebeziumOffset(mapOf(Jsons.nullNode() to Jsons.nullNode())) - every { creatorOps.position(syntheticOffset) } returns 123L + every { creatorOps.position(syntheticOffset) } returns CreatorPosition(123L) every { creatorOps.generateColdStartOffset() } returns syntheticOffset upperBoundReference.set(null) val readers: List = runBlocking { creator.run() } Assertions.assertEquals(1, readers.size) val reader = readers.first() as CdcPartitionReader<*> - Assertions.assertEquals(123L, reader.upperBound) + Assertions.assertEquals(CreatorPosition(123L), reader.upperBound) Assertions.assertEquals(syntheticOffset, reader.startingOffset) } @@ -108,11 +114,11 @@ class CdcPartitionsCreatorTest { val deserializedState = ValidDebeziumWarmStartState(offset = incumbentOffset, schemaHistory = null) every { creatorOps.deserializeState(Jsons.objectNode()) } returns deserializedState - upperBoundReference.set(1_000_000L) + upperBoundReference.set(CreatorPosition(1_000_000L)) val readers: List = runBlocking { creator.run() } Assertions.assertEquals(1, readers.size) val reader = readers.first() as CdcPartitionReader<*> - Assertions.assertEquals(1_000_000L, reader.upperBound) + Assertions.assertEquals(CreatorPosition(1_000_000L), reader.upperBound) Assertions.assertEquals(deserializedState.offset, reader.startingOffset) } @@ -123,7 +129,7 @@ class CdcPartitionsCreatorTest { val deserializedState = ValidDebeziumWarmStartState(offset = incumbentOffset, schemaHistory = null) every { creatorOps.deserializeState(Jsons.objectNode()) } returns deserializedState - upperBoundReference.set(1L) + upperBoundReference.set(CreatorPosition(1L)) val readers: List = runBlocking { creator.run() } Assertions.assertEquals(emptyList(), readers) } diff --git a/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/DebeziumPropertiesBuilderTest.kt b/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/DebeziumPropertiesBuilderTest.kt index 34ae5158ed68..d6bdd5280323 100644 --- a/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/DebeziumPropertiesBuilderTest.kt +++ b/airbyte-cdk/bulk/toolkits/extract-cdc/src/test/kotlin/io/airbyte/cdk/read/cdc/DebeziumPropertiesBuilderTest.kt @@ -5,7 +5,7 @@ package io.airbyte.cdk.read.cdc import io.airbyte.cdk.StreamIdentifier -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.discover.IntFieldType import io.airbyte.cdk.discover.OffsetDateTimeFieldType import io.airbyte.cdk.discover.StringFieldType @@ -41,7 +41,7 @@ class DebeziumPropertiesBuilderTest { @Test fun testWithStreams() { - fun stream(namespace: String, name: String, vararg fields: Field): Stream = + fun stream(namespace: String, name: String, vararg fields: EmittedField): Stream = Stream( id = StreamIdentifier.from( @@ -54,13 +54,18 @@ class DebeziumPropertiesBuilderTest { ) val streams: List = listOf( - stream("schema1", "table1", Field("k", IntFieldType), Field("v", StringFieldType)), + stream( + "schema1", + "table1", + EmittedField("k", IntFieldType), + EmittedField("v", StringFieldType) + ), stream( "schema2", "table2", - Field("id", IntFieldType), - Field("ts", OffsetDateTimeFieldType), - Field("msg", StringFieldType) + EmittedField("id", IntFieldType), + EmittedField("ts", OffsetDateTimeFieldType), + EmittedField("msg", StringFieldType) ), ) val actual: Map = diff --git a/airbyte-cdk/bulk/toolkits/extract-cdc/src/testFixtures/kotlin/io/airbyte/cdk/read/cdc/AbstractCdcPartitionReaderTest.kt b/airbyte-cdk/bulk/toolkits/extract-cdc/src/testFixtures/kotlin/io/airbyte/cdk/read/cdc/AbstractCdcPartitionReaderTest.kt index 6f410e1fde5b..6e517e5867a5 100644 --- a/airbyte-cdk/bulk/toolkits/extract-cdc/src/testFixtures/kotlin/io/airbyte/cdk/read/cdc/AbstractCdcPartitionReaderTest.kt +++ b/airbyte-cdk/bulk/toolkits/extract-cdc/src/testFixtures/kotlin/io/airbyte/cdk/read/cdc/AbstractCdcPartitionReaderTest.kt @@ -14,7 +14,7 @@ import io.airbyte.cdk.StreamIdentifier import io.airbyte.cdk.command.OpaqueStateValue import io.airbyte.cdk.data.IntCodec import io.airbyte.cdk.data.TextCodec -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.discover.IntFieldType import io.airbyte.cdk.discover.TestMetaFieldDecorator import io.airbyte.cdk.output.BufferingOutputConsumer @@ -60,7 +60,7 @@ import org.junit.jupiter.api.extension.ExtendWith */ @SuppressFBWarnings(value = ["NP_NONNULL_RETURN_VIOLATION"], justification = "Micronaut DI") @ExtendWith(MockKExtension::class) -abstract class AbstractCdcPartitionReaderTest, C : AutoCloseable>( +abstract class AbstractCdcPartitionReaderTest, C : AutoCloseable>( namespace: String?, val heartbeat: Duration = Duration.ofMillis(100), val timeout: Duration = Duration.ofSeconds(10), @@ -73,7 +73,7 @@ abstract class AbstractCdcPartitionReaderTest, C : AutoCloseab val stream = Stream( id = StreamIdentifier.from(StreamDescriptor().withName("tbl").withNamespace(namespace)), - schema = setOf(Field("v", IntFieldType), TestMetaFieldDecorator.GlobalCursor), + schema = setOf(EmittedField("v", IntFieldType), TestMetaFieldDecorator.GlobalCursor), configuredSyncMode = ConfiguredSyncMode.INCREMENTAL, configuredPrimaryKey = null, configuredCursor = TestMetaFieldDecorator.GlobalCursor, @@ -115,7 +115,7 @@ abstract class AbstractCdcPartitionReaderTest, C : AutoCloseab override val stream: Stream = this@AbstractCdcPartitionReaderTest.stream override fun accept( recordData: NativeRecordPayload, - changes: Map? + changes: Map? ) { outputConsumer.accept( AirbyteRecordMessage() @@ -290,7 +290,7 @@ abstract class AbstractCdcPartitionReaderTest, C : AutoCloseab data class Update(override val id: Int, val v: Int) : Record data class Delete(override val id: Int, val ignore: Boolean = false) : Record - abstract inner class AbstractCdcPartitionsCreatorDbzOps> : + abstract inner class AbstractCdcPartitionsCreatorDbzOps> : CdcPartitionsCreatorDebeziumOperations { override fun deserializeState(opaqueStateValue: OpaqueStateValue): DebeziumWarmStartState { @@ -318,7 +318,7 @@ abstract class AbstractCdcPartitionReaderTest, C : AutoCloseab } } - abstract inner class AbstractCdcPartitionReaderDbzOps> : + abstract inner class AbstractCdcPartitionReaderDbzOps> : CdcPartitionReaderDebeziumOperations { override fun deserializeRecord( diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/discover/JdbcAirbyteStreamFactory.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/discover/JdbcAirbyteStreamFactory.kt index bda87e982b9d..afa0428d6ec6 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/discover/JdbcAirbyteStreamFactory.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/discover/JdbcAirbyteStreamFactory.kt @@ -54,10 +54,11 @@ interface JdbcAirbyteStreamFactory : AirbyteStreamFactory, MetaFieldDecorator { if (discoveredStream.primaryKeyColumnIDs.isEmpty()) { return false } - val allColumnsByID: Map = discoveredStream.columns.associateBy { it.id } + val allColumnsByID: Map = + discoveredStream.columns.associateBy { it.id } return discoveredStream.primaryKeyColumnIDs.all { idComponents: List -> val id: String = idComponents.joinToString(separator = ".") - val field: Field? = allColumnsByID[id] + val field: EmittedField? = allColumnsByID[id] field != null && isPossiblePrimaryKeyElement(field) } } @@ -76,7 +77,7 @@ interface JdbcAirbyteStreamFactory : AirbyteStreamFactory, MetaFieldDecorator { * objects. For instance if the [Field.type] does not map to a [LosslessFieldType] then the * field can't reliably round-trip checkpoint values during a resumable initial sync. */ - fun isPossiblePrimaryKeyElement(field: Field): Boolean = + fun isPossiblePrimaryKeyElement(field: EmittedField): Boolean = when (field.type) { !is LosslessFieldType -> false CharacterStreamFieldType, @@ -94,6 +95,6 @@ interface JdbcAirbyteStreamFactory : AirbyteStreamFactory, MetaFieldDecorator { * to round-trip the column values, we need to be able to query the max value from the source at * the start of the sync. */ - fun isPossibleCursor(field: Field): Boolean = + fun isPossibleCursor(field: EmittedField): Boolean = isPossiblePrimaryKeyElement(field) && field.type !is BooleanFieldType } diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/discover/JdbcMetadataQuerier.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/discover/JdbcMetadataQuerier.kt index d87d9de44550..90cf769b63b8 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/discover/JdbcMetadataQuerier.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/discover/JdbcMetadataQuerier.kt @@ -34,6 +34,7 @@ class JdbcMetadataQuerier( val checkQueries: JdbcCheckQueries, jdbcConnectionFactory: JdbcConnectionFactory, ) : MetadataQuerier { + val conn: Connection = jdbcConnectionFactory.get() private val log = KotlinLogging.logger {} @@ -126,7 +127,6 @@ class JdbcMetadataQuerier( log.info { "Querying column names for catalog discovery." } try { val dbmd: DatabaseMetaData = conn.metaData - fun addColumnsFromQuery( catalog: String?, schema: String?, @@ -160,11 +160,15 @@ class JdbcMetadataQuerier( ?.value if (patterns != null && patterns.isNotEmpty()) { for (pattern in patterns) { - addColumnsFromQuery(catalog, schema, pattern, isPseudoColumn = true) + if (constants.includePseudoColumns) { + addColumnsFromQuery(catalog, schema, pattern, isPseudoColumn = true) + } addColumnsFromQuery(catalog, schema, pattern, isPseudoColumn = false) } } else { - addColumnsFromQuery(catalog, schema, null, isPseudoColumn = true) + if (constants.includePseudoColumns) { + addColumnsFromQuery(catalog, schema, null, isPseudoColumn = true) + } addColumnsFromQuery(catalog, schema, null, isPseudoColumn = false) } } @@ -247,9 +251,9 @@ class JdbcMetadataQuerier( override fun fields( streamID: StreamIdentifier, - ): List { + ): List { val table: TableName = findTableName(streamID) ?: return listOf() - return columnMetadata(table).map { Field(it.label, fieldTypeMapper.toFieldType(it)) } + return columnMetadata(table).map { EmittedField(it.label, fieldTypeMapper.toFieldType(it)) } } fun columnMetadata(table: TableName): List { @@ -279,7 +283,7 @@ class JdbcMetadataQuerier( ): String { val querySpec = SelectQuerySpec( - SelectColumns(columnIDs.map { Field(it, NullFieldType) }), + SelectColumns(columnIDs.map { EmittedField(it, NullFieldType) }), From(table.name, table.namespace()), limit = Limit(0), ) @@ -400,7 +404,7 @@ class JdbcMetadataQuerier( selectQueryGenerator, fieldTypeMapper, checkQueries, - jdbcConnectionFactory, + jdbcConnectionFactory ) } } diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/DefaultJdbcConstants.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/DefaultJdbcConstants.kt index e783338937b5..6782b78e1e99 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/DefaultJdbcConstants.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/DefaultJdbcConstants.kt @@ -31,6 +31,8 @@ data class DefaultJdbcConstants( /** Whether the namespace field denotes a JDBC schema or a JDBC catalog. */ val namespaceKind: NamespaceKind = NamespaceKind.SCHEMA, val maxSequentialQueryLimit: Long? = MAX_SEQUENTIAL_QUERY_LIMIT_NULL, + /** Whether to fetch pseudo-columns when querying column metadata. */ + val includePseudoColumns: Boolean = true, ) { enum class NamespaceKind { diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/JdbcAccessor.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/JdbcAccessor.kt index e5a084891194..534699653aa6 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/JdbcAccessor.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/JdbcAccessor.kt @@ -15,6 +15,7 @@ import java.sql.Timestamp import java.time.LocalDate import java.time.LocalDateTime import java.time.LocalTime +import java.time.OffsetDateTime /** Combination of [JdbcGetter] and [JdbcSetter]. */ interface JdbcAccessor : JdbcGetter, JdbcSetter @@ -306,7 +307,15 @@ data object DateAccessor : JdbcAccessor { override fun get( rs: ResultSet, colIdx: Int, - ): LocalDate? = rs.getDate(colIdx)?.takeUnless { rs.wasNull() }?.toLocalDate() + ): LocalDate? { + val dateStr = rs.getString(colIdx) + return when { + rs.wasNull() -> null + dateStr == "infinity" || dateStr == "-infinity" -> + throw IllegalStateException("Date '$dateStr' is not supported") + else -> rs.getDate(colIdx).toLocalDate() + } + } override fun set( stmt: PreparedStatement, @@ -336,7 +345,15 @@ data object TimestampAccessor : JdbcAccessor { override fun get( rs: ResultSet, colIdx: Int, - ): LocalDateTime? = rs.getTimestamp(colIdx)?.takeUnless { rs.wasNull() }?.toLocalDateTime() + ): LocalDateTime? { + val timestampStr = rs.getString(colIdx) + return when { + rs.wasNull() -> null + timestampStr == "infinity" || timestampStr == "-infinity" -> + throw IllegalStateException("Timestamp '$timestampStr' is not supported") + else -> rs.getTimestamp(colIdx).toLocalDateTime() + } + } override fun set( stmt: PreparedStatement, @@ -347,6 +364,21 @@ data object TimestampAccessor : JdbcAccessor { } } +data object TimestampTzGetter : JdbcGetter { + override fun get( + rs: ResultSet, + colIdx: Int, + ): OffsetDateTime? { + val timestampStr = rs.getString(colIdx) + return when { + rs.wasNull() -> null + timestampStr == "infinity" || timestampStr == "-infinity" -> + throw IllegalStateException("Timestamp '$timestampStr' is not supported") + else -> rs.getObject(colIdx, OffsetDateTime::class.java) + } + } +} + data object XmlAccessor : JdbcAccessor { override fun get( rs: ResultSet, @@ -416,6 +448,9 @@ data class AnySetter( data class ArrayGetter( val elementGetter: JdbcGetter, ) : JdbcGetter> { + // TODO: Allow partial success. + // Catch exceptions for individual values and replace with null. + // This requires returning both a list of values and a list of exceptions. override fun get( rs: ResultSet, colIdx: Int, diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/JdbcConnectionFactory.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/JdbcConnectionFactory.kt index 7ab36e78c8eb..a06f6d3a80de 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/JdbcConnectionFactory.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/JdbcConnectionFactory.kt @@ -23,7 +23,7 @@ private val log = KotlinLogging.logger {} * SSH tunnel session is shared by many connections. */ @Singleton -class JdbcConnectionFactory( +open class JdbcConnectionFactory( val config: JdbcSourceConfiguration, ) : Supplier { diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/JdbcFieldTypes.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/JdbcFieldTypes.kt index e6bba19b8da9..9bcafa2106f7 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/JdbcFieldTypes.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/jdbc/JdbcFieldTypes.kt @@ -273,7 +273,7 @@ data object OffsetTimeFieldType : data object OffsetDateTimeFieldType : LosslessJdbcFieldType( LeafAirbyteSchemaType.TIMESTAMP_WITH_TIMEZONE, - ObjectGetter(OffsetDateTime::class.java), + TimestampTzGetter, OffsetDateTimeCodec, OffsetDateTimeCodec, AnyAccessor, diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/DefaultJdbcPartition.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/DefaultJdbcPartition.kt index 71c37a9b5cb8..f2b5b1ff0895 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/DefaultJdbcPartition.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/DefaultJdbcPartition.kt @@ -5,9 +5,9 @@ package io.airbyte.cdk.read import com.fasterxml.jackson.databind.JsonNode -import com.fasterxml.jackson.databind.node.ObjectNode import io.airbyte.cdk.command.OpaqueStateValue -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField +import io.airbyte.cdk.output.sockets.toJson import io.airbyte.cdk.util.Jsons /** Base class for default implementations of [JdbcPartition]. */ @@ -57,7 +57,7 @@ class DefaultJdbcUnsplittableSnapshotPartition( class DefaultJdbcUnsplittableSnapshotWithCursorPartition( selectQueryGenerator: SelectQueryGenerator, streamState: DefaultJdbcStreamState, - val cursor: Field, + val cursor: EmittedField, ) : DefaultJdbcUnsplittablePartition(selectQueryGenerator, streamState), JdbcCursorPartition { @@ -79,7 +79,7 @@ class DefaultJdbcUnsplittableSnapshotWithCursorPartition( sealed class DefaultJdbcSplittablePartition( selectQueryGenerator: SelectQueryGenerator, streamState: DefaultJdbcStreamState, - val checkpointColumns: List, + val checkpointColumns: List, ) : DefaultJdbcPartition(selectQueryGenerator, streamState), JdbcSplittablePartition { @@ -118,10 +118,10 @@ sealed class DefaultJdbcSplittablePartition( val where: WhereNode get() { - val zippedLowerBound: List> = + val zippedLowerBound: List> = lowerBound?.let { checkpointColumns.zip(it) } ?: listOf() val lowerBoundDisj: List = - zippedLowerBound.mapIndexed { idx: Int, (gtCol: Field, gtValue: JsonNode) -> + zippedLowerBound.mapIndexed { idx: Int, (gtCol: EmittedField, gtValue: JsonNode) -> val lastLeaf: WhereClauseLeafNode = if (isLowerBoundIncluded && idx == checkpointColumns.size - 1) { GreaterOrEqual(gtCol, gtValue) @@ -129,15 +129,16 @@ sealed class DefaultJdbcSplittablePartition( Greater(gtCol, gtValue) } And( - zippedLowerBound.take(idx).map { (eqCol: Field, eqValue: JsonNode) -> + zippedLowerBound.take(idx).map { (eqCol: EmittedField, eqValue: JsonNode) -> Equal(eqCol, eqValue) } + listOf(lastLeaf), ) } - val zippedUpperBound: List> = + val zippedUpperBound: List> = upperBound?.let { checkpointColumns.zip(it) } ?: listOf() val upperBoundDisj: List = - zippedUpperBound.mapIndexed { idx: Int, (leqCol: Field, leqValue: JsonNode) -> + zippedUpperBound.mapIndexed { idx: Int, (leqCol: EmittedField, leqValue: JsonNode) + -> val lastLeaf: WhereClauseLeafNode = if (idx < zippedUpperBound.size - 1) { Lesser(leqCol, leqValue) @@ -145,7 +146,7 @@ sealed class DefaultJdbcSplittablePartition( LesserOrEqual(leqCol, leqValue) } And( - zippedUpperBound.take(idx).map { (eqCol: Field, eqValue: JsonNode) -> + zippedUpperBound.take(idx).map { (eqCol: EmittedField, eqValue: JsonNode) -> Equal(eqCol, eqValue) } + listOf(lastLeaf), ) @@ -177,7 +178,7 @@ sealed class DefaultJdbcSplittablePartition( class DefaultJdbcSplittableSnapshotPartition( selectQueryGenerator: SelectQueryGenerator, streamState: DefaultJdbcStreamState, - primaryKey: List, + primaryKey: List, override val lowerBound: List?, override val upperBound: List?, ) : DefaultJdbcSplittablePartition(selectQueryGenerator, streamState, primaryKey) { @@ -193,10 +194,11 @@ class DefaultJdbcSplittableSnapshotPartition( ) } - override fun incompleteState(lastRecord: ObjectNode): OpaqueStateValue = + override fun incompleteState(lastRecord: SelectQuerier.ResultRow): OpaqueStateValue = DefaultJdbcStreamStateValue.snapshotCheckpoint( primaryKey = checkpointColumns, - primaryKeyCheckpoint = checkpointColumns.map { lastRecord[it.id] ?: Jsons.nullNode() }, + primaryKeyCheckpoint = + checkpointColumns.map { lastRecord.data.toJson()[it.id] ?: Jsons.nullNode() }, ) } @@ -206,8 +208,8 @@ class DefaultJdbcSplittableSnapshotPartition( sealed class DefaultJdbcCursorPartition( selectQueryGenerator: SelectQueryGenerator, streamState: DefaultJdbcStreamState, - checkpointColumns: List, - val cursor: Field, + checkpointColumns: List, + val cursor: EmittedField, private val explicitCursorUpperBound: JsonNode?, ) : DefaultJdbcSplittablePartition(selectQueryGenerator, streamState, checkpointColumns), @@ -229,10 +231,10 @@ sealed class DefaultJdbcCursorPartition( class DefaultJdbcSplittableSnapshotWithCursorPartition( selectQueryGenerator: SelectQueryGenerator, streamState: DefaultJdbcStreamState, - primaryKey: List, + primaryKey: List, override val lowerBound: List?, override val upperBound: List?, - cursor: Field, + cursor: EmittedField, cursorUpperBound: JsonNode?, ) : DefaultJdbcCursorPartition( @@ -260,10 +262,11 @@ class DefaultJdbcSplittableSnapshotWithCursorPartition( ) } - override fun incompleteState(lastRecord: ObjectNode): OpaqueStateValue = + override fun incompleteState(lastRecord: SelectQuerier.ResultRow): OpaqueStateValue = DefaultJdbcStreamStateValue.snapshotWithCursorCheckpoint( primaryKey = checkpointColumns, - primaryKeyCheckpoint = checkpointColumns.map { lastRecord[it.id] ?: Jsons.nullNode() }, + primaryKeyCheckpoint = + checkpointColumns.map { lastRecord.data.toJson()[it.id] ?: Jsons.nullNode() }, cursor, cursorUpperBound, ) @@ -276,7 +279,7 @@ class DefaultJdbcSplittableSnapshotWithCursorPartition( class DefaultJdbcCursorIncrementalPartition( selectQueryGenerator: SelectQueryGenerator, streamState: DefaultJdbcStreamState, - cursor: Field, + cursor: EmittedField, val cursorLowerBound: JsonNode, override val isLowerBoundIncluded: Boolean, cursorUpperBound: JsonNode?, @@ -300,9 +303,9 @@ class DefaultJdbcCursorIncrementalPartition( cursorCheckpoint = cursorUpperBound, ) - override fun incompleteState(lastRecord: ObjectNode): OpaqueStateValue = + override fun incompleteState(lastRecord: SelectQuerier.ResultRow): OpaqueStateValue = DefaultJdbcStreamStateValue.cursorIncrementalCheckpoint( cursor, - cursorCheckpoint = lastRecord[cursor.id] ?: Jsons.nullNode(), + cursorCheckpoint = lastRecord.data.toJson()[cursor.id] ?: Jsons.nullNode(), ) } diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/DefaultJdbcPartitionFactory.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/DefaultJdbcPartitionFactory.kt index 8bcd6e20c54e..6149801b4893 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/DefaultJdbcPartitionFactory.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/DefaultJdbcPartitionFactory.kt @@ -9,8 +9,8 @@ import io.airbyte.cdk.ConfigErrorException import io.airbyte.cdk.StreamIdentifier import io.airbyte.cdk.command.JdbcSourceConfiguration import io.airbyte.cdk.command.OpaqueStateValue -import io.airbyte.cdk.discover.Field -import io.airbyte.cdk.discover.FieldOrMetaField +import io.airbyte.cdk.discover.DataOrMetaField +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.output.CatalogValidationFailureHandler import io.airbyte.cdk.output.InvalidCursor import io.airbyte.cdk.output.InvalidPrimaryKey @@ -56,14 +56,14 @@ class DefaultJdbcPartitionFactory( } val sv: DefaultJdbcStreamStateValue = Jsons.treeToValue(opaqueStateValue, DefaultJdbcStreamStateValue::class.java) - val pkMap: Map = + val pkMap: Map = sv.pkMap(stream) ?: run { handler.accept(ResetStream(stream.id)) streamState.reset() return coldStart(streamState) } - val cursorPair: Pair? = + val cursorPair: Pair? = if (sv.cursors.isEmpty()) { null } else { @@ -97,7 +97,7 @@ class DefaultJdbcPartitionFactory( ) } } else { - val (cursor: Field, cursorCheckpoint: JsonNode) = cursorPair + val (cursor: EmittedField, cursorCheckpoint: JsonNode) = cursorPair if (!isCursorBasedIncremental) { handler.accept(ResetStream(stream.id)) streamState.reset() @@ -130,11 +130,11 @@ class DefaultJdbcPartitionFactory( } } - private fun DefaultJdbcStreamStateValue.pkMap(stream: Stream): Map? { + private fun DefaultJdbcStreamStateValue.pkMap(stream: Stream): Map? { if (primaryKey.isEmpty()) { return mapOf() } - val fields: List = stream.configuredPrimaryKey ?: listOf() + val fields: List = stream.configuredPrimaryKey ?: listOf() if (primaryKey.keys != fields.map { it.id }.toSet()) { handler.accept( InvalidPrimaryKey(stream.id, primaryKey.keys.toList()), @@ -144,7 +144,9 @@ class DefaultJdbcPartitionFactory( return fields.associateWith { primaryKey[it.id]!! } } - private fun DefaultJdbcStreamStateValue.cursorPair(stream: Stream): Pair? { + private fun DefaultJdbcStreamStateValue.cursorPair( + stream: Stream + ): Pair? { if (cursors.size > 1) { handler.accept( InvalidCursor(stream.id, cursors.keys.toString()), @@ -152,8 +154,8 @@ class DefaultJdbcPartitionFactory( return null } val cursorLabel: String = cursors.keys.first() - val cursor: FieldOrMetaField? = stream.schema.find { it.id == cursorLabel } - if (cursor !is Field) { + val cursor: DataOrMetaField? = stream.schema.find { it.id == cursorLabel } + if (cursor !is EmittedField) { handler.accept( InvalidCursor(stream.id, cursorLabel), ) @@ -170,7 +172,7 @@ class DefaultJdbcPartitionFactory( private fun coldStart(streamState: DefaultJdbcStreamState): DefaultJdbcPartition { val stream: Stream = streamState.stream - val pkChosenFromCatalog: List = stream.configuredPrimaryKey ?: listOf() + val pkChosenFromCatalog: List = stream.configuredPrimaryKey ?: listOf() if (stream.configuredSyncMode == ConfiguredSyncMode.FULL_REFRESH || configuration.global) { if (pkChosenFromCatalog.isEmpty()) { return DefaultJdbcUnsplittableSnapshotPartition( @@ -186,8 +188,8 @@ class DefaultJdbcPartitionFactory( upperBound = null, ) } - val cursorChosenFromCatalog: Field = - stream.configuredCursor as? Field ?: throw ConfigErrorException("no cursor") + val cursorChosenFromCatalog: EmittedField = + stream.configuredCursor as? EmittedField ?: throw ConfigErrorException("no cursor") if (pkChosenFromCatalog.isEmpty()) { return DefaultJdbcUnsplittableSnapshotWithCursorPartition( selectQueryGenerator, diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/DefaultJdbcStreamStateValue.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/DefaultJdbcStreamStateValue.kt index cf814764b853..280db3be2abf 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/DefaultJdbcStreamStateValue.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/DefaultJdbcStreamStateValue.kt @@ -7,7 +7,7 @@ package io.airbyte.cdk.read import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.JsonNode import io.airbyte.cdk.command.OpaqueStateValue -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.util.Jsons /** @@ -26,7 +26,7 @@ data class DefaultJdbcStreamStateValue( /** Value representing the progress of a ongoing snapshot not involving cursor columns. */ fun snapshotCheckpoint( - primaryKey: List, + primaryKey: List, primaryKeyCheckpoint: List, ): OpaqueStateValue = when (primaryKeyCheckpoint.first().isNull) { @@ -41,9 +41,9 @@ data class DefaultJdbcStreamStateValue( /** Value representing the progress of an ongoing snapshot involving cursor columns. */ fun snapshotWithCursorCheckpoint( - primaryKey: List, + primaryKey: List, primaryKeyCheckpoint: List, - cursor: Field, + cursor: EmittedField, cursorUpperBound: JsonNode, ): OpaqueStateValue = when (primaryKeyCheckpoint.first().isNull) { @@ -59,7 +59,7 @@ data class DefaultJdbcStreamStateValue( /** Value representing the progress of an ongoing incremental cursor read. */ fun cursorIncrementalCheckpoint( - cursor: Field, + cursor: EmittedField, cursorCheckpoint: JsonNode, ): OpaqueStateValue = when (cursorCheckpoint.isNull) { diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcPartition.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcPartition.kt index fe76774bf4ff..979a9cfe2436 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcPartition.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcPartition.kt @@ -4,7 +4,6 @@ package io.airbyte.cdk.read -import com.fasterxml.jackson.databind.node.ObjectNode import io.airbyte.cdk.command.OpaqueStateValue /** @@ -45,7 +44,7 @@ interface JdbcSplittablePartition> : JdbcPartition { fun resumableQuery(limit: Long): SelectQuery /** State value to emit when the partition is read up to (and including) [lastRecord]. */ - fun incompleteState(lastRecord: ObjectNode): OpaqueStateValue + fun incompleteState(lastRecord: SelectQuerier.ResultRow): OpaqueStateValue } /** A [JdbcPartition] which allows cursor-based incremental reads. */ diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcPartitionReader.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcPartitionReader.kt index a093b4497f77..b6a5904898d4 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcPartitionReader.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcPartitionReader.kt @@ -1,16 +1,15 @@ /* Copyright (c) 2026 Airbyte, Inc., all rights reserved. */ package io.airbyte.cdk.read -import com.fasterxml.jackson.databind.node.ObjectNode import edu.umd.cs.findbugs.annotations.SuppressFBWarnings import io.airbyte.cdk.TransientErrorException import io.airbyte.cdk.command.OpaqueStateValue -import io.airbyte.cdk.discover.Field -import io.airbyte.cdk.output.DataChannelMedium.* +import io.airbyte.cdk.discover.EmittedField +import io.airbyte.cdk.jdbc.JdbcConnectionFactory +import io.airbyte.cdk.output.DataChannelMedium.SOCKET +import io.airbyte.cdk.output.DataChannelMedium.STDIO import io.airbyte.cdk.output.OutputMessageRouter import io.airbyte.cdk.output.sockets.NativeRecordPayload -import io.airbyte.cdk.output.sockets.toJson -import io.airbyte.cdk.util.Jsons import io.airbyte.protocol.models.v0.AirbyteStateMessage import io.airbyte.protocol.models.v0.AirbyteStreamStatusTraceMessage import java.time.Duration @@ -28,7 +27,7 @@ sealed class JdbcPartitionReader

>( ) : PartitionReader { lateinit var outputMessageRouter: OutputMessageRouter - lateinit var outputRoute: ((NativeRecordPayload, Map?) -> Unit) + lateinit var outputRoute: ((NativeRecordPayload, Map?) -> Unit) protected var partitionId: String = generatePartitionId(4) val streamState: JdbcStreamState<*> = partition.streamState @@ -143,6 +142,7 @@ class JdbcNonResumablePartitionReader

>( numRecords.incrementAndGet() } } + streamState.validatePartition(partition, JdbcConnectionFactory(sharedState.configuration)) runComplete.set(true) } @@ -172,7 +172,7 @@ class JdbcResumablePartitionReader

>( val incumbentLimit = AtomicLong() val numRecords = AtomicLong() - val lastRecord = AtomicReference(null) + val lastRecord = AtomicReference(null) val runComplete = AtomicBoolean(false) override suspend fun run() { @@ -196,7 +196,7 @@ class JdbcResumablePartitionReader

>( .use { result: SelectQuerier.Result -> for (row in result) { out(row) - lastRecord.set(row.data.toJson(Jsons.objectNode())) + lastRecord.set(row) // Check activity periodically to handle timeout. if (numRecords.incrementAndGet() % fetchSize == 0L) { coroutineContext.ensureActive() @@ -233,7 +233,7 @@ class JdbcResumablePartitionReader

>( streamState.updateLimitState { it.down } } } - val checkpointState: OpaqueStateValue = partition.incompleteState(lastRecord.get()!!) + val checkpointState: OpaqueStateValue = partition.incompleteState(lastRecord.get()) return PartitionReadCheckpoint( checkpointState, numRecords.get(), diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcPartitionsCreator.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcPartitionsCreator.kt index 7c8b53e78725..e062b6d5f962 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcPartitionsCreator.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcPartitionsCreator.kt @@ -100,8 +100,8 @@ abstract class JdbcPartitionsCreator< } /** Collects a sample of rows in the unsplit partition. */ - fun collectSample( - recordMapper: (ObjectNode) -> T, + open fun collectSample( + recordMapper: (SelectQuerier.ResultRow) -> T, ): Sample { val values = mutableListOf() var previousWeight = 0L @@ -116,7 +116,7 @@ abstract class JdbcPartitionsCreator< val samplingQuery: SelectQuery = partition.samplingQuery(sampleRateInvPow2) selectQuerier.executeQuery(samplingQuery).use { for (row in it) { - values.add(recordMapper(row.data.toJson())) + values.add(recordMapper(row)) } } if (values.size < sharedState.maxSampleSize) { @@ -162,8 +162,9 @@ class JdbcSequentialPartitionsCreator< } if (streamState.fetchSize == null) { if (sharedState.withSampling) { - val rowByteSizeSample: Sample = - collectSample(sharedState.rowByteSizeEstimator()::apply) + val rowByteSizeSample: Sample = collectSample { + sharedState.rowByteSizeEstimator().apply(it.data.toJson()) + } val expectedTableByteSize: Long = rowByteSizeSample.sampledValues.sum() * rowByteSizeSample.valueWeight log.info { "Table memory size estimated at ${expectedTableByteSize shr 20} MiB." } @@ -187,13 +188,13 @@ class JdbcSequentialPartitionsCreator< return listOf(JdbcNonResumablePartitionReader(partition)) } // Happy path. - log.info { "Table will be read by sequential partition reader(s)." } + log.info { "Table will be read by sequential partition reader." } return listOf(JdbcResumablePartitionReader(partition)) } } /** Concurrent JDBC implementation of [PartitionsCreator]. */ -class JdbcConcurrentPartitionsCreator< +open class JdbcConcurrentPartitionsCreator< A : JdbcSharedState, S : JdbcStreamState, P : JdbcPartition, @@ -223,12 +224,14 @@ class JdbcConcurrentPartitionsCreator< return listOf(JdbcNonResumablePartitionReader(partition)) } // Sample the table for partition split boundaries and for record byte sizes. - val sample: Sample> = collectSample { record: ObjectNode -> - val boundary: OpaqueStateValue? = - (partition as? JdbcSplittablePartition<*>)?.incompleteState(record) - val rowByteSize: Long = sharedState.rowByteSizeEstimator().apply(record) - boundary to rowByteSize - } + val sample: Sample> = + collectSample { record: SelectQuerier.ResultRow -> + val boundary: OpaqueStateValue? = + (partition as? JdbcSplittablePartition<*>)?.incompleteState(record) + val rowByteSize: Long = + sharedState.rowByteSizeEstimator().apply(record.data.toJson()) + boundary to rowByteSize + } if (sample.kind == Sample.Kind.EMPTY) { log.info { "Sampling query found that the table was empty." } return listOf(CheckpointOnlyPartitionReader()) diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcStreamState.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcStreamState.kt index ebdcc72d7834..4a4c4dddf5a4 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcStreamState.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/JdbcStreamState.kt @@ -5,6 +5,7 @@ package io.airbyte.cdk.read import com.fasterxml.jackson.databind.JsonNode +import io.airbyte.cdk.jdbc.JdbcConnectionFactory /** * Encapsulates database-specific transient state for a particular [stream]. @@ -43,4 +44,9 @@ interface JdbcStreamState { /** Resets the transient state to its initial setting. */ fun reset() + + fun validatePartition( + partition: JdbcPartition<*>, + jdbcConnectionFactory: JdbcConnectionFactory + ) {} } diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/SelectQuerier.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/SelectQuerier.kt index a5bb60a5b60c..87b5f90a8626 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/SelectQuerier.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/SelectQuerier.kt @@ -4,7 +4,8 @@ package io.airbyte.cdk.read import com.fasterxml.jackson.databind.node.ObjectNode import io.airbyte.cdk.data.JsonEncoder import io.airbyte.cdk.data.NullCodec -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField +import io.airbyte.cdk.discover.NonEmittedField import io.airbyte.cdk.jdbc.JdbcConnectionFactory import io.airbyte.cdk.jdbc.JdbcFieldType import io.airbyte.cdk.output.sockets.FieldValueEncoder @@ -41,7 +42,8 @@ interface SelectQuerier { interface ResultRow { val data: NativeRecordPayload - val changes: Map + val changes: Map + val nonEmittedData: NativeRecordPayload } } @@ -57,7 +59,8 @@ class JdbcSelectQuerier( data class ResultRow( override val data: NativeRecordPayload = mutableMapOf(), - override var changes: MutableMap = mutableMapOf(), + override var changes: MutableMap = mutableMapOf(), + override var nonEmittedData: NativeRecordPayload = mutableMapOf(), ) : SelectQuerier.ResultRow class Result( @@ -137,25 +140,36 @@ class JdbcSelectQuerier( log.debug { "Getting value #$colIdx for $column." } val jdbcFieldType: JdbcFieldType<*> = column.type as JdbcFieldType<*> try { - @Suppress("UNCHECKED_CAST") - resultRow.data[column.id] = - FieldValueEncoder( - jdbcFieldType.jdbcGetter.get(rs!!, colIdx), - jdbcFieldType.jsonEncoder as JsonEncoder, - ) + if (column is NonEmittedField) { + @Suppress("UNCHECKED_CAST") // TODO: See if we can avoid an unchecked cast + resultRow.nonEmittedData[column.id] = + FieldValueEncoder( + jdbcFieldType.jdbcGetter.get(rs!!, colIdx), + jdbcFieldType.jsonEncoder as JsonEncoder, + ) + } else { + @Suppress("UNCHECKED_CAST") + resultRow.data[column.id] = + FieldValueEncoder( + jdbcFieldType.jdbcGetter.get(rs!!, colIdx), + jdbcFieldType.jsonEncoder as JsonEncoder, + ) + } } catch (e: Exception) { - resultRow.data[column.id] = - FieldValueEncoder( - null, - NullCodec // Use NullCodec for null values - ) // Use NullCodec for null values if (!hasLoggedException) { log.warn(e) { "Error deserializing value in column $column." } hasLoggedException = true } else { log.debug(e) { "Error deserializing value in column $column." } } - resultRow.changes.set(column, FieldValueChange.RETRIEVAL_FAILURE_TOTAL) + if (column is EmittedField) { + resultRow.changes[column] = FieldValueChange.RETRIEVAL_FAILURE_TOTAL + resultRow.data[column.id] = + FieldValueEncoder( + null, + NullCodec // Use NullCodec for null values + ) // Use NullCodec for null values + } } colIdx++ } @@ -189,3 +203,40 @@ class JdbcSelectQuerier( } } } + +/** + * Convenience function for executing a query that is expected to return exactly one row and + * extracting a single value from that row. + * + * @param jdbcConnectionFactory Factory for creating JDBC connections + * @param query SQL query string to execute (should return exactly one row) + * @param bindParameters Optional lambda to bind parameters to the PreparedStatement before + * execution + * @param withResultSet Lambda function to process the ResultSet and extract the desired value + * @param noResultsCase Lambda to execute if the query returns no results + * @param multipleResultsCase Lambda to execute if the query returns multiple results + * @return The value extracted from the single result row using the withRS function + */ +fun querySingleValue( + jdbcConnectionFactory: JdbcConnectionFactory, + query: String, + bindParameters: ((PreparedStatement) -> Unit)? = null, + withResultSet: (ResultSet) -> T, + noResultsCase: () -> Unit = { + throw IllegalStateException("Query unexpectedly produced no results: [$query]") + }, + multipleResultsCase: () -> Unit = { + throw IllegalStateException("Query unexpectedly produced more than one result: [$query]") + }, +): T { + jdbcConnectionFactory.get().use { connection -> + connection.prepareStatement(query).use { stmt -> + bindParameters?.invoke(stmt) + stmt.executeQuery().use { rs -> + if (!rs.next()) noResultsCase() + if (!rs.isLast) multipleResultsCase() + return withResultSet(rs) + } + } + } +} diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/SelectQuery.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/SelectQuery.kt index 48c3175559e6..833f4b015494 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/SelectQuery.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/SelectQuery.kt @@ -2,7 +2,7 @@ package io.airbyte.cdk.read import com.fasterxml.jackson.databind.JsonNode -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.DataField import io.airbyte.cdk.jdbc.LosslessJdbcFieldType /** @@ -11,7 +11,7 @@ import io.airbyte.cdk.jdbc.LosslessJdbcFieldType */ data class SelectQuery( val sql: String, - val columns: List, + val columns: List, val bindings: List, ) { data class Binding( diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/SelectQuerySpec.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/SelectQuerySpec.kt index 1d821605479d..23388479f35b 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/SelectQuerySpec.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/main/kotlin/io/airbyte/cdk/read/SelectQuerySpec.kt @@ -2,7 +2,7 @@ package io.airbyte.cdk.read import com.fasterxml.jackson.databind.JsonNode -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.DataField import java.math.BigDecimal /** @@ -21,19 +21,19 @@ data class SelectQuerySpec( ) sealed interface SelectNode { - val columns: List + val columns: List } data class SelectColumns( - override val columns: List, + override val columns: List, ) : SelectNode { - constructor(vararg columns: Field) : this(columns.toList()) + constructor(vararg columns: DataField) : this(columns.toList()) } data class SelectColumnMaxValue( - val column: Field, + val column: DataField, ) : SelectNode { - override val columns: List + override val columns: List get() = listOf(column) } @@ -65,6 +65,13 @@ data class FromSample( get() = 1L shl sampleRateInvPow2 } +fun FromNode.optimize(): FromNode = + when (this) { + NoFrom -> this + is From -> this + is FromSample -> where?.let { this.copy(where = where.optimize()) } ?: this + } + sealed interface WhereNode data object NoWhere : WhereNode @@ -88,41 +95,41 @@ data class Or( } sealed interface WhereClauseLeafNode : WhereClauseNode { - val column: Field + val column: DataField val bindingValue: JsonNode } data class GreaterOrEqual( - override val column: Field, + override val column: DataField, override val bindingValue: JsonNode, ) : WhereClauseLeafNode data class Greater( - override val column: Field, + override val column: DataField, override val bindingValue: JsonNode, ) : WhereClauseLeafNode data class LesserOrEqual( - override val column: Field, + override val column: DataField, override val bindingValue: JsonNode, ) : WhereClauseLeafNode data class Lesser( - override val column: Field, + override val column: DataField, override val bindingValue: JsonNode, ) : WhereClauseLeafNode data class Equal( - override val column: Field, + override val column: DataField, override val bindingValue: JsonNode, ) : WhereClauseLeafNode sealed interface OrderByNode data class OrderBy( - val columns: List, + val columns: List, ) : OrderByNode { - constructor(vararg columns: Field) : this(columns.toList()) + constructor(vararg columns: DataField) : this(columns.toList()) } data object NoOrderBy : OrderByNode @@ -136,7 +143,7 @@ data class Limit( data object NoLimit : LimitNode fun SelectQuerySpec.optimize(): SelectQuerySpec = - SelectQuerySpec(select.optimize(), from, where.optimize(), orderBy.optimize(), limit) + SelectQuerySpec(select.optimize(), from.optimize(), where.optimize(), orderBy.optimize(), limit) fun SelectNode.optimize(): SelectNode = when (this) { diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/discover/JdbcAirbyteStreamFactoryTest.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/discover/JdbcAirbyteStreamFactoryTest.kt index 26ac2e73ca0f..36269a13edd0 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/discover/JdbcAirbyteStreamFactoryTest.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/discover/JdbcAirbyteStreamFactoryTest.kt @@ -32,7 +32,12 @@ class JdbcAirbyteStreamFactoryTest { `when`(streamId.namespace).thenReturn("test_namespace") `when`(discoveredStream.id).thenReturn(streamId) `when`(discoveredStream.columns) - .thenReturn(listOf(Field("id", BigIntegerFieldType), Field("name", StringFieldType))) + .thenReturn( + listOf( + EmittedField("id", BigIntegerFieldType), + EmittedField("name", StringFieldType) + ) + ) } @Test @@ -85,7 +90,7 @@ class JdbcAirbyteStreamFactoryTest { `when`(config.isCdc()).thenReturn(false) `when`(discoveredStream.primaryKeyColumnIDs).thenReturn(emptyList()) `when`(discoveredStream.columns) - .thenReturn(listOf(Field("non_cursor_col", BooleanFieldType))) + .thenReturn(listOf(EmittedField("non_cursor_col", BooleanFieldType))) val factory = H2SourceOperations() val stream = factory.create(config, discoveredStream) diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/DefaultJdbcPartitionFactoryTest.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/DefaultJdbcPartitionFactoryTest.kt index f6ac9bca6a45..1f667792eb30 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/DefaultJdbcPartitionFactoryTest.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/DefaultJdbcPartitionFactoryTest.kt @@ -313,7 +313,7 @@ class DefaultJdbcPartitionFactoryTest { stream.namespace, sampleRateInvPow2 = 8, DefaultJdbcConstants.TABLE_SAMPLE_SIZE, - Where(Or(listOf(And(listOf(Greater(id, IntCodec.encode(22))))))), + Where(Greater(id, IntCodec.encode(22))), ), NoWhere, OrderBy(id), @@ -372,7 +372,7 @@ class DefaultJdbcPartitionFactoryTest { stream.namespace, sampleRateInvPow2 = 8, DefaultJdbcConstants.TABLE_SAMPLE_SIZE, - Where(Or(listOf(And(listOf(Greater(id, IntCodec.encode(22))))))), + Where(Greater(id, IntCodec.encode(22))), ), NoWhere, OrderBy(id) @@ -456,30 +456,8 @@ class DefaultJdbcPartitionFactoryTest { DefaultJdbcConstants.TABLE_SAMPLE_SIZE, Where( And( - Or( - listOf( - And( - listOf( - GreaterOrEqual( - ts, - LocalDateCodec.encode(cursorValue) - ) - ) - ) - ) - ), - Or( - listOf( - And( - listOf( - LesserOrEqual( - ts, - LocalDateCodec.encode(cursorUpperBound) - ) - ) - ) - ) - ) + GreaterOrEqual(ts, LocalDateCodec.encode(cursorValue)), + LesserOrEqual(ts, LocalDateCodec.encode(cursorUpperBound)) ) ), ), diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/JdbcPartitionsCreatorTest.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/JdbcPartitionsCreatorTest.kt index d86e7932c161..c20633cdca34 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/JdbcPartitionsCreatorTest.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/JdbcPartitionsCreatorTest.kt @@ -146,16 +146,7 @@ class JdbcPartitionsCreatorTest { stream().namespace, sampleRateInvPow2 = 16, sampleSize = 4, - where = - Where( - Or( - listOf( - And( - listOf(Greater(id, IntCodec.encode(22))) - ) - ) - ) - ) + where = Where(Greater(id, IntCodec.encode(22))) ), NoWhere, OrderBy(id) @@ -172,16 +163,7 @@ class JdbcPartitionsCreatorTest { stream().namespace, sampleRateInvPow2 = 8, sampleSize = 4, - where = - Where( - Or( - listOf( - And( - listOf(Greater(id, IntCodec.encode(22))) - ) - ) - ) - ) + where = Where(Greater(id, IntCodec.encode(22))) ), NoWhere, OrderBy(id) @@ -279,16 +261,7 @@ class JdbcPartitionsCreatorTest { stream().namespace, sampleRateInvPow2 = 16, sampleSize = 4, - where = - Where( - Or( - listOf( - And( - listOf(Greater(id, IntCodec.encode(22))) - ) - ) - ) - ) + where = Where(Greater(id, IntCodec.encode(22))) ), NoWhere, OrderBy(id) @@ -305,16 +278,7 @@ class JdbcPartitionsCreatorTest { stream().namespace, sampleRateInvPow2 = 8, sampleSize = 4, - where = - Where( - Or( - listOf( - And( - listOf(Greater(id, IntCodec.encode(22))) - ) - ) - ) - ) + where = Where(Greater(id, IntCodec.encode(22))) ), NoWhere, OrderBy(id) @@ -327,7 +291,7 @@ class JdbcPartitionsCreatorTest { ) ), ) - val expectedFetchSize = 674 // adjust this as needed based on inputs + val expectedFetchSize = 681 // adjust this as needed based on inputs val factory = sharedState.factory() val initialPartition = factory.create(stream.bootstrap(opaqueStateValue(pk = 22))).asPartition() diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/JdbcSelectQuerierTest.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/JdbcSelectQuerierTest.kt index 00ba619c3c2a..04c7724fb2ca 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/JdbcSelectQuerierTest.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/JdbcSelectQuerierTest.kt @@ -2,7 +2,7 @@ package io.airbyte.cdk.read import com.fasterxml.jackson.databind.JsonNode -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.h2.H2TestFixture import io.airbyte.cdk.h2source.H2SourceConfiguration import io.airbyte.cdk.h2source.H2SourceConfigurationFactory @@ -32,7 +32,8 @@ class JdbcSelectQuerierTest { h2.execute("INSERT INTO kv (k, v) VALUES (1, 'foo'), (2, 'bar'), (3, NULL);") } - val columns: List = listOf(Field("k", IntFieldType), Field("v", StringFieldType)) + val columns: List = + listOf(EmittedField("k", IntFieldType), EmittedField("v", StringFieldType)) @Test fun testVanilla() { diff --git a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/TestFixtures.kt b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/TestFixtures.kt index c811cbdd7d50..5c4392bcb4e1 100644 --- a/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/TestFixtures.kt +++ b/airbyte-cdk/bulk/toolkits/extract-jdbc/src/test/kotlin/io/airbyte/cdk/read/TestFixtures.kt @@ -11,7 +11,9 @@ import io.airbyte.cdk.StreamIdentifier import io.airbyte.cdk.command.JdbcSourceConfiguration import io.airbyte.cdk.command.OpaqueStateValue import io.airbyte.cdk.command.TableFilter -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.data.IntCodec +import io.airbyte.cdk.data.LocalDateCodec +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.discover.MetaField import io.airbyte.cdk.discover.MetaFieldDecorator import io.airbyte.cdk.jdbc.DefaultJdbcConstants @@ -23,6 +25,7 @@ import io.airbyte.cdk.output.BufferingOutputConsumer import io.airbyte.cdk.output.CatalogValidationFailure import io.airbyte.cdk.output.DataChannelFormat import io.airbyte.cdk.output.DataChannelMedium +import io.airbyte.cdk.output.sockets.FieldValueEncoder import io.airbyte.cdk.output.sockets.NativeRecordPayload import io.airbyte.cdk.ssh.SshConnectionOptions import io.airbyte.cdk.ssh.SshTunnelMethodConfiguration @@ -35,9 +38,9 @@ import org.junit.jupiter.api.Assertions object TestFixtures { - val id = Field("id", IntFieldType) - val ts = Field("ts", LocalDateFieldType) - val msg = Field("msg", StringFieldType) + val id = EmittedField("id", IntFieldType) + val ts = EmittedField("ts", LocalDateFieldType) + val msg = EmittedField("msg", StringFieldType) fun stream( withPK: Boolean = true, @@ -67,14 +70,15 @@ object TestFixtures { fun record( pk: Int? = null, cursor: LocalDate? = null, - ): ObjectNode = - Jsons.readTree( - listOfNotNull( - """ "${id.id}" : $pk """.takeIf { pk != null }, - """ "${ts.id}" : "$cursor" """.takeIf { cursor != null }, - ) - .joinToString(",", "{", "}") - ) as ObjectNode + ): SelectQuerier.ResultRow = + JdbcSelectQuerier.ResultRow( + mutableMapOf( + "id" to FieldValueEncoder(pk, IntCodec), + "ts" to FieldValueEncoder(cursor, LocalDateCodec) + ), + mutableMapOf(), + mutableMapOf(), + ) fun sharedState( global: Boolean = false, @@ -171,7 +175,8 @@ object TestFixtures { override fun next(): SelectQuerier.ResultRow = object : SelectQuerier.ResultRow { override val data: NativeRecordPayload = wrapped.next() - override val changes: Map = emptyMap() + override val changes: Map = emptyMap() + override val nonEmittedData: NativeRecordPayload = mutableMapOf() } override fun close() {} } diff --git a/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartition.kt b/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartition.kt index 78bb696210f7..ee97e48c6196 100644 --- a/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartition.kt +++ b/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartition.kt @@ -5,9 +5,9 @@ package io.airbyte.cdk import com.fasterxml.jackson.databind.JsonNode -import com.fasterxml.jackson.databind.node.ObjectNode import io.airbyte.cdk.command.OpaqueStateValue -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField +import io.airbyte.cdk.output.sockets.toJson import io.airbyte.cdk.read.And import io.airbyte.cdk.read.DefaultJdbcStreamStateValue import io.airbyte.cdk.read.Equal @@ -25,6 +25,7 @@ import io.airbyte.cdk.read.Or import io.airbyte.cdk.read.OrderBy import io.airbyte.cdk.read.SelectColumnMaxValue import io.airbyte.cdk.read.SelectColumns +import io.airbyte.cdk.read.SelectQuerier import io.airbyte.cdk.read.SelectQuery import io.airbyte.cdk.read.SelectQueryGenerator import io.airbyte.cdk.read.SelectQuerySpec @@ -91,7 +92,7 @@ class TriggerUnsplittableSnapshotPartition( class TriggerUnsplittableSnapshotWithCursorPartition( selectQueryGenerator: SelectQueryGenerator, streamState: TriggerStreamState, - val cursor: Field, + val cursor: EmittedField, config: TriggerTableConfig, ) : TriggerUnsplittablePartition(selectQueryGenerator, streamState, config), @@ -115,7 +116,7 @@ sealed class TriggerSplittablePartition( selectQueryGenerator: SelectQueryGenerator, streamState: TriggerStreamState, config: TriggerTableConfig, - val checkpointColumns: List, + val checkpointColumns: List, val triggerCdcPartitionState: TriggerCdcPartitionState? = null, ) : TriggerPartition(selectQueryGenerator, streamState, config), @@ -181,10 +182,10 @@ sealed class TriggerSplittablePartition( val where: Where get() { - val zippedLowerBound: List> = + val zippedLowerBound: List> = lowerBound?.let { checkpointColumns.zip(it) } ?: listOf() val lowerBoundDisj: List = - zippedLowerBound.mapIndexed { idx: Int, (gtCol: Field, gtValue: JsonNode) -> + zippedLowerBound.mapIndexed { idx: Int, (gtCol: EmittedField, gtValue: JsonNode) -> val lastLeaf: WhereClauseLeafNode = if (isLowerBoundIncluded && idx == checkpointColumns.size - 1) { GreaterOrEqual(gtCol, gtValue) @@ -192,15 +193,16 @@ sealed class TriggerSplittablePartition( Greater(gtCol, gtValue) } And( - zippedLowerBound.take(idx).map { (eqCol: Field, eqValue: JsonNode) -> + zippedLowerBound.take(idx).map { (eqCol: EmittedField, eqValue: JsonNode) -> Equal(eqCol, eqValue) } + listOf(lastLeaf), ) } - val zippedUpperBound: List> = + val zippedUpperBound: List> = upperBound?.let { checkpointColumns.zip(it) } ?: listOf() val upperBoundDisj: List = - zippedUpperBound.mapIndexed { idx: Int, (leqCol: Field, leqValue: JsonNode) -> + zippedUpperBound.mapIndexed { idx: Int, (leqCol: EmittedField, leqValue: JsonNode) + -> val lastLeaf: WhereClauseLeafNode = if (idx < zippedUpperBound.size - 1) { Lesser(leqCol, leqValue) @@ -208,7 +210,7 @@ sealed class TriggerSplittablePartition( LesserOrEqual(leqCol, leqValue) } And( - zippedUpperBound.take(idx).map { (eqCol: Field, eqValue: JsonNode) -> + zippedUpperBound.take(idx).map { (eqCol: EmittedField, eqValue: JsonNode) -> Equal(eqCol, eqValue) } + listOf(lastLeaf), ) @@ -224,7 +226,7 @@ class TriggerSplittableSnapshotPartition( selectQueryGenerator: SelectQueryGenerator, streamState: TriggerStreamState, config: TriggerTableConfig, - primaryKey: List, + primaryKey: List, triggerCdcPartitionState: TriggerCdcPartitionState? = null, override val lowerBound: List?, override val upperBound: List?, @@ -248,10 +250,11 @@ class TriggerSplittableSnapshotPartition( ) } - override fun incompleteState(lastRecord: ObjectNode): OpaqueStateValue = + override fun incompleteState(lastRecord: SelectQuerier.ResultRow): OpaqueStateValue = DefaultJdbcStreamStateValue.snapshotCheckpoint( primaryKey = checkpointColumns, - primaryKeyCheckpoint = checkpointColumns.map { lastRecord[it.id] ?: Jsons.nullNode() }, + primaryKeyCheckpoint = + checkpointColumns.map { lastRecord.data.toJson()[it.id] ?: Jsons.nullNode() }, ) } @@ -262,9 +265,9 @@ sealed class TriggerCursorPartition( selectQueryGenerator: SelectQueryGenerator, streamState: TriggerStreamState, config: TriggerTableConfig, - checkpointColumns: List, + checkpointColumns: List, triggerCdcPartitionState: TriggerCdcPartitionState? = null, - val cursor: Field, + val cursor: EmittedField, private val explicitCursorUpperBound: JsonNode?, ) : TriggerSplittablePartition( @@ -301,11 +304,11 @@ class TriggerSplittableSnapshotWithCursorPartition( selectQueryGenerator: SelectQueryGenerator, streamState: TriggerStreamState, config: TriggerTableConfig, - primaryKey: List, + primaryKey: List, triggerCdcPartitionState: TriggerCdcPartitionState? = null, override val lowerBound: List?, override val upperBound: List?, - cursor: Field, + cursor: EmittedField, cursorUpperBound: JsonNode?, ) : TriggerCursorPartition( @@ -335,10 +338,11 @@ class TriggerSplittableSnapshotWithCursorPartition( ) } - override fun incompleteState(lastRecord: ObjectNode): OpaqueStateValue = + override fun incompleteState(lastRecord: SelectQuerier.ResultRow): OpaqueStateValue = DefaultJdbcStreamStateValue.snapshotWithCursorCheckpoint( primaryKey = checkpointColumns, - primaryKeyCheckpoint = checkpointColumns.map { lastRecord[it.id] ?: Jsons.nullNode() }, + primaryKeyCheckpoint = + checkpointColumns.map { lastRecord.data.toJson()[it.id] ?: Jsons.nullNode() }, cursor, cursorUpperBound, ) @@ -352,7 +356,7 @@ class TriggerCursorIncrementalPartition( selectQueryGenerator: SelectQueryGenerator, streamState: TriggerStreamState, config: TriggerTableConfig, - cursor: Field, + cursor: EmittedField, triggerCdcPartitionState: TriggerCdcPartitionState? = null, val cursorLowerBound: JsonNode, override val isLowerBoundIncluded: Boolean, @@ -379,10 +383,10 @@ class TriggerCursorIncrementalPartition( cursorCheckpoint = cursorUpperBound, ) - override fun incompleteState(lastRecord: ObjectNode): OpaqueStateValue = + override fun incompleteState(lastRecord: SelectQuerier.ResultRow): OpaqueStateValue = DefaultJdbcStreamStateValue.cursorIncrementalCheckpoint( cursor, - cursorCheckpoint = lastRecord[cursor.id] ?: Jsons.nullNode(), + cursorCheckpoint = lastRecord.data.toJson()[cursor.id] ?: Jsons.nullNode(), ) } diff --git a/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartitionFactory.kt b/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartitionFactory.kt index 6c85d0b6fb01..a4c612866164 100644 --- a/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartitionFactory.kt +++ b/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartitionFactory.kt @@ -6,8 +6,8 @@ package io.airbyte.cdk import com.fasterxml.jackson.databind.JsonNode import io.airbyte.cdk.command.OpaqueStateValue -import io.airbyte.cdk.discover.Field -import io.airbyte.cdk.discover.FieldOrMetaField +import io.airbyte.cdk.discover.DataOrMetaField +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.output.CatalogValidationFailureHandler import io.airbyte.cdk.output.InvalidCursor import io.airbyte.cdk.output.InvalidPrimaryKey @@ -77,14 +77,14 @@ class TriggerPartitionFactory( } val sv: DefaultJdbcStreamStateValue = Jsons.treeToValue(opaqueStateValue, DefaultJdbcStreamStateValue::class.java) - val pkMap: Map = + val pkMap: Map = sv.pkMap(stream) ?: run { handler.accept(ResetStream(stream.id)) streamState.reset() return coldStart(streamState) } - val cursorPair: Pair? = + val cursorPair: Pair? = if (sv.cursors.isEmpty()) { null } else { @@ -119,7 +119,7 @@ class TriggerPartitionFactory( ) } } else { - val (cursor: Field, cursorCheckpoint: JsonNode) = cursorPair + val (cursor: EmittedField, cursorCheckpoint: JsonNode) = cursorPair val triggerCdcPartitionState = if (cursor.id == config.CURSOR_FIELD.id) TriggerCdcPartitionState.INCREMENTAL else null @@ -160,11 +160,11 @@ class TriggerPartitionFactory( } } - private fun DefaultJdbcStreamStateValue.pkMap(stream: Stream): Map? { + private fun DefaultJdbcStreamStateValue.pkMap(stream: Stream): Map? { if (primaryKey.isEmpty()) { return mapOf() } - val fields: List = stream.configuredPrimaryKey ?: listOf() + val fields: List = stream.configuredPrimaryKey ?: listOf() if (primaryKey.keys != fields.map { it.id }.toSet()) { handler.accept( InvalidPrimaryKey(stream.id, primaryKey.keys.toList()), @@ -174,7 +174,9 @@ class TriggerPartitionFactory( return fields.associateWith { primaryKey[it.id]!! } } - private fun DefaultJdbcStreamStateValue.cursorPair(stream: Stream): Pair? { + private fun DefaultJdbcStreamStateValue.cursorPair( + stream: Stream + ): Pair? { if (cursors.size > 1) { handler.accept( InvalidCursor(stream.id, cursors.keys.toString()), @@ -182,10 +184,10 @@ class TriggerPartitionFactory( return null } val cursorLabel: String = cursors.keys.first() - val cursor: FieldOrMetaField? = + val cursor: DataOrMetaField? = stream.schema.find { it.id == cursorLabel } ?: config.COMMON_FIELDS.find { it.id == cursorLabel } - if (cursor !is Field) { + if (cursor !is EmittedField) { handler.accept( InvalidCursor(stream.id, cursorLabel), ) @@ -202,7 +204,7 @@ class TriggerPartitionFactory( private fun coldStart(streamState: TriggerStreamState): TriggerPartition { val stream: Stream = streamState.stream - val pkChosenFromCatalog: List = stream.configuredPrimaryKey ?: listOf() + val pkChosenFromCatalog: List = stream.configuredPrimaryKey ?: listOf() if (stream.configuredSyncMode == ConfiguredSyncMode.FULL_REFRESH) { if (pkChosenFromCatalog.isEmpty()) { return TriggerUnsplittableSnapshotPartition( @@ -220,8 +222,8 @@ class TriggerPartitionFactory( upperBound = null, ) } - val cursorChosenFromCatalog: Field = - stream.configuredCursor as? Field ?: throw ConfigErrorException("no cursor") + val cursorChosenFromCatalog: EmittedField = + stream.configuredCursor as? EmittedField ?: throw ConfigErrorException("no cursor") if (pkChosenFromCatalog.isEmpty()) { return TriggerUnsplittableSnapshotWithCursorPartition( selectQueryGenerator, diff --git a/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartitionReader.kt b/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartitionReader.kt index c0fe1eca49e5..9564d1942595 100644 --- a/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartitionReader.kt +++ b/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartitionReader.kt @@ -6,8 +6,8 @@ package io.airbyte.cdk import edu.umd.cs.findbugs.annotations.SuppressFBWarnings import io.airbyte.cdk.data.NullCodec import io.airbyte.cdk.discover.CommonMetaField -import io.airbyte.cdk.discover.Field -import io.airbyte.cdk.discover.FieldOrMetaField +import io.airbyte.cdk.discover.DataOrMetaField +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.output.DataChannelMedium.SOCKET import io.airbyte.cdk.output.DataChannelMedium.STDIO import io.airbyte.cdk.output.OutputMessageRouter @@ -39,7 +39,7 @@ abstract class TriggerPartitionReader

>( private val nullValueEncoder = FieldValueEncoder(null, NullCodec) lateinit var outputMessageRouter: OutputMessageRouter - lateinit var outputRoute: ((NativeRecordPayload, Map?) -> Unit) + lateinit var outputRoute: ((NativeRecordPayload, Map?) -> Unit) private val charPool: List = ('a'..'z') + ('A'..'Z') + ('0'..'9') private fun generatePartitionId(length: Int): String = @@ -149,7 +149,7 @@ abstract class TriggerPartitionReader

>( // Validate the data field name with the schema field name so they have the same case. private fun validateDataFieldName( payload: NativeRecordPayload, - schema: Set, + schema: Set, ): NativeRecordPayload { val validatedPayload: NativeRecordPayload = mutableMapOf() for (field in schema) { diff --git a/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartitionsCreator.kt b/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartitionsCreator.kt index 574205a943ec..cde69637faf4 100644 --- a/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartitionsCreator.kt +++ b/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerPartitionsCreator.kt @@ -115,7 +115,7 @@ class TriggerPartitionsCreator< /** Collects a sample of rows in the unsplit partition. */ fun collectSample( - recordMapper: (ObjectNode) -> T, + recordMapper: (SelectQuerier.ResultRow) -> T, ): Sample { val values = mutableListOf() var previousWeight = 0L @@ -130,7 +130,7 @@ class TriggerPartitionsCreator< val samplingQuery: SelectQuery = partition.samplingQuery(sampleRateInvPow2) selectQuerier.executeQuery(samplingQuery).use { for (row in it) { - values.add(recordMapper(row.data.toJson())) + values.add(recordMapper(row)) } } if (values.size < sharedState.maxSampleSize) { @@ -171,12 +171,14 @@ class TriggerPartitionsCreator< return listOf(TriggerNonResumablePartitionReader(partition, config, deleteQuerier)) } // Sample the table for partition split boundaries and for record byte sizes. - val sample: Sample> = collectSample { record: ObjectNode -> - val boundary: OpaqueStateValue? = - (partition as? JdbcSplittablePartition<*>)?.incompleteState(record) - val rowByteSize: Long = sharedState.rowByteSizeEstimator().apply(record) - boundary to rowByteSize - } + val sample: Sample> = + collectSample { record: SelectQuerier.ResultRow -> + val boundary: OpaqueStateValue? = + (partition as? JdbcSplittablePartition<*>)?.incompleteState(record) + val rowByteSize: Long = + sharedState.rowByteSizeEstimator().apply(record.data.toJson()) + boundary to rowByteSize + } if (sample.kind == Sample.Kind.EMPTY) { log.info { "Sampling query found that the table was empty." } return listOf(CheckpointOnlyPartitionReader()) diff --git a/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerTableConfig.kt b/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerTableConfig.kt index a67daf89902c..cc32a900906d 100644 --- a/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerTableConfig.kt +++ b/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/TriggerTableConfig.kt @@ -4,7 +4,7 @@ package io.airbyte.cdk -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.discover.FieldType import io.airbyte.cdk.jdbc.BigIntegerFieldType import io.airbyte.cdk.jdbc.StringFieldType @@ -19,14 +19,14 @@ abstract class TriggerTableConfig() { abstract val cursorFieldType: FieldType abstract val cdcEnabled: Boolean - val CURSOR_FIELD: Field + val CURSOR_FIELD: EmittedField get() = - Field( + EmittedField( id = TRIGGER_TABLE_PREFIX + "change_time", type = cursorFieldType, ) - val COMMON_FIELDS: List + val COMMON_FIELDS: List get() = listOf( CHANGE_ID_FIELD, @@ -34,12 +34,16 @@ abstract class TriggerTableConfig() { OPERATION_TYPE_FIELD, ) - fun getTriggerTableSchemaFromStream(stream: Stream): List { - val result = mutableListOf() + fun getTriggerTableSchemaFromStream(stream: Stream): List { + val result = mutableListOf() stream.schema.forEach { field -> - result.add(Field(id = TRIGGER_TABLE_PREFIX + field.id + "_before", type = field.type)) - result.add(Field(id = TRIGGER_TABLE_PREFIX + field.id + "_after", type = field.type)) + result.add( + EmittedField(id = TRIGGER_TABLE_PREFIX + field.id + "_before", type = field.type) + ) + result.add( + EmittedField(id = TRIGGER_TABLE_PREFIX + field.id + "_after", type = field.type) + ) } return COMMON_FIELDS + result } @@ -48,12 +52,12 @@ abstract class TriggerTableConfig() { const val TRIGGER_TABLE_PREFIX = "_ab_trigger_" const val TRIGGER_TABLE_NAMESPACE = "_ab_cdc" val CHANGE_ID_FIELD = - Field( + EmittedField( id = TRIGGER_TABLE_PREFIX + "change_id", type = BigIntegerFieldType, ) val OPERATION_TYPE_FIELD = - Field( + EmittedField( id = TRIGGER_TABLE_PREFIX + "operation_type", type = StringFieldType, ) diff --git a/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/operations/TriggerStreamFactory.kt b/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/operations/TriggerStreamFactory.kt index c7f550b0ce08..3072f2ee1582 100644 --- a/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/operations/TriggerStreamFactory.kt +++ b/airbyte-cdk/bulk/toolkits/extract-trigger/src/main/kotlin/io/airbyte/cdk/operations/TriggerStreamFactory.kt @@ -8,7 +8,7 @@ import io.airbyte.cdk.TriggerTableConfig import io.airbyte.cdk.command.OpaqueStateValue import io.airbyte.cdk.data.NullCodec import io.airbyte.cdk.discover.CommonMetaField -import io.airbyte.cdk.discover.FieldOrMetaField +import io.airbyte.cdk.discover.DataOrMetaField import io.airbyte.cdk.discover.JdbcAirbyteStreamFactory import io.airbyte.cdk.discover.MetaField import io.airbyte.cdk.output.sockets.FieldValueEncoder @@ -22,7 +22,7 @@ import java.time.OffsetDateTime @Primary class TriggerStreamFactory(private val config: TriggerTableConfig) : JdbcAirbyteStreamFactory { - override val globalCursor: FieldOrMetaField = config.CURSOR_FIELD + override val globalCursor: DataOrMetaField = config.CURSOR_FIELD override val globalMetaFields: Set = setOf( diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/AbstractSourceConnectorTest.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/AbstractSourceConnectorTest.kt index 6eb4b4ecce50..95e0db92f6df 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/AbstractSourceConnectorTest.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/AbstractSourceConnectorTest.kt @@ -1,6 +1,9 @@ /* * Copyright (c) 2026 Airbyte, Inc., all rights reserved. */ + +@file:Suppress("DEPRECATION") + package io.airbyte.cdk.test.fixtures.legacy import com.fasterxml.jackson.databind.JsonNode diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/AbstractSourceDatabaseTypeTest.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/AbstractSourceDatabaseTypeTest.kt index de0646245abe..8305c9f9ae5b 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/AbstractSourceDatabaseTypeTest.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/AbstractSourceDatabaseTypeTest.kt @@ -116,13 +116,13 @@ abstract class AbstractSourceDatabaseTypeTest : AbstractSourceConnectorTest() { @Throws(Exception::class) open fun testDataContent() { // Class used to make easier the error reporting - class MissedRecords( // Stream that is missing any value + data class MissedRecords( // Stream that is missing any value var streamName: String?, // Which are the values that has not being gathered from the source var missedValues: List ) - class UnexpectedRecord(val streamName: String, val unexpectedValue: String?) + data class UnexpectedRecord(val streamName: String, val unexpectedValue: String?) val catalog = configuredCatalog val allMessages = runRead(catalog) @@ -136,8 +136,7 @@ abstract class AbstractSourceDatabaseTypeTest : AbstractSourceConnectorTest() { val testByName: MutableMap = HashMap() // If there is no expected value in the test set we don't include it in the list to be - // asserted - // (even if the table contains records) + // asserted (even if the table contains records) testDataHolders.forEach( Consumer { testDataHolder: TestDataHolder -> if (!testDataHolder.expectedValues.isEmpty()) { @@ -145,7 +144,7 @@ abstract class AbstractSourceDatabaseTypeTest : AbstractSourceConnectorTest() { testDataHolder.expectedValues testByName[testDataHolder.nameWithTestPrefix] = testDataHolder } else { - LOGGER.warn("Missing expected values for type: " + testDataHolder.sourceType) + LOGGER.warn { "Missing expected values for type: ${testDataHolder.sourceType}" } } } ) @@ -201,7 +200,6 @@ abstract class AbstractSourceDatabaseTypeTest : AbstractSourceConnectorTest() { for (errors in errorsByStream.values) { errorStrings.add(StringUtils.join(errors, "\n")) } - Assertions.assertTrue(errorsByStream.isEmpty(), StringUtils.join(errorStrings, "\n")) } @@ -232,7 +230,7 @@ abstract class AbstractSourceDatabaseTypeTest : AbstractSourceConnectorTest() { for (test in testDataHolders) { database!!.query { ctx: DSLContext -> ctx.fetch(test.createSqlQuery) - LOGGER.info("Table {} is created.", test.nameWithTestPrefix) + LOGGER.info { "Table ${test.nameSpace}.${test.nameWithTestPrefix} is created." } null } } @@ -243,11 +241,9 @@ abstract class AbstractSourceDatabaseTypeTest : AbstractSourceConnectorTest() { for (test in testDataHolders) { database!!.query { ctx: DSLContext -> test.insertSqlQueries.forEach(Consumer { sql: String -> ctx.fetch(sql) }) - LOGGER.info( - "Inserted {} rows in Ttable {}", - test.insertSqlQueries.size, - test.nameWithTestPrefix - ) + LOGGER.info { + "Inserted ${test.insertSqlQueries.size} rows in table ${test.nameWithTestPrefix}" + } null } } @@ -343,7 +339,7 @@ abstract class AbstractSourceDatabaseTypeTest : AbstractSourceConnectorTest() { } protected fun printMarkdownTestTable() { - LOGGER.info(markdownTestTable) + LOGGER.info { markdownTestTable } } @Throws(SQLException::class) diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/ConnectorConfigUpdater.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/ConnectorConfigUpdater.kt index 81e0b54fd2d2..202543394ecd 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/ConnectorConfigUpdater.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/ConnectorConfigUpdater.kt @@ -2,6 +2,8 @@ * Copyright (c) 2026 Airbyte, Inc., all rights reserved. */ +@file:Suppress("DEPRECATION") + package io.airbyte.cdk.test.fixtures.legacy import com.google.common.hash.Hashing @@ -55,12 +57,9 @@ class ConnectorConfigUpdater( "update source" )!! - LOGGER.info( - "Persisted updated configuration for source {}. New config hash: {}.", - sourceId, - Hashing.sha256() - .hashString(updatedSource.connectionConfiguration.asText(), StandardCharsets.UTF_8) - ) + LOGGER.info { + "Persisted updated configuration for source $sourceId. New config hash: ${Hashing.sha256().hashString(updatedSource.connectionConfiguration.asText(), StandardCharsets.UTF_8)}." + } } /** @@ -91,15 +90,9 @@ class ConnectorConfigUpdater( "update destination" )!! - LOGGER.info( - "Persisted updated configuration for destination {}. New config hash: {}.", - destinationId, - Hashing.sha256() - .hashString( - updatedDestination.connectionConfiguration.asText(), - StandardCharsets.UTF_8 - ) - ) + LOGGER.info { + "Persisted updated configuration for destination $destinationId. New config hash: ${Hashing.sha256().hashString(updatedDestination.connectionConfiguration.asText(), StandardCharsets.UTF_8)}." + } } companion object {} diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/ContainerFactory.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/ContainerFactory.kt index e93f305e9a33..03cd7fe18995 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/ContainerFactory.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/ContainerFactory.kt @@ -183,11 +183,9 @@ abstract class ContainerFactory> { imageName: DockerImageName, containerModifiersWithNames: List, String>> ): C { - LOGGER.info( - "Creating new container based on {} with {}.", - imageName, - containerModifiersWithNames.map { it.second } - ) + LOGGER.info { + "Creating new container based on $imageName with ${containerModifiersWithNames.map { it.second }}." + } val container = createNewContainer(imageName) @Suppress("unchecked_cast") val logConsumer: Slf4jLogConsumer = @@ -205,12 +203,9 @@ abstract class ContainerFactory> { } container.withLogConsumer(logConsumer) for (resolvedNamedContainerModifier in containerModifiersWithNames) { - LOGGER.info( - "Calling {} in {} on new container based on {}.", - resolvedNamedContainerModifier.second, - javaClass.name, - imageName - ) + LOGGER.info { + "Calling ${resolvedNamedContainerModifier.second} in ${javaClass.name} on new container based on $imageName." + } resolvedNamedContainerModifier.first.accept(container) } container.start() diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultAirbyteSource.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultAirbyteSource.kt index 18544229147e..ba984047a539 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultAirbyteSource.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultAirbyteSource.kt @@ -12,7 +12,6 @@ import java.nio.file.Path import java.time.Duration import java.time.temporal.ChronoUnit import java.util.* -import java.util.List import java.util.concurrent.TimeUnit private val LOGGER = KotlinLogging.logger {} @@ -97,7 +96,7 @@ internal constructor( // stdout logs are logged elsewhere since stdout also contains data LineGobbler.gobble( sourceProcess!!.errorStream, - { msg: String -> LOGGER.error(msg) }, + { msg: String -> LOGGER.error { msg } }, "airbyte-source", CONTAINER_LOG_MDC_BUILDER ) @@ -105,7 +104,7 @@ internal constructor( logInitialStateAsJSON(sourceConfig) val acceptedMessageTypes = - List.of( + listOf( AirbyteMessage.Type.RECORD, AirbyteMessage.Type.STATE, AirbyteMessage.Type.TRACE, @@ -114,7 +113,7 @@ internal constructor( messageIterator = streamFactory .create(IOs.newBufferedReader(sourceProcess!!.inputStream)) - .peek { message: AirbyteMessage -> heartbeatMonitor.beat() } + .peek { _: AirbyteMessage -> heartbeatMonitor.beat() } .filter { message: AirbyteMessage -> acceptedMessageTypes.contains(message.type) } .iterator() } @@ -141,11 +140,11 @@ internal constructor( @Throws(Exception::class) override fun close() { if (sourceProcess == null) { - LOGGER.debug("Source process already exited") + LOGGER.debug { "Source process already exited" } return } - LOGGER.debug("Closing source process") + LOGGER.debug { "Closing source process" } TestHarnessUtils.gentleClose( sourceProcess, GRACEFUL_SHUTDOWN_DURATION.toMillis(), @@ -156,20 +155,20 @@ internal constructor( val message = if (sourceProcess!!.isAlive) "Source has not terminated " else "Source process exit with code " + exitValue - LOGGER.warn("$message. This warning is normal if the job was cancelled.") + LOGGER.warn { "$message. This warning is normal if the job was cancelled." } } } @Throws(Exception::class) override fun cancel() { - LOGGER.info("Attempting to cancel source process...") + LOGGER.info { "Attempting to cancel source process..." } if (sourceProcess == null) { - LOGGER.info("Source process no longer exists, cancellation is a no-op.") + LOGGER.info { "Source process no longer exists, cancellation is a no-op." } } else { - LOGGER.info("Source process exists, cancelling...") + LOGGER.info { "Source process exists, cancelling..." } TestHarnessUtils.cancelProcess(sourceProcess) - LOGGER.info("Cancelled source process!") + LOGGER.info { "Cancelled source process!" } } } @@ -179,11 +178,11 @@ internal constructor( } if (sourceConfig.state == null) { - LOGGER.info("source starting state | empty") + LOGGER.info { "source starting state | empty" } return } - LOGGER.info("source starting state | " + Jsons.serialize(sourceConfig.state!!.state)) + LOGGER.info { "source starting state | ${Jsons.serialize(sourceConfig.state!!.state)}" } } companion object { diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultAirbyteStreamFactory.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultAirbyteStreamFactory.kt index db323b7fbf04..ddaa75959546 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultAirbyteStreamFactory.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultAirbyteStreamFactory.kt @@ -125,7 +125,7 @@ class DefaultAirbyteStreamFactory : AirbyteStreamFactory { // we log as info all the lines that are not valid json // some sources actually log their process on stdout, we // want to make sure this info is available in the logs. - containerLogMdcBuilder.build().use { mdcScope -> logger.info(line) } + containerLogMdcBuilder.build().use { _ -> logger.info { line } } } return jsonLine.stream() } @@ -133,7 +133,7 @@ class DefaultAirbyteStreamFactory : AirbyteStreamFactory { protected fun validate(json: JsonNode): Boolean { val res = protocolValidator.test(json) if (!res) { - logger.error("Validation failed: {}", Jsons.serialize(json)) + logger.error { "Validation failed: ${Jsons.serialize(json)}" } } return res } @@ -141,7 +141,7 @@ class DefaultAirbyteStreamFactory : AirbyteStreamFactory { protected fun toAirbyteMessage(json: JsonNode?): Stream { val m = Jsons.tryObject(json, AirbyteMessage::class.java) if (m.isEmpty) { - logger.error("Deserialization failed: {}", Jsons.serialize(json)) + logger.error { "Deserialization failed: ${Jsons.serialize(json)}" } } return m.stream() } @@ -149,7 +149,7 @@ class DefaultAirbyteStreamFactory : AirbyteStreamFactory { protected fun filterLog(message: AirbyteMessage): Boolean { val isLog = message.type == AirbyteMessage.Type.LOG if (isLog) { - containerLogMdcBuilder.build().use { mdcScope -> internalLog(message.log) } + containerLogMdcBuilder.build().use { _ -> internalLog(message.log) } } return !isLog } @@ -163,18 +163,18 @@ class DefaultAirbyteStreamFactory : AirbyteStreamFactory { when (logMessage.level) { AirbyteLogMessage.Level.FATAL, - AirbyteLogMessage.Level.ERROR -> logger.error(combinedMessage) - AirbyteLogMessage.Level.WARN -> logger.warn(combinedMessage) - AirbyteLogMessage.Level.DEBUG -> logger.debug(combinedMessage) - AirbyteLogMessage.Level.TRACE -> logger.trace(combinedMessage) - else -> logger.info(combinedMessage) + AirbyteLogMessage.Level.ERROR -> logger.error { combinedMessage } + AirbyteLogMessage.Level.WARN -> logger.warn { combinedMessage } + AirbyteLogMessage.Level.DEBUG -> logger.debug { combinedMessage } + AirbyteLogMessage.Level.TRACE -> logger.trace { combinedMessage } + else -> logger.info { combinedMessage } } } // Human-readable byte size from // https://stackoverflow.com/questions/3758606/how-can-i-convert-byte-size-into-a-human-readable-format-in-java - private fun humanReadableByteCountSI(bytes: Long): String { - var bytes = bytes + private fun humanReadableByteCountSI(initialBytes: Long): String { + var bytes = initialBytes if (-1000 < bytes && bytes < 1000) { return "$bytes B" } diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultCheckConnectionTestHarness.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultCheckConnectionTestHarness.kt index a5472b0f3151..9f426826898b 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultCheckConnectionTestHarness.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultCheckConnectionTestHarness.kt @@ -20,11 +20,11 @@ constructor( private lateinit var process: Process @Throws(TestHarnessException::class) - override fun run(input: StandardCheckConnectionInput, jobRoot: Path): ConnectorJobOutput { + override fun run(inputType: StandardCheckConnectionInput, jobRoot: Path): ConnectorJobOutput { LineGobbler.startSection("CHECK") try { - val inputConfig = input.connectionConfiguration!! + val inputConfig = inputType.connectionConfiguration!! val process = integrationLauncher.check( jobRoot, @@ -36,7 +36,7 @@ constructor( val jobOutput = ConnectorJobOutput().withOutputType(ConnectorJobOutput.OutputType.CHECK_CONNECTION) - LineGobbler.gobble(process.errorStream, { msg: String -> LOGGER.error(msg) }) + LineGobbler.gobble(process.errorStream, { msg: String -> LOGGER.error { msg } }) val messagesByType = TestHarnessUtils.getMessagesByType(process, streamFactory, 30) val connectionStatus = @@ -45,7 +45,7 @@ constructor( .map { obj: AirbyteMessage -> obj.connectionStatus } .firstOrNull() - if (input.actorId != null && input.actorType != null) { + if (inputType.actorId != null && inputType.actorType != null) { val optionalConfigMsg = TestHarnessUtils.getMostRecentConfigControlMessage(messagesByType) if ( @@ -55,15 +55,15 @@ constructor( optionalConfigMsg.get() ) ) { - when (input.actorType!!) { + when (inputType.actorType!!) { ActorType.SOURCE -> connectorConfigUpdater.updateSource( - input.actorId, + inputType.actorId, optionalConfigMsg.get().config ) ActorType.DESTINATION -> connectorConfigUpdater.updateDestination( - input.actorId, + inputType.actorId, optionalConfigMsg.get().config ) } @@ -76,13 +76,11 @@ constructor( ConnectorJobOutput.OutputType.CHECK_CONNECTION, messagesByType ) - failureReason.ifPresent { failureReason: FailureReason -> - jobOutput.failureReason = failureReason - } + failureReason.ifPresent { jobOutput.failureReason = it } val exitCode = process.exitValue() if (exitCode != 0) { - LOGGER.warn("Check connection job subprocess finished with exit code {}", exitCode) + LOGGER.warn { "Check connection job subprocess finished with exit code $exitCode" } } if (connectionStatus != null) { @@ -95,7 +93,7 @@ constructor( ) ) .withMessage(connectionStatus.message) - LOGGER.info("Check connection job received output: {}", output) + LOGGER.info { "Check connection job received output: $output" } jobOutput.checkConnection = output } else if (failureReason.isEmpty) { TestHarnessUtils.throwWorkerException( @@ -106,7 +104,7 @@ constructor( LineGobbler.endSection("CHECK") return jobOutput } catch (e: Exception) { - LOGGER.error("Unexpected error while checking connection: ", e) + LOGGER.error(e) { "Unexpected error while checking connection: " } LineGobbler.endSection("CHECK") throw TestHarnessException("Unexpected error while getting checking connection.", e) } diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultDiscoverCatalogTestHarness.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultDiscoverCatalogTestHarness.kt index 9f40e0ca4d04..8ad0521cd05b 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultDiscoverCatalogTestHarness.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultDiscoverCatalogTestHarness.kt @@ -2,6 +2,8 @@ * Copyright (c) 2026 Airbyte, Inc., all rights reserved. */ +@file:Suppress("DEPRECATION") + package io.airbyte.cdk.test.fixtures.legacy import io.airbyte.api.client.AirbyteApiClient @@ -26,12 +28,9 @@ constructor( @Volatile private lateinit var process: Process @Throws(TestHarnessException::class) - override fun run( - discoverSchemaInput: StandardDiscoverCatalogInput, - jobRoot: Path - ): ConnectorJobOutput { + override fun run(inputType: StandardDiscoverCatalogInput, jobRoot: Path): ConnectorJobOutput { try { - val inputConfig = discoverSchemaInput.connectionConfiguration!! + val inputConfig = inputType.connectionConfiguration!! process = integrationLauncher.discover( jobRoot, @@ -43,7 +42,7 @@ constructor( ConnectorJobOutput() .withOutputType(ConnectorJobOutput.OutputType.DISCOVER_CATALOG_ID) - LineGobbler.gobble(process.errorStream, { msg: String -> LOGGER.error(msg) }) + LineGobbler.gobble(process.errorStream, { msg: String -> LOGGER.error { msg } }) val messagesByType = TestHarnessUtils.getMessagesByType(process, streamFactory, 30) @@ -63,7 +62,7 @@ constructor( ) ) { connectorConfigUpdater.updateSource( - UUID.fromString(discoverSchemaInput.sourceId), + UUID.fromString(inputType.sourceId), optionalConfigMsg.get().config ) jobOutput.connectorConfigurationUpdated = true @@ -78,7 +77,7 @@ constructor( val exitCode = process.exitValue() if (exitCode != 0) { - LOGGER.warn("Discover job subprocess finished with exit codee {}", exitCode) + LOGGER.warn { "Discover job subprocess finished with exit codee $exitCode" } } if (catalog != null) { @@ -86,10 +85,7 @@ constructor( AirbyteApiClient.retryWithJitter( { airbyteApiClient.sourceApi.writeDiscoverCatalogResult( - buildSourceDiscoverSchemaWriteRequestBody( - discoverSchemaInput, - catalog - ) + buildSourceDiscoverSchemaWriteRequestBody(inputType, catalog) ) }, WRITE_DISCOVER_CATALOG_LOGS_TAG diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultGetSpecTestHarness.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultGetSpecTestHarness.kt index 2a00e6360232..461a015e4137 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultGetSpecTestHarness.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DefaultGetSpecTestHarness.kt @@ -18,19 +18,19 @@ constructor( private lateinit var process: Process @Throws(TestHarnessException::class) - override fun run(config: JobGetSpecConfig, jobRoot: Path): ConnectorJobOutput { + override fun run(inputType: JobGetSpecConfig, jobRoot: Path): ConnectorJobOutput { try { val process = integrationLauncher.spec(jobRoot) this.process = process val jobOutput = ConnectorJobOutput().withOutputType(ConnectorJobOutput.OutputType.SPEC) - LineGobbler.gobble(process!!.errorStream, { msg: String -> LOGGER.error(msg) }) + LineGobbler.gobble(process.errorStream, { msg: String -> LOGGER.error { msg } }) val messagesByType = TestHarnessUtils.getMessagesByType(process, streamFactory, 30) val spec = messagesByType - .getOrDefault(AirbyteMessage.Type.SPEC, ArrayList())!! + .getOrDefault(AirbyteMessage.Type.SPEC, ArrayList()) .map { obj: AirbyteMessage -> obj.spec } .firstOrNull() @@ -39,13 +39,11 @@ constructor( ConnectorJobOutput.OutputType.SPEC, messagesByType ) - failureReason!!.ifPresent { failureReason: FailureReason -> - jobOutput.failureReason = failureReason - } + failureReason.ifPresent { jobOutput.failureReason = it } - val exitCode = process!!.exitValue() + val exitCode = process.exitValue() if (exitCode != 0) { - LOGGER.warn("Spec job subprocess finished with exit code {}", exitCode) + LOGGER.warn { "Spec job subprocess finished with exit code $exitCode" } } if (spec != null) { @@ -60,7 +58,7 @@ constructor( return jobOutput } catch (e: Exception) { throw TestHarnessException( - String.format("Error while getting spec from image %s", config.dockerImage), + String.format("Error while getting spec from image %s", inputType.dockerImage), e ) } diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DockerProcessFactory.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DockerProcessFactory.kt index f381c0e562e7..09f34541b208 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DockerProcessFactory.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/DockerProcessFactory.kt @@ -46,7 +46,7 @@ class DockerProcessFactory( jobType: String?, jobId: String, attempt: Int, - jobRoot: Path, + jobPath: Path, imageName: String, usesIsolatedPool: Boolean, usesStdin: Boolean, @@ -56,7 +56,7 @@ class DockerProcessFactory( allowedHosts: AllowedHosts?, labels: Map?, jobMetadata: Map, - internalToExternalPorts: Map?, + portMapping: Map?, additionalEnvironmentVariables: Map, vararg args: String ): Process { @@ -65,12 +65,12 @@ class DockerProcessFactory( throw TestHarnessException("Could not find image: $imageName") } - if (!jobRoot.toFile().exists()) { - Files.createDirectory(jobRoot) + if (!jobPath.toFile().exists()) { + Files.createDirectory(jobPath) } for ((key, value) in files) { - IOs.writeFile(jobRoot, key, value) + IOs.writeFile(jobPath, key, value) } val cmd: MutableList = @@ -81,7 +81,7 @@ class DockerProcessFactory( "--init", "-i", "-w", - rebasePath(jobRoot).toString(), // rebases the job root on the job data mount + rebasePath(jobPath).toString(), // rebases the job root on the job data mount "--log-driver", "none" ) @@ -93,12 +93,9 @@ class DockerProcessFactory( attempt, DOCKER_NAME_LEN_LIMIT ) - LOGGER.info( - "Creating docker container = {} with resources {} and allowedHosts {}", - containerName, - resourceRequirements, - allowedHosts - ) + LOGGER.info { + "Creating docker container = $containerName with resources $resourceRequirements and allowedHosts $allowedHosts" + } cmd.add("--name") cmd.add(containerName) cmd.addAll(localDebuggingOptions(containerName)) @@ -159,7 +156,7 @@ class DockerProcessFactory( cmd.add(imageName) cmd.addAll(args) - LOGGER.info("Preparing command: {}", Joiner.on(" ").join(cmd)) + LOGGER.info { "Preparing command: ${Joiner.on(" ").join(cmd)}" } return ProcessBuilder(cmd).start() } catch (e: IOException) { @@ -177,8 +174,8 @@ class DockerProcessFactory( fun checkImageExists(imageName: String?): Boolean { try { val process = ProcessBuilder(imageExistsScriptPath.toString(), imageName).start() - LineGobbler.gobble(process.errorStream, { msg: String -> LOGGER.error(msg) }) - LineGobbler.gobble(process.inputStream, { msg: String -> LOGGER.info(msg) }) + LineGobbler.gobble(process.errorStream, { msg: String -> LOGGER.error { msg } }) + LineGobbler.gobble(process.inputStream, { msg: String -> LOGGER.info { msg } }) TestHarnessUtils.gentleClose(process, 10, TimeUnit.MINUTES) @@ -241,7 +238,7 @@ class DockerProcessFactory( .map( Function { imageName: String -> ProcessFactory.Companion.extractShortImageName(containerName) - .startsWith(imageName!!) + .startsWith(imageName) } ) .orElse(false) && diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/EntrypointEnvChecker.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/EntrypointEnvChecker.kt index d3dfef9aab7b..44451430a724 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/EntrypointEnvChecker.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/EntrypointEnvChecker.kt @@ -47,8 +47,7 @@ object EntrypointEnvChecker { emptyMap() ) - val stdout = - BufferedReader(InputStreamReader(process!!.inputStream, StandardCharsets.UTF_8)) + val stdout = BufferedReader(InputStreamReader(process.inputStream, StandardCharsets.UTF_8)) var outputLine: String? = null diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/IOs.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/IOs.kt index 57b2e3746a56..2745c73244b1 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/IOs.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/IOs.kt @@ -3,7 +3,6 @@ */ package io.airbyte.cdk.test.fixtures.legacy -import com.google.common.base.Charsets import java.io.* import java.nio.charset.StandardCharsets import java.nio.file.Files diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/Jsons.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/Jsons.kt index fb93106da480..603362e3619a 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/Jsons.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/Jsons.kt @@ -15,7 +15,6 @@ import com.fasterxml.jackson.databind.ObjectWriter import com.fasterxml.jackson.databind.node.ArrayNode import com.fasterxml.jackson.databind.node.ObjectNode import com.fasterxml.jackson.dataformat.yaml.YAMLFactory -import com.google.common.base.Charsets import com.google.common.base.Preconditions import io.github.oshai.kotlinlogging.KotlinLogging import java.io.File diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/ProcessFactory.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/ProcessFactory.kt index 711557bdbe3f..d758046b1e60 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/ProcessFactory.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/ProcessFactory.kt @@ -1,6 +1,7 @@ /* * Copyright (c) 2026 Airbyte, Inc., all rights reserved. */ + package io.airbyte.cdk.test.fixtures.legacy import java.nio.file.Path @@ -69,7 +70,8 @@ interface ProcessFactory { lenLimit: Int ): String { var imageName = extractShortImageName(fullImagePath) - val randSuffix = RandomStringUtils.randomAlphabetic(5).lowercase(Locale.getDefault()) + val randSuffix = + RandomStringUtils.secure().nextAlphabetic(5).lowercase(Locale.getDefault()) val suffix = "$jobType-$jobId-$attempt-$randSuffix" var processName = "$imageName-$suffix" diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/SourceAcceptanceTest.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/SourceAcceptanceTest.kt index d832831f5b72..9fa79622f66c 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/SourceAcceptanceTest.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/SourceAcceptanceTest.kt @@ -59,7 +59,7 @@ abstract class SourceAcceptanceTest : AbstractSourceConnectorTest() { * Specification for integration. Will be passed to integration where appropriate in each test. * Should be valid. */ - @get:Throws(Exception::class) protected abstract val spec: ConnectorSpecification + @get:Throws(Exception::class) protected abstract val spec: ConnectorSpecification? /** * The catalog to use to validate the output of read operations. This will be used as follows: @@ -75,15 +75,11 @@ abstract class SourceAcceptanceTest : AbstractSourceConnectorTest() { /** a JSON file representing the state file to use when testing incremental syncs */ @get:Throws(Exception::class) protected abstract val state: JsonNode? + private val log = KotlinLogging.logger {} /** Verify that a spec operation issued to the connector returns a valid spec. */ @Test - @Throws(Exception::class) open fun testGetSpec() { - Assertions.assertEquals( - spec, - runSpec(), - "Expected spec output by integration to be equal to spec provided by test runner" - ) + Assertions.assertDoesNotThrow { runSpec() } } /** @@ -95,7 +91,7 @@ abstract class SourceAcceptanceTest : AbstractSourceConnectorTest() { fun testCheckConnection() { Assertions.assertEquals( StandardCheckConnectionOutput.Status.SUCCEEDED, - runCheck()!!.status, + runCheck().status, "Expected check connection operation to succeed" ) } @@ -138,7 +134,7 @@ abstract class SourceAcceptanceTest : AbstractSourceConnectorTest() { @Throws(Exception::class) open fun testFullRefreshRead() { if (!sourceSupportsFullRefresh()) { - LOGGER.info("Test skipped. Source does not support full refresh.") + LOGGER.info { "Test skipped. Source does not support full refresh." } return } @@ -167,7 +163,7 @@ abstract class SourceAcceptanceTest : AbstractSourceConnectorTest() { @Throws(Exception::class) open fun testIdenticalFullRefreshes() { if (!sourceSupportsFullRefresh()) { - LOGGER.info("Test skipped. Source does not support full refresh.") + LOGGER.info { "Test skipped. Source does not support full refresh." } return } @@ -273,8 +269,8 @@ abstract class SourceAcceptanceTest : AbstractSourceConnectorTest() { assert(Objects.nonNull(latestState)) val secondSyncRecords = filterRecords(runRead(configuredCatalog, latestState)) Assertions.assertTrue( - secondSyncRecords.isEmpty(), - "Expected the second incremental sync to produce no records when given the first sync's output state." + secondSyncRecords.size <= configuredCatalog.streams.size, + "Expected the second incremental sync to produce no more than the one record per stream when given the first sync's output state." ) } @@ -295,7 +291,7 @@ abstract class SourceAcceptanceTest : AbstractSourceConnectorTest() { } if (!sourceSupportsFullRefresh()) { - LOGGER.info("Test skipped. Source does not support full refresh.") + LOGGER.info { "Test skipped. Source does not support full refresh." } return } diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/SshBastionContainer.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/SshBastionContainer.kt index d2deb55b5bf0..4c758b66db2c 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/SshBastionContainer.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/SshBastionContainer.kt @@ -4,7 +4,6 @@ package io.airbyte.cdk.test.fixtures.legacy import com.fasterxml.jackson.databind.JsonNode -import com.google.common.collect.ImmutableMap import java.io.IOException import java.util.* import java.util.function.Consumer @@ -50,61 +49,55 @@ class SshBastionContainer : AutoCloseable { if (innerAddress) getInnerContainerAddress(container!!) else getOuterContainerAddress(container!!) return Jsons.jsonNode( - ImmutableMap.builder() - .put("tunnel_host", Objects.requireNonNull(containerAddress!!.left)) - .put("tunnel_method", tunnelMethod) - .put("tunnel_port", containerAddress.right) - .put("tunnel_user", SSH_USER) - .put( - "tunnel_user_password", + mapOf( + "tunnel_host" to Objects.requireNonNull(containerAddress.left), + "tunnel_method" to tunnelMethod, + "tunnel_port" to containerAddress.right, + "tunnel_user" to SSH_USER, + "tunnel_user_password" to if (tunnelMethod == SshTunnel.TunnelMethod.SSH_PASSWORD_AUTH) SSH_PASSWORD - else "" - ) - .put( - "ssh_key", + else "", + "ssh_key" to if (tunnelMethod == SshTunnel.TunnelMethod.SSH_KEY_AUTH) container!!.execInContainer("cat", "var/bastion/id_rsa").stdout - else "" - ) - .build() + else "", + ) ) } @Throws(IOException::class, InterruptedException::class) fun getTunnelConfig( tunnelMethod: SshTunnel.TunnelMethod, - builderWithSchema: ImmutableMap.Builder, + builderWithSchema: MutableMap, innerAddress: Boolean ): JsonNode? { - return Jsons.jsonNode( - builderWithSchema - .put("tunnel_method", getTunnelMethod(tunnelMethod, innerAddress)) - .build() - ) + builderWithSchema["tunnel_method"] = getTunnelMethod(tunnelMethod, innerAddress) + return Jsons.jsonNode(builderWithSchema) } - fun getBasicDbConfigBuider(db: JdbcDatabaseContainer<*>): ImmutableMap.Builder { + fun getBasicDbConfigBuider(db: JdbcDatabaseContainer<*>): MutableMap { return getBasicDbConfigBuider(db, db.databaseName) } fun getBasicDbConfigBuider( db: JdbcDatabaseContainer<*>, schemas: MutableList - ): ImmutableMap.Builder { - return getBasicDbConfigBuider(db, db.databaseName).put("schemas", schemas) + ): MutableMap { + return getBasicDbConfigBuider(db, db.databaseName).also { it["schemas"] = schemas } } fun getBasicDbConfigBuider( db: JdbcDatabaseContainer<*>, schemaName: String - ): ImmutableMap.Builder { - return ImmutableMap.builder() - .put("host", Objects.requireNonNull(HostPortResolver.resolveHost(db))) - .put("username", db.username) - .put("password", db.password) - .put("port", HostPortResolver.resolvePort(db)) - .put("database", schemaName) - .put("ssl", false) + ): MutableMap { + return mutableMapOf( + "host" to Objects.requireNonNull(HostPortResolver.resolveHost(db)), + "username" to db.username, + "password" to db.password, + "port" to HostPortResolver.resolvePort(db), + "database" to schemaName, + "ssl" to false, + ) } fun stopAndCloseContainers(db: JdbcDatabaseContainer<*>) { diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/TestDatabase.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/TestDatabase.kt index 60eb907844ad..97dd7b28e305 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/TestDatabase.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/TestDatabase.kt @@ -5,6 +5,7 @@ package io.airbyte.cdk.test.fixtures.legacy import com.fasterxml.jackson.databind.node.ObjectNode import com.google.common.collect.ImmutableMap +import io.airbyte.cdk.test.fixtures.legacy.JdbcUtils.MODE_KEY import io.github.oshai.kotlinlogging.KotlinLogging import java.io.IOException import java.io.UncheckedIOException @@ -51,7 +52,7 @@ protected constructor(val container: C) : AutoCloseable { private val dateFormat: DateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS") init { - LOGGER!!.info(formatLogLine("creating database $databaseName")) + LOGGER.info { formatLogLine("creating database $databaseName") } } protected fun formatLogLine(logLine: String?): String { @@ -162,7 +163,7 @@ protected constructor(val container: C) : AutoCloseable { try { database.query { ctx: DSLContext -> sql.forEach { statement: String -> - LOGGER!!.info("executing SQL statement {}", statement) + LOGGER.info { "executing SQL statement $statement" } ctx.execute(statement) } null @@ -178,14 +179,14 @@ protected constructor(val container: C) : AutoCloseable { return } try { - LOGGER!!.info( + LOGGER.info { formatLogLine( String.format("executing command %s", Strings.join(cmd.asIterable(), " ")) ) - ) + } val exec = container.execInContainer(*cmd.toTypedArray()) if (exec!!.exitCode == 0) { - LOGGER.info( + LOGGER.info { formatLogLine( String.format( "execution success\nstdout:\n%s\nstderr:\n%s", @@ -193,9 +194,9 @@ protected constructor(val container: C) : AutoCloseable { exec.stderr ) ) - ) + } } else { - LOGGER.error( + LOGGER.error { formatLogLine( String.format( "execution failure, code %s\nstdout:\n%s\nstderr:\n%s", @@ -204,7 +205,7 @@ protected constructor(val container: C) : AutoCloseable { exec.stderr ) ) - ) + } } } catch (e: IOException) { throw UncheckedIOException(e) @@ -239,7 +240,7 @@ protected constructor(val container: C) : AutoCloseable { override fun close() { execSQL(cleanupSQL.stream()) execInContainer(inContainerUndoBootstrapCmd()) - LOGGER!!.info("closing database databaseId=$databaseId") + LOGGER.info { "closing database databaseId=$databaseId" } } open class ConfigBuilder, B : ConfigBuilder>( @@ -284,7 +285,8 @@ protected constructor(val container: C) : AutoCloseable { } open fun withoutSsl(): B { - return with(JdbcUtils.SSL_KEY, false) + // return with(JdbcUtils.SSL_KEY, false) + return withSsl(mutableMapOf(MODE_KEY to "disable")) } open fun withSsl(sslMode: MutableMap): B { @@ -292,7 +294,7 @@ protected constructor(val container: C) : AutoCloseable { } companion object { - @JvmField val DEFAULT_CDC_REPLICATION_INITIAL_WAIT: Duration = Duration.ofSeconds(5) + @JvmField val DEFAULT_CDC_REPLICATION_INITIAL_WAIT: Duration = Duration.ofSeconds(15) } } diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/TestEnvConfigs.kt b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/TestEnvConfigs.kt index e60b2349dbd5..1d7810157502 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/TestEnvConfigs.kt +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/legacy/TestEnvConfigs.kt @@ -45,7 +45,7 @@ class TestEnvConfigs private constructor(envMap: Map) { try { return@getEnvOrDefault DeploymentMode.valueOf(s) } catch (e: IllegalArgumentException) { - LOGGER.info(s + " not recognized, defaulting to " + DeploymentMode.OSS) + LOGGER.info { "$s not recognized, defaulting to ${DeploymentMode.OSS}" } return@getEnvOrDefault DeploymentMode.OSS } } @@ -75,7 +75,7 @@ class TestEnvConfigs private constructor(envMap: Map) { // an empty string. Change this logic if this assumption no longer holds. val jobSharedEnvMap = JOB_SHARED_ENVS.entries.associate { - it.key to Exceptions.swallowWithDefault({ it.value.apply(this) ?: "" }, "") + it.key to Exceptions.swallowWithDefault({ it.value.apply(this) }, "") } return MoreMaps.merge(jobPrefixedEnvMap, jobSharedEnvMap) } @@ -95,14 +95,11 @@ class TestEnvConfigs private constructor(envMap: Map) { isSecret: Boolean ): T { val value = getEnv.apply(key) - if (value != null && !value.isEmpty()) { + if (value.isNotEmpty()) { return parser.apply(value) } else { - LOGGER.info( - "Using default value for environment variable {}: '{}'", - key, - if (isSecret) "*****" else defaultValue - ) + val displayValue = if (isSecret) "*****" else defaultValue.toString() + LOGGER.info { "Using default value for environment variable $key: '$displayValue'" } return defaultValue } } @@ -113,8 +110,6 @@ class TestEnvConfigs private constructor(envMap: Map) { fun getEnsureEnv(name: String): String { val value = getEnv(name) - checkNotNull(value != null) { "$name environment variable cannot be null" } - return value } diff --git a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/resources/ssh-tunnel-spec.json b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/resources/ssh-tunnel-spec.json index 8b2551186dae..97f9fdeb672e 100644 --- a/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/resources/ssh-tunnel-spec.json +++ b/airbyte-cdk/bulk/toolkits/legacy-source-integration-tests/src/testFixtures/resources/ssh-tunnel-spec.json @@ -114,6 +114,6 @@ ], "description": "Whether to initiate an SSH tunnel before connecting to the database, and if so, which kind of authentication to use.", "title": "SSH Tunnel Method", - "order": 9, + "order": 11, "type": "object" } diff --git a/airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/connector/IntegrationTestOperations.kt b/airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/connector/IntegrationTestOperations.kt index 654206de3263..b8e3172f460e 100644 --- a/airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/connector/IntegrationTestOperations.kt +++ b/airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/connector/IntegrationTestOperations.kt @@ -26,10 +26,17 @@ class IntegrationTestOperations( return streams } + @Deprecated("Use the correctly named 'read' function") fun sync( catalog: ConfiguredAirbyteCatalog, state: List = listOf(), vararg featureFlags: FeatureFlag + ): BufferingOutputConsumer = read(catalog, state, *featureFlags) + + fun read( + catalog: ConfiguredAirbyteCatalog, + state: List = listOf(), + vararg featureFlags: FeatureFlag ): BufferingOutputConsumer { return CliRunner.source("read", configSpec, catalog, state, *featureFlags).run() } diff --git a/airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/tests/BaseConnectorTest.kt b/airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/tests/BaseConnectorTest.kt index 10fd375eed80..55b5a72e28f2 100644 --- a/airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/tests/BaseConnectorTest.kt +++ b/airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/tests/BaseConnectorTest.kt @@ -8,7 +8,7 @@ import io.airbyte.cdk.command.ConfigurationSpecification import io.airbyte.cdk.command.SourceConfiguration import io.airbyte.cdk.command.SourceConfigurationFactory import io.airbyte.cdk.discover.DiscoveredStream -import io.airbyte.cdk.discover.Field +import io.airbyte.cdk.discover.EmittedField import io.airbyte.cdk.discover.JdbcAirbyteStreamFactory import io.airbyte.cdk.jdbc.BigIntegerFieldType import io.airbyte.cdk.jdbc.LocalDateTimeFieldType @@ -151,7 +151,7 @@ abstract class BaseConnectorTest( val discoveredStream = DiscoveredStream( id = StreamIdentifier.from(desc), - columns = table.columns.map { Field(it.name, it.jdbcType) }, + columns = table.columns.map { EmittedField(it.name, it.jdbcType) }, primaryKeyColumnIDs = table.columns .filter { it.isPrimaryKey } diff --git a/airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/tests/CursorBasedSyncTest.kt b/airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/tests/CursorBasedSyncTest.kt new file mode 100644 index 000000000000..6eac537e9d9b --- /dev/null +++ b/airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/tests/CursorBasedSyncTest.kt @@ -0,0 +1,233 @@ +/* Copyright (c) 2026 Airbyte, Inc., all rights reserved. */ +package io.airbyte.cdk.test.fixtures.tests + +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.node.ObjectNode +import io.airbyte.cdk.ClockFactory +import io.airbyte.cdk.command.ConfigurationSpecification +import io.airbyte.cdk.output.BufferingOutputConsumer +import io.airbyte.cdk.test.fixtures.cleanup.TestAssetResourceNamer +import io.airbyte.cdk.test.fixtures.connector.IntegrationTestOperations +import io.airbyte.cdk.test.fixtures.connector.TestDbExecutor +import io.airbyte.cdk.util.Jsons +import io.airbyte.protocol.models.v0.AirbyteMessage +import io.airbyte.protocol.models.v0.AirbyteRecordMessage +import io.airbyte.protocol.models.v0.AirbyteStateMessage +import io.airbyte.protocol.models.v0.AirbyteStream +import io.airbyte.protocol.models.v0.AirbyteTraceMessage +import io.airbyte.protocol.models.v0.CatalogHelpers +import io.airbyte.protocol.models.v0.ConfiguredAirbyteCatalog +import io.airbyte.protocol.models.v0.SyncMode +import io.github.oshai.kotlinlogging.KotlinLogging +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.DynamicContainer +import org.junit.jupiter.api.DynamicNode +import org.junit.jupiter.api.DynamicTest +import org.junit.jupiter.api.TestFactory +import org.junit.jupiter.api.Timeout +import org.junit.jupiter.api.function.Executable + +abstract class CursorBasedSyncTest { + private val log = KotlinLogging.logger {} + + abstract val configSpec: ConfigurationSpecification + abstract val executor: TestDbExecutor + abstract val setupDdl: List + abstract val testCases: List + + @TestFactory + @Timeout(300) + fun tests(): Iterable { + log.info { "Executing setup DDL statements." } + for (stmt in setupDdl) { + executor.executeUpdate(stmt) + } + log.info { "Inserting initial rows." } + for (stmt in testCases.flatMap { it.initialDml }) { + executor.executeUpdate(stmt) + } + val actual = DiscoverAndSyncAll(IntegrationTestOperations(configSpec), executor, testCases) + val discoverAndSyncAllTest = DynamicTest.dynamicTest("discover-and-sync-all", actual) + val testCaseNodes = + testCases.map { + DynamicContainer.dynamicContainer(it.testName, dynamicTests(actual, it)) + } + return listOf(discoverAndSyncAllTest) + testCaseNodes + } + + private fun dynamicTests(actual: DiscoverAndSyncAll, testCase: TestCase): List { + return listOf( + DynamicTest.dynamicTest("sync1-records") { + assertRecords( + "sync1", + testCase, + actual.sync1MessagesByStream, + testCase.expectedSync1Values + ) + }, + DynamicTest.dynamicTest("sync2-records") { + assertRecords( + "sync2", + testCase, + actual.sync2MessagesByStream, + testCase.expectedSync2Values + ) + }, + ) + } + + private fun assertRecords( + syncLabel: String, + testCase: TestCase, + messagesByStream: Map, + expectedJsonValues: List, + ) { + val consumer = messagesByStream[testCase.tableName.uppercase()] + Assertions.assertNotNull(consumer) + val actualRecords = extractCursorFieldData(consumer!!.records(), testCase.cursorField) + val expectedRecords = + expectedJsonValues.map { Jsons.readTree("""{"${testCase.cursorField}":$it}""") } + log.info { + "$syncLabel ${testCase.testName}: emitted records ${Jsons.writeValueAsString(sortedRecords(actualRecords))}" + } + Assertions.assertEquals( + Jsons.writeValueAsString(sortedRecords(expectedRecords)), + Jsons.writeValueAsString(sortedRecords(actualRecords)), + ) + } + + private fun extractCursorFieldData( + records: List, + cursorField: String, + ): List = + records.mapNotNull { record -> + val data = record.data as? ObjectNode ?: return@mapNotNull null + data.deepCopy().apply { + for (fieldName in data.fieldNames()) { + if (fieldName != cursorField) remove(fieldName) + } + } + } + + private fun sortedRecords(records: List): JsonNode = + Jsons.createArrayNode().apply { addAll(records.sortedBy { it.toString() }) } + + class DiscoverAndSyncAll( + private val ops: IntegrationTestOperations, + private val executor: TestDbExecutor, + private val testCases: List, + ) : Executable { + private val log = KotlinLogging.logger {} + + lateinit var sync1MessagesByStream: Map + lateinit var sync2MessagesByStream: Map + + override fun execute() { + log.info { "Running JDBC DISCOVER operation." } + val streams = ops.discover() + val catalog = configuredCatalog(streams) + + log.info { "Running JDBC READ (sync 1)." } + val sync1Output = ops.read(catalog) + Assertions.assertNotEquals(emptyList(), sync1Output.states()) + Assertions.assertNotEquals(emptyList(), sync1Output.records()) + sync1MessagesByStream = byStream(sync1Output.messages()) + + log.info { "Inserting additional rows." } + for (stmt in testCases.flatMap { it.additionalDml }) { + executor.executeUpdate(stmt) + } + + log.info { "Running JDBC READ (sync 2)." } + val sync2Output = ops.read(catalog, sync1Output.states()) + sync2MessagesByStream = byStream(sync2Output.messages()) + + log.info { "Done." } + } + + private fun configuredCatalog( + streams: Map + ): ConfiguredAirbyteCatalog { + val configuredStreams = + testCases.mapNotNull { testCase -> + streams[testCase.tableName]?.let { stream -> + CatalogHelpers.toDefaultConfiguredStream(stream) + .withSyncMode(SyncMode.INCREMENTAL) + .withCursorField(listOf(testCase.cursorField)) + } + } + return ConfiguredAirbyteCatalog().withStreams(configuredStreams) + } + + private fun byStream(messages: List): Map { + val result = + testCases.associate { + it.tableName.uppercase() to BufferingOutputConsumer(ClockFactory().fixed()) + } + for (msg in messages) { + result[streamName(msg) ?: continue]?.accept(msg) + } + return result + } + + private fun streamName(msg: AirbyteMessage): String? = + when (msg.type) { + AirbyteMessage.Type.RECORD -> msg.record?.stream + AirbyteMessage.Type.STATE -> msg.state?.stream?.streamDescriptor?.name + AirbyteMessage.Type.TRACE -> + when (msg.trace?.type) { + AirbyteTraceMessage.Type.ERROR -> msg.trace?.error?.streamDescriptor?.name + AirbyteTraceMessage.Type.ESTIMATE -> msg.trace?.estimate?.name + AirbyteTraceMessage.Type.STREAM_STATUS -> + msg.trace?.streamStatus?.streamDescriptor?.name + AirbyteTraceMessage.Type.ANALYTICS -> null + null -> null + } + else -> null + } + } + + data class TestCase( + val namespace: String, + val sqlType: String, + val cursorField: String, + // SQL literal → expected JSON output, inserted before sync 1; all must appear in sync 1 + val initialRows: Map, + // SQL literal → expected JSON output, inserted before sync 1 at the max cursor value; + // must appear in both sync 1 and sync 2 due to the >= lower bound used by the bulk CDK + val boundaryRows: Map = emptyMap(), + // SQL literal → expected JSON output, inserted between syncs; all must appear in sync 2 + val additionalRows: Map, + val testName: String = + sqlType + .replace("\\[]".toRegex(), " array") + .replace("[^a-zA-Z0-9]".toRegex(), " ") + .trim() + .replace(" +".toRegex(), "_") + .uppercase(), + ) { + companion object { + val testAssetResourceNamer = TestAssetResourceNamer() + } + + val tableName: String = testAssetResourceNamer.getName() + + val initialDml: List + get() = + (initialRows.keys + boundaryRows.keys).map { + "INSERT INTO \"$namespace\".\"$tableName\" (\"$cursorField\") VALUES ($it)" + } + + val additionalDml: List + get() = + additionalRows.keys.map { + "INSERT INTO \"$namespace\".\"$tableName\" (\"$cursorField\") VALUES ($it)" + } + + val expectedSync1Values: List + get() = initialRows.values.toList() + boundaryRows.values.toList() + + val expectedSync2Values: List + get() = boundaryRows.values.toList() + additionalRows.values.toList() + } +} diff --git a/airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/tests/FieldTypeMapperTest.kt b/airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/tests/FieldTypeMapperTest.kt index ea5dca34c934..4b13872cecc1 100644 --- a/airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/tests/FieldTypeMapperTest.kt +++ b/airbyte-cdk/bulk/toolkits/source-tests/src/testFixtures/kotlin/io/airbyte/cdk/test/fixtures/tests/FieldTypeMapperTest.kt @@ -9,6 +9,7 @@ import io.airbyte.cdk.data.AirbyteSchemaType import io.airbyte.cdk.data.LeafAirbyteSchemaType import io.airbyte.cdk.discover.MetaField import io.airbyte.cdk.output.BufferingOutputConsumer +import io.airbyte.cdk.test.fixtures.cleanup.TestAssetResourceNamer import io.airbyte.cdk.test.fixtures.connector.IntegrationTestOperations import io.airbyte.cdk.test.fixtures.connector.TestDbExecutor import io.airbyte.cdk.util.Jsons @@ -47,10 +48,6 @@ abstract class FieldTypeMapperTest { return testCases.find { streamName.uppercase() in it.streamNamesToRecordData.keys } } - companion object { - lateinit var ops: IntegrationTestOperations - } - @TestFactory @Timeout(300) fun tests(): Iterable { @@ -67,8 +64,8 @@ abstract class FieldTypeMapperTest { val discoverAndReadAllTest: DynamicNode = DynamicTest.dynamicTest("discover-and-read-all", actual) val testCases: List = - allStreamNamesAndRecordData.keys.map { streamName: String -> - DynamicContainer.dynamicContainer(streamName, dynamicTests(actual, streamName)) + testCases.map { + DynamicContainer.dynamicContainer(it.testName, dynamicTests(actual, it.tableName)) } return listOf(discoverAndReadAllTest) + testCases } @@ -95,7 +92,7 @@ abstract class FieldTypeMapperTest { } val testCase: TestCase = findTestCase(streamName)!! val jsonSchema: JsonNode = actualStream!!.jsonSchema?.get("properties")!! - val actualSchema: JsonNode? = jsonSchema[testCase.columnName.uppercase()] + val actualSchema: JsonNode? = jsonSchema[testCase.columnName] Assertions.assertNotNull(actualSchema) val expectedSchema: JsonNode = testCase.airbyteSchemaType.asJsonSchema() Assertions.assertEquals(expectedSchema, actualSchema) @@ -149,7 +146,7 @@ abstract class FieldTypeMapperTest { jdbcStreams = ops.discover() jdbcConfiguredCatalog = configuredCatalog(jdbcStreams) log.info { "Running JDBC READ operation." } - jdbcReadOutput = ops.sync(jdbcConfiguredCatalog) + jdbcReadOutput = ops.read(jdbcConfiguredCatalog) Assertions.assertNotEquals(emptyList(), jdbcReadOutput.states()) Assertions.assertNotEquals(emptyList(), jdbcReadOutput.records()) Assertions.assertEquals(emptyList(), jdbcReadOutput.logs()) @@ -213,25 +210,26 @@ abstract class FieldTypeMapperTest { val sqlType: String, val values: Map, val airbyteSchemaType: AirbyteSchemaType = LeafAirbyteSchemaType.STRING, + val testName: String = + sqlType + .replace("\\[]".toRegex(), "_array") + .replace("[^a-zA-Z0-9]".toRegex(), " ") + .trim() + .replace(" +".toRegex(), "_") + .uppercase() ) { - val id: String - get() = - sqlType - .replace("[^a-zA-Z0-9]".toRegex(), " ") - .trim() - .replace(" +".toRegex(), "_") - .lowercase() + companion object { + val testAssetResourceNamer = TestAssetResourceNamer() + } - val tableName: String - get() = "tbl_$id" + val tableName = testAssetResourceNamer.getName() - val columnName: String - get() = "col_$id" + val columnName = "TYPE_COL" val dml: List get() { return values.keys.map { - "INSERT INTO $namespace.$tableName ($columnName) VALUES ($it)" + "INSERT INTO \"$namespace\".\"$tableName\" (\"$columnName\") VALUES ($it)" } } @@ -239,10 +237,157 @@ abstract class FieldTypeMapperTest { get() { return mapOf( tableName.uppercase() to - values.values.map { - Jsons.readTree("""{"${columnName.uppercase()}":$it}""") - } + values.values.map { Jsons.readTree("""{"${columnName}":$it}""") } ) } } + + // pads the json string map values to a fixed length + protected fun Map.withLength(length: Int): Map { + return this.mapValues { + val currentLength = it.value.length - 2 // exclude the quotes + if (currentLength > length) { + throw IllegalArgumentException("$length is out of bounds") + } else { + // make it longer + it.value.replace("\"$".toRegex(), "\"".padStart(length - currentLength + 1)) + } + } + } +} + +object AnsiSql { + + val intValues = + mapOf( + "null" to "null", + "1" to "1", + "0" to "0", + "-1" to "-1", + "2147483647" to "2147483647", + "-2147483648" to "-2147483648", + ) + + val smallIntValues = + mapOf( + "null" to "null", + "1" to "1", + "0" to "0", + "-1" to "-1", + "32767" to "32767", + "-32768" to "-32768", + ) + + val bigIntValues = + mapOf( + "null" to "null", + "1" to "1", + "0" to "0", + "-1" to "-1", + "9223372036854775807" to "9223372036854775807", + "-9223372036854775808" to "-9223372036854775808", + ) + + val decimalValues = + mapOf( + "null" to "null", + "123456789.123456789" to "123456789.123456789", + "-123456789.123456789" to "-123456789.123456789", + "0.000000001" to "0.000000001", + "9999999999.999999999" to "9999999999.999999999", + "-9999999999.999999999" to "-9999999999.999999999", + ) + + val realValues = + mapOf( + "null" to "null", + "3.402E+38" to "3.402E+38", + "-3.402E+38" to "-3.402E+38", + "1.175E-37" to "1.175E-37", + "0.0" to "0.0", + ) + + val doubleValues = + mapOf( + "null" to "null", + "1.7976931348623157E+308" to "1.7976931348623157E+308", + "-1.7976931348623157E+308" to "-1.7976931348623157E+308", + "2.2250738585072014E-308" to "2.2250738585072014E-308", + "0.0" to "0.0", + ) + + val booleanValues = + mapOf( + "null" to "null", + "true" to "true", + "false" to "false", + ) + + val charValues = + mapOf( + "null" to "null", + "'a'" to "\"a\"", + "'Z'" to "\"Z\"", + "'1'" to "\"1\"", + "' '" to "\" \"", + ) + + val varcharValues = + mapOf( + "null" to "null", + "'Hello'" to "\"Hello\"", + "'12345'" to "\"12345\"", + "' '" to "\" \"", + "''" to "\"\"", + ) + + val dateValues = + mapOf( + "null" to "null", + "'1000-01-01'" to "\"1000-01-01\"", + "'9999-12-31'" to "\"9999-12-31\"", + ) + + val timeValues = + mapOf( + "null" to "null", + "'00:00:00'" to "\"00:00:00.000000\"", + "'23:59:59'" to "\"23:59:59.000000\"", + ) + + val timeTzValues = + mapOf( + "null" to "null", + "'00:00:00+00'" to "\"00:00:00.000000Z\"", + "'23:59:59+00'" to "\"23:59:59.000000Z\"", + ) + + val timestampValues = + mapOf( + "null" to "null", + "'1000-01-01 00:00:00'" to "\"1000-01-01T00:00:00.000000\"", + "'9999-12-31 23:59:59'" to "\"9999-12-31T23:59:59.000000\"", + ) + + val timestampWithTzValues = + mapOf( + "null" to "null", + "'1000-01-01 00:00:00'" to "\"1000-01-01T00:00:00.000000Z\"", + "'9999-12-31 23:59:59'" to "\"9999-12-31T23:59:59.000000Z\"", + ) +} + +object ExtendedSql { + val xmlValues = + mapOf( + "null" to "null", + "'value'" to "\"value\"" + ) + + val jsonValues = + mapOf( + "'{}'" to "\"{}\"", + "'{\"k\": null}'" to "\"{\\\"k\\\": null}\"", + "'{\"k\": \"v\"}'" to "\"{\\\"k\\\": \\\"v\\\"}\"" + ) } From 91d1690d7de20a2b6f2fd31ff282cfe0f91f629f Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 12:37:49 -0700 Subject: [PATCH 295/379] test: progressive rollout e2e test on source-faker (#75908) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Octavia Squidington III --- .../connectors/source-faker/README.md | 1 + .../connectors/source-faker/metadata.yaml | 12 ++++++++---- .../connectors/source-faker/pyproject.toml | 2 +- docs/integrations/sources/faker.md | 1 + 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/airbyte-integrations/connectors/source-faker/README.md b/airbyte-integrations/connectors/source-faker/README.md index 082aeb47b12f..0dca30e25e8d 100644 --- a/airbyte-integrations/connectors/source-faker/README.md +++ b/airbyte-integrations/connectors/source-faker/README.md @@ -102,3 +102,4 @@ You've checked out the repo, implemented a million dollar feature, and you're re 6. Pat yourself on the back for being an awesome contributor. 7. Someone from Airbyte will take a look at your PR and iterate with you to merge it into master. 8. Once your PR is merged, the new version of the connector will be automatically published to Docker Hub and our connector registry. +# Progressive rollout e2e test 20260331 diff --git a/airbyte-integrations/connectors/source-faker/metadata.yaml b/airbyte-integrations/connectors/source-faker/metadata.yaml index dd022bc3917d..ccc5ad9946cd 100644 --- a/airbyte-integrations/connectors/source-faker/metadata.yaml +++ b/airbyte-integrations/connectors/source-faker/metadata.yaml @@ -9,7 +9,7 @@ data: connectorSubtype: api connectorType: source definitionId: dfd88b22-b603-4c3d-aad7-3701784586b1 - dockerImageTag: 7.0.4 + dockerImageTag: 7.1.0-rc.1 dockerRepository: airbyte/source-faker documentationUrl: https://docs.airbyte.com/integrations/sources/faker externalDocumentationUrls: @@ -26,18 +26,22 @@ data: registryOverrides: cloud: enabled: true + dockerImageTag: 7.0.4 oss: enabled: true + dockerImageTag: 7.0.4 releaseStage: beta releases: rolloutConfiguration: - enableProgressiveRollout: false + enableProgressiveRollout: true breakingChanges: 4.0.0: message: This is a breaking change message upgradeDeadline: "2023-07-19" 5.0.0: - message: ID and products.year fields are changing to be integers instead of floats. + message: + ID and products.year fields are changing to be integers instead of + floats. upgradeDeadline: "2023-08-31" 6.0.0: message: Declare 'id' columns as primary keys. @@ -45,7 +49,7 @@ data: 7.0.0: message: This is a test breaking change to validate breaking change infrastructure. upgradeDeadline: "2026-03-19" - deadlineAction: "disable" + deadlineAction: disable scopedImpact: - scopeType: stream impactedScopes: diff --git a/airbyte-integrations/connectors/source-faker/pyproject.toml b/airbyte-integrations/connectors/source-faker/pyproject.toml index 62dd1ea81e9e..6136023c2721 100644 --- a/airbyte-integrations/connectors/source-faker/pyproject.toml +++ b/airbyte-integrations/connectors/source-faker/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "7.0.4" +version = "7.1.0-rc.1" name = "source-faker" description = "Source implementation for fake but realistic looking data." authors = [ "Airbyte ",] diff --git a/docs/integrations/sources/faker.md b/docs/integrations/sources/faker.md index e98df6b66b7c..21b078c1eb8f 100644 --- a/docs/integrations/sources/faker.md +++ b/docs/integrations/sources/faker.md @@ -47,6 +47,7 @@ Each purchase record includes: `id`, `user_id`, `product_id`, `created_at`, `upd | Version | Date | Pull Request | Subject | |:------------|:-----------| :-------------------------------------------------------------------------------------------------------------------- |:----------------------------------------------------------------------------------------------------------------| +| 7.1.0-rc.1 | 2026-03-31 | [75908](https://github.com/airbytehq/airbyte/pull/75908) | test: progressive rollout e2e test on source-faker | | 7.0.4 | 2026-03-31 | [75657](https://github.com/airbytehq/airbyte/pull/75657) | Patch version bump (test publish) | | 7.0.3 | 2026-03-20 | [75256](https://github.com/airbytehq/airbyte/pull/75256) | Re-release to verify yank/un-yank behavior in ops CLI registry pipeline | | 7.0.2 | 2026-03-19 | [75232](https://github.com/airbytehq/airbyte/pull/75232) | Patch version bump (ops CLI registry post-launch test) | From f97c51cdb2ffd9bde9ff1394caf75c56431fb19a Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 12:45:55 -0700 Subject: [PATCH 296/379] ci(connectors): migrate `connectors_up_to_date` workflow from `airbyte-ci` to `airbyte-ops` (#75524) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/connectors_up_to_date.yml | 263 +++++++++++++++++--- 1 file changed, 224 insertions(+), 39 deletions(-) diff --git a/.github/workflows/connectors_up_to_date.yml b/.github/workflows/connectors_up_to_date.yml index 29a051c21548..e39e57142217 100644 --- a/.github/workflows/connectors_up_to_date.yml +++ b/.github/workflows/connectors_up_to_date.yml @@ -10,8 +10,13 @@ on: workflow_dispatch: inputs: connectors-options: - description: "Options to pass to the 'airbyte-ci connectors' command group." - default: "--language=python --language=low-code --language=manifest-only" + description: >- + Override: pass these flags directly to `airbyte-ops local connector list` + instead of the default source/destination selection. + Examples: `--name=source-github` (one connector), + `--connectors-filter=source-github,source-stripe` (multiple by name), + `--certified-only --connector-type=destination` (custom query). + default: "" jobs: generate_matrix: name: Generate matrix @@ -21,29 +26,82 @@ jobs: steps: - name: Checkout Airbyte uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - - name: Run airbyte-ci connectors list [SCHEDULED TRIGGER] - if: github.event_name == 'schedule' - id: airbyte-ci-connectors-list-scheduled - uses: ./.github/actions/run-airbyte-ci - with: - context: "master" - subcommand: 'connectors --language=python --language=low-code --language=manifest-only --metadata-query="\"-rc.\" not in data.dockerImageTag and \"source-declarative-manifest\" not in data.dockerRepository" list --output=selected_connectors.json' - - name: Run airbyte-ci connectors list [MANUAL TRIGGER] - if: github.event_name == 'workflow_dispatch' - id: airbyte-ci-connectors-list-workflow-dispatch - uses: ./.github/actions/run-airbyte-ci - with: - context: "master" - subcommand: 'connectors ${{ github.event.inputs.connectors-options }} --metadata-query="\"-rc.\" not in data.dockerImageTag and \"source-declarative-manifest\" not in data.dockerRepository" list --output=selected_connectors.json' - # We generate a dynamic matrix from the list of selected connectors. - # A matrix is required in this situation because the number of connectors is large and running them all in a single job would exceed the maximum job time limit of 6 hours. - # We use 25 connectors per job, with hopes they can finish within the 1 hours duration of the GitHub App's - # token. - - name: Generate matrix - 25 connectors per job + + - name: Install uv + uses: astral-sh/setup-uv@6b9c6063abd6010835644d4c2e1bef4cf5cd0fca # v6.0.1 + + - name: Install airbyte-ops CLI + run: uv tool install airbyte-internal-ops + + # --- Connector selection --- + # When connectors-options is provided, use it directly as an override. + # Otherwise, use the three-call pattern: sources (all support levels) + + # destinations (certified only), then combine. + + # Override path: use connectors-options as-is + - name: "[override] List connectors from manual input" + id: list-override + if: github.event.inputs.connectors-options != '' + env: + CONNECTOR_OPTIONS: ${{ github.event.inputs.connectors-options }} + run: | + echo "generated_matrix=$( \ + airbyte-ops local connector list \ + --repo-path "$GITHUB_WORKSPACE" \ + $CONNECTOR_OPTIONS \ + --output-format=json-gh-matrix \ + )" | tee -a $GITHUB_OUTPUT + + # Default path — Call 1: Sources (all support levels) + - name: List source connectors + id: list-sources + if: github.event.inputs.connectors-options == '' || github.event_name == 'schedule' + run: | + SOURCES=$( + airbyte-ops local connector list \ + --repo-path "$GITHUB_WORKSPACE" \ + --connector-type=source \ + --language python --language low-code --language manifest-only \ + --exclude-connectors=source-declarative-manifest \ + --output-format=csv + ) + echo "sources=$SOURCES" | tee -a $GITHUB_OUTPUT + + # Default path — Call 2: Destinations (certified only) + - name: List destination connectors + id: list-destinations + if: github.event.inputs.connectors-options == '' || github.event_name == 'schedule' + run: | + DESTINATIONS=$( + airbyte-ops local connector list \ + --repo-path "$GITHUB_WORKSPACE" \ + --connector-type=destination \ + --certified-only \ + --language python --language low-code --language manifest-only \ + --output-format=csv + ) + echo "destinations=$DESTINATIONS" | tee -a $GITHUB_OUTPUT + + # Default path — Call 3: Combine both sets into GH Actions matrix + - name: Generate matrix from source + destination lists + id: list-default + if: github.event.inputs.connectors-options == '' || github.event_name == 'schedule' + run: | + echo "generated_matrix=$( \ + airbyte-ops local connector list \ + --repo-path "$GITHUB_WORKSPACE" \ + --connectors-filter="${{ steps.list-sources.outputs.sources }},${{ steps.list-destinations.outputs.destinations }}" \ + --output-format=json-gh-matrix \ + )" | tee -a $GITHUB_OUTPUT + + # Merge: pick whichever path ran + - name: Set final matrix output id: generate_matrix + env: + OVERRIDE_MATRIX: ${{ steps.list-override.outputs.generated_matrix }} + DEFAULT_MATRIX: ${{ steps.list-default.outputs.generated_matrix }} run: | - matrix=$(jq -c -r '{include: [.[] | "--name=" + .] | to_entries | group_by(.key / 25 | floor) | map(map(.value) | {"connector_names": join(" ")})}' selected_connectors.json) - echo "generated_matrix=$matrix" >> $GITHUB_OUTPUT + echo "generated_matrix=${OVERRIDE_MATRIX:-$DEFAULT_MATRIX}" | tee -a $GITHUB_OUTPUT run_connectors_up_to_date: needs: generate_matrix @@ -51,12 +109,24 @@ jobs: runs-on: connector-up-to-date-medium continue-on-error: true strategy: - matrix: ${{fromJson(needs.generate_matrix.outputs.generated_matrix)}} + matrix: ${{ fromJson(needs.generate_matrix.outputs.generated_matrix) }} permissions: pull-requests: write + contents: write + env: + CONNECTOR_NAME: ${{ matrix.connector }} + CONNECTOR_DIR: ${{ matrix.connector_dir }} + CONNECTOR_LANGUAGE: ${{ matrix.connector_language }} steps: - name: Checkout Airbyte uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + + - name: Install uv + uses: astral-sh/setup-uv@6b9c6063abd6010835644d4c2e1bef4cf5cd0fca # v6.0.1 + + - name: Install airbyte-ops CLI + run: uv tool install airbyte-internal-ops + - name: Authenticate as 'octavia-bot-hoard' GitHub App uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 id: get-app-token @@ -65,19 +135,134 @@ jobs: repositories: ${{ inputs.repo || github.event.repository.name }} app-id: ${{ secrets.OCTAVIA_BOT_HOARD_APP_ID }} private-key: ${{ secrets.OCTAVIA_BOT_HOARD_PRIVATE_KEY }} - # Token is good for 1 hour - - name: Run airbyte-ci connectors up-to-date [WORKFLOW] - id: airbyte-ci-connectors-up-to-date-workflow-dispatch - uses: ./.github/actions/run-airbyte-ci + + - name: Get GitHub App User ID + id: get-user-id + env: + GH_TOKEN: ${{ steps.get-app-token.outputs.token }} + run: echo "user-id=$(gh api "/users/${{ steps.get-app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT" + + - name: Configure git author + run: | + git config --global user.name '${{ steps.get-app-token.outputs.app-slug }}[bot]' + git config --global user.email '${{ steps.get-user-id.outputs.user-id }}+${{ steps.get-app-token.outputs.app-slug }}[bot]@users.noreply.github.com' + + - name: Docker login + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: - context: "master" - dagger_cloud_token: ${{ secrets.DAGGER_CLOUD_TOKEN_CACHE_3 }} - docker_hub_password: ${{ secrets.DOCKER_HUB_PASSWORD }} - docker_hub_username: ${{ secrets.DOCKER_HUB_USERNAME }} - gcp_gsm_credentials: ${{ secrets.GCP_GSM_CREDENTIALS }} - gcs_credentials: ${{ secrets.METADATA_SERVICE_PROD_GCS_CREDENTIALS }} - github_token: ${{ steps.get-app-token.outputs.token }} - sentry_dsn: ${{ secrets.SENTRY_AIRBYTE_CI_DSN }} - s3_build_cache_access_key_id: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} - s3_build_cache_secret_key: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} - subcommand: "connectors --concurrency=10 ${{ matrix.connector_names}} up-to-date --create-prs --auto-merge" + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_PASSWORD }} + + # --- Step 1: Set up Python + Poetry --- + # bump-deps runs `poetry update --lock` internally, so Poetry must be available. + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: "3.11" + + - name: Install and configure Poetry + uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1.4.1 + with: + version: 2.3.3 + + # --- Step 2: Bump dependencies (CDK + external) --- + - name: Bump dependencies + run: | + airbyte-ops local connector bump-deps \ + --name "$CONNECTOR_NAME" \ + --repo-path "$GITHUB_WORKSPACE" + + # --- Step 3: Update base image --- + - name: Update base image in metadata.yaml + run: | + airbyte-ops local connector bump-base-image \ + --name "$CONNECTOR_NAME" \ + --repo-path "$GITHUB_WORKSPACE" + + # --- Step 4: Check for changes --- + - name: Check for changes + id: check-changes + run: | + if git diff --quiet; then + echo "has_changes=false" >> $GITHUB_OUTPUT + echo "No changes detected for $CONNECTOR_NAME" + else + echo "has_changes=true" >> $GITHUB_OUTPUT + echo "Changes detected for $CONNECTOR_NAME" + fi + + # --- Step 5: Create or update PR --- + # peter-evans/create-pull-request detects working-tree changes, commits them, + # and creates (or updates) a draft PR. We submit it as a draft so we can push + # a follow-up changelog commit before marking it ready for review. + - name: Create or update PR + id: create-pr + if: steps.check-changes.outputs.has_changes == 'true' + uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6 + with: + token: ${{ steps.get-app-token.outputs.token }} + commit-message: "chore(${{ env.CONNECTOR_NAME }}): update dependencies" + branch: "connectors-up-to-date/${{ env.CONNECTOR_NAME }}" + delete-branch: true + title: "chore(${{ env.CONNECTOR_NAME }}): update dependencies" + body: | + Updates dependencies for `${{ env.CONNECTOR_NAME }}`. + + 🤖 Generated by [automated workflow](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}). + labels: | + area/connectors + auto-merge + draft: true + + # --- Step 6: Bump version + changelog (needs PR number) --- + # This runs after PR creation so we can reference the PR number in the changelog. + # The changes are pushed as a follow-up commit to the PR branch. + - name: Bump connector version (patch) with changelog + if: steps.check-changes.outputs.has_changes == 'true' + env: + PR_NUMBER: ${{ steps.create-pr.outputs.pull-request-number }} + run: | + airbyte-ops local connector bump-version \ + --name "$CONNECTOR_NAME" \ + --repo-path "$GITHUB_WORKSPACE" \ + --bump-type patch \ + --changelog-message "Update dependencies" \ + --pr-number "$PR_NUMBER" + + # --- Step 7: Push changelog commit to the PR branch --- + - name: Push changelog commit to PR branch + if: steps.check-changes.outputs.has_changes == 'true' + env: + PR_BRANCH: ${{ steps.create-pr.outputs.pull-request-branch }} + GH_TOKEN: ${{ steps.get-app-token.outputs.token }} + run: | + git fetch --depth=1 origin "$PR_BRANCH" + git checkout "$PR_BRANCH" + git add "$CONNECTOR_DIR" + git commit -m "chore($CONNECTOR_NAME): bump version and update changelog" + git push origin "$PR_BRANCH" + + # --- Step 8: Mark PR ready for review --- + - name: Mark PR as ready for review + if: steps.check-changes.outputs.has_changes == 'true' + env: + GH_TOKEN: ${{ steps.get-app-token.outputs.token }} + PR_NUMBER: ${{ steps.create-pr.outputs.pull-request-number }} + run: gh pr ready "$PR_NUMBER" + + # --- Step 9: Apply bot approval --- + - name: Apply bot approval + if: steps.check-changes.outputs.has_changes == 'true' + continue-on-error: true + env: + GH_TOKEN: ${{ steps.get-app-token.outputs.token }} + PR_NUMBER: ${{ steps.create-pr.outputs.pull-request-number }} + run: gh pr review "$PR_NUMBER" --approve --body "Auto-approved by connectors up-to-date workflow." + + # --- Step 10: Enable auto-merge --- + - name: Enable auto-merge on PR + if: steps.check-changes.outputs.has_changes == 'true' + env: + GH_TOKEN: ${{ steps.get-app-token.outputs.token }} + PR_NUMBER: ${{ steps.create-pr.outputs.pull-request-number }} + run: gh pr merge "$PR_NUMBER" --squash --auto From 7b31745ac86e4aeeba4fd9aa41fafff71370db09 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 12:55:53 -0700 Subject: [PATCH 297/379] fix(ci): use correct CLI command name for progressive rollout operations (#75916) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/finalize_rollout.yml | 2 +- .github/workflows/publish_connectors.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/finalize_rollout.yml b/.github/workflows/finalize_rollout.yml index f4ed78d86eba..b3d46b8b0bac 100644 --- a/.github/workflows/finalize_rollout.yml +++ b/.github/workflows/finalize_rollout.yml @@ -58,7 +58,7 @@ jobs: GCS_CREDENTIALS: ${{ secrets.METADATA_SERVICE_PROD_GCS_CREDENTIALS }} REGISTRY_STORE: "coral:prod" run: > - airbyte-ops registry rc cleanup + airbyte-ops registry progressive-rollout cleanup --name "${CONNECTOR_NAME}" --store "${REGISTRY_STORE}" diff --git a/.github/workflows/publish_connectors.yml b/.github/workflows/publish_connectors.yml index ae6954bb8984..2b082308f6d8 100644 --- a/.github/workflows/publish_connectors.yml +++ b/.github/workflows/publish_connectors.yml @@ -443,7 +443,7 @@ jobs: run: | echo "Creating RC metadata marker for ${{ matrix.connector }}" airbyte-ops \ - registry rc create \ + registry progressive-rollout create \ --name "${{ matrix.connector }}" \ --store "${REGISTRY_STORE}" From aeae0c5f185538486572e4d1bf399e798e519944 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 12:59:08 -0700 Subject: [PATCH 298/379] ci(connectors): fix error handling in connectors_up_to_date matrix generation (#75917) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/connectors_up_to_date.yml | 27 ++++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/.github/workflows/connectors_up_to_date.yml b/.github/workflows/connectors_up_to_date.yml index e39e57142217..12d8b7011fc4 100644 --- a/.github/workflows/connectors_up_to_date.yml +++ b/.github/workflows/connectors_up_to_date.yml @@ -13,7 +13,7 @@ on: description: >- Override: pass these flags directly to `airbyte-ops local connector list` instead of the default source/destination selection. - Examples: `--name=source-github` (one connector), + Examples: `--connectors-filter=source-github` (one connector), `--connectors-filter=source-github,source-stripe` (multiple by name), `--certified-only --connector-type=destination` (custom query). default: "" @@ -45,12 +45,13 @@ jobs: env: CONNECTOR_OPTIONS: ${{ github.event.inputs.connectors-options }} run: | - echo "generated_matrix=$( \ + MATRIX=$( airbyte-ops local connector list \ --repo-path "$GITHUB_WORKSPACE" \ $CONNECTOR_OPTIONS \ - --output-format=json-gh-matrix \ - )" | tee -a $GITHUB_OUTPUT + --output-format=json-gh-matrix + ) + echo "generated_matrix=$MATRIX" | tee -a $GITHUB_OUTPUT # Default path — Call 1: Sources (all support levels) - name: List source connectors @@ -65,6 +66,7 @@ jobs: --exclude-connectors=source-declarative-manifest \ --output-format=csv ) + echo "Sources: $SOURCES" echo "sources=$SOURCES" | tee -a $GITHUB_OUTPUT # Default path — Call 2: Destinations (certified only) @@ -80,6 +82,7 @@ jobs: --language python --language low-code --language manifest-only \ --output-format=csv ) + echo "Destinations: $DESTINATIONS" echo "destinations=$DESTINATIONS" | tee -a $GITHUB_OUTPUT # Default path — Call 3: Combine both sets into GH Actions matrix @@ -87,21 +90,27 @@ jobs: id: list-default if: github.event.inputs.connectors-options == '' || github.event_name == 'schedule' run: | - echo "generated_matrix=$( \ + MATRIX=$( airbyte-ops local connector list \ --repo-path "$GITHUB_WORKSPACE" \ --connectors-filter="${{ steps.list-sources.outputs.sources }},${{ steps.list-destinations.outputs.destinations }}" \ - --output-format=json-gh-matrix \ - )" | tee -a $GITHUB_OUTPUT + --output-format=json-gh-matrix + ) + echo "generated_matrix=$MATRIX" | tee -a $GITHUB_OUTPUT - # Merge: pick whichever path ran + # Merge: pick whichever path ran, and validate non-empty - name: Set final matrix output id: generate_matrix env: OVERRIDE_MATRIX: ${{ steps.list-override.outputs.generated_matrix }} DEFAULT_MATRIX: ${{ steps.list-default.outputs.generated_matrix }} run: | - echo "generated_matrix=${OVERRIDE_MATRIX:-$DEFAULT_MATRIX}" | tee -a $GITHUB_OUTPUT + FINAL_MATRIX="${OVERRIDE_MATRIX:-$DEFAULT_MATRIX}" + if [ -z "$FINAL_MATRIX" ]; then + echo "::error::Matrix generation produced empty output. Check CLI commands above for errors." + exit 1 + fi + echo "generated_matrix=$FINAL_MATRIX" | tee -a $GITHUB_OUTPUT run_connectors_up_to_date: needs: generate_matrix From 75fe275cdafdeb3ceddf92d6682643af59bc0282 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 13:04:21 -0700 Subject: [PATCH 299/379] ci(connectors): fix multiline JSON matrix output in connectors_up_to_date (#75918) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/connectors_up_to_date.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/connectors_up_to_date.yml b/.github/workflows/connectors_up_to_date.yml index 12d8b7011fc4..535e2f1649a3 100644 --- a/.github/workflows/connectors_up_to_date.yml +++ b/.github/workflows/connectors_up_to_date.yml @@ -51,7 +51,11 @@ jobs: $CONNECTOR_OPTIONS \ --output-format=json-gh-matrix ) - echo "generated_matrix=$MATRIX" | tee -a $GITHUB_OUTPUT + echo "Matrix: $MATRIX" + # Use heredoc delimiter for multiline JSON + echo "generated_matrix<> $GITHUB_OUTPUT + echo "$MATRIX" >> $GITHUB_OUTPUT + echo "MATRIX_EOF" >> $GITHUB_OUTPUT # Default path — Call 1: Sources (all support levels) - name: List source connectors @@ -96,7 +100,11 @@ jobs: --connectors-filter="${{ steps.list-sources.outputs.sources }},${{ steps.list-destinations.outputs.destinations }}" \ --output-format=json-gh-matrix ) - echo "generated_matrix=$MATRIX" | tee -a $GITHUB_OUTPUT + echo "Matrix: $MATRIX" + # Use heredoc delimiter for multiline JSON + echo "generated_matrix<> $GITHUB_OUTPUT + echo "$MATRIX" >> $GITHUB_OUTPUT + echo "MATRIX_EOF" >> $GITHUB_OUTPUT # Merge: pick whichever path ran, and validate non-empty - name: Set final matrix output @@ -110,7 +118,11 @@ jobs: echo "::error::Matrix generation produced empty output. Check CLI commands above for errors." exit 1 fi - echo "generated_matrix=$FINAL_MATRIX" | tee -a $GITHUB_OUTPUT + echo "Final matrix: $FINAL_MATRIX" + # Use heredoc delimiter for multiline JSON + echo "generated_matrix<> $GITHUB_OUTPUT + echo "$FINAL_MATRIX" >> $GITHUB_OUTPUT + echo "MATRIX_EOF" >> $GITHUB_OUTPUT run_connectors_up_to_date: needs: generate_matrix From 886f7ecbee316d5b97dbf41285d0422b8cfdb791 Mon Sep 17 00:00:00 2001 From: Sunil Kuruba Date: Tue, 31 Mar 2026 13:17:25 -0700 Subject: [PATCH 300/379] deps(destination-bigquery): Upgrade BigQuery Cloud dependencies and CDK version (#75913) Signed-off-by: sunil-kuruba --- .../connectors/destination-bigquery/metadata.yaml | 4 ++-- docs/integrations/destinations/bigquery.md | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/destination-bigquery/metadata.yaml b/airbyte-integrations/connectors/destination-bigquery/metadata.yaml index 9761220975da..d05db650d67c 100644 --- a/airbyte-integrations/connectors/destination-bigquery/metadata.yaml +++ b/airbyte-integrations/connectors/destination-bigquery/metadata.yaml @@ -6,7 +6,7 @@ data: connectorSubtype: database connectorType: destination definitionId: 22f6c74f-5699-40ff-833c-4a879ea40133 - dockerImageTag: 3.0.18-rc.1 + dockerImageTag: 3.0.18 dockerRepository: airbyte/destination-bigquery documentationUrl: https://docs.airbyte.com/integrations/destinations/bigquery githubIssueLabel: destination-bigquery @@ -39,7 +39,7 @@ data: message: "If you never interact with the raw tables, you can upgrade without taking any action. Otherwise, make sure to read the migration guide for more details." upgradeDeadline: "2026-07-31" rolloutConfiguration: - enableProgressiveRollout: true + enableProgressiveRollout: false resourceRequirements: jobSpecific: - jobType: sync diff --git a/docs/integrations/destinations/bigquery.md b/docs/integrations/destinations/bigquery.md index a682ac47ac8e..ad81617ceb45 100644 --- a/docs/integrations/destinations/bigquery.md +++ b/docs/integrations/destinations/bigquery.md @@ -250,6 +250,7 @@ This destination supports [namespaces](https://docs.airbyte.com/platform/using-a | Version | Date | Pull Request | Subject | |:------------|:-----------|:-----------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 3.0.18 | 2026-03-31 | [75913](https://github.com/airbytehq/airbyte/pull/75913) | Finalize upgrade BigQuery Cloud dependencies and CDK version | | 3.0.18-rc.1 | 2026-03-27 | [75541](https://github.com/airbytehq/airbyte/pull/75541) | Upgrade BigQuery Cloud dependencies and CDK version | | 3.0.17 | 2026-01-28 | [72427](https://github.com/airbytehq/airbyte/pull/72427) | Finalize upgrade CDK to 0.2.0 | | 3.0.17-rc.1 | 2026-01-26 | [72296](https://github.com/airbytehq/airbyte/pull/72296) | Upgrade CDK to 0.2.0 | From e2a149722c655cdfd8953f5adc4f5be2e6808943 Mon Sep 17 00:00:00 2001 From: sophiecuiy Date: Tue, 31 Mar 2026 13:24:01 -0700 Subject: [PATCH 301/379] feat(source-gitlab): Re-enable HTTPAPIBudget with concurrency 10 (4.4.23-rc.4) (#75915) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../connectors/source-gitlab/manifest.yaml | 100 +++++++++--------- .../connectors/source-gitlab/metadata.yaml | 2 +- docs/integrations/sources/gitlab.md | 1 + 3 files changed, 52 insertions(+), 51 deletions(-) diff --git a/airbyte-integrations/connectors/source-gitlab/manifest.yaml b/airbyte-integrations/connectors/source-gitlab/manifest.yaml index 180446384bea..47701265e52a 100644 --- a/airbyte-integrations/connectors/source-gitlab/manifest.yaml +++ b/airbyte-integrations/connectors/source-gitlab/manifest.yaml @@ -893,56 +893,56 @@ definitions: # GET /projects/:id/members/all — 200/min # GET /groups/:id/members/all — 200/min # All other authenticated API traffic — 2,000/min -# api_budget: -# type: HTTPAPIBudget -# policies: -# # Members endpoints: 200 requests/min (most restrictive) -# - type: MovingWindowCallRatePolicy -# rates: -# - limit: 200 -# interval: PT1M -# matchers: -# - method: GET -# url_path_pattern: "/members" -# # GET /groups (list) and /descendant_groups: 200 requests/min -# - type: MovingWindowCallRatePolicy -# rates: -# - limit: 200 -# interval: PT1M -# matchers: -# - method: GET -# url_path_pattern: "^groups$" -# - type: MovingWindowCallRatePolicy -# rates: -# - limit: 200 -# interval: PT1M -# matchers: -# - method: GET -# url_path_pattern: "/descendant_groups$" -# # GET /groups/:id and GET /projects/:id: 400 requests/min -# - type: MovingWindowCallRatePolicy -# rates: -# - limit: 400 -# interval: PT1M -# matchers: -# - method: GET -# url_path_pattern: "^groups/[^/]+$" -# - type: MovingWindowCallRatePolicy -# rates: -# - limit: 400 -# interval: PT1M -# matchers: -# - method: GET -# url_path_pattern: "^projects/[^/]+$" -# # Catch-all: 2,000 requests/min for all other authenticated API traffic -# - type: MovingWindowCallRatePolicy -# rates: -# - limit: 2000 -# interval: PT1M -# matchers: [] -# ratelimit_reset_header: "RateLimit-Reset" -# ratelimit_remaining_header: "RateLimit-Remaining" -# status_codes_for_ratelimit_hit: [429] +api_budget: + type: HTTPAPIBudget + policies: + # Members endpoints: 200 requests/min (most restrictive) + - type: MovingWindowCallRatePolicy + rates: + - limit: 200 + interval: PT1M + matchers: + - method: GET + url_path_pattern: "/members" + # GET /groups (list) and /descendant_groups: 200 requests/min + - type: MovingWindowCallRatePolicy + rates: + - limit: 200 + interval: PT1M + matchers: + - method: GET + url_path_pattern: "^groups$" + - type: MovingWindowCallRatePolicy + rates: + - limit: 200 + interval: PT1M + matchers: + - method: GET + url_path_pattern: "/descendant_groups$" + # GET /groups/:id and GET /projects/:id: 400 requests/min + - type: MovingWindowCallRatePolicy + rates: + - limit: 400 + interval: PT1M + matchers: + - method: GET + url_path_pattern: "^groups/[^/]+$" + - type: MovingWindowCallRatePolicy + rates: + - limit: 400 + interval: PT1M + matchers: + - method: GET + url_path_pattern: "^projects/[^/]+$" + # Catch-all: 2,000 requests/min for all other authenticated API traffic + - type: MovingWindowCallRatePolicy + rates: + - limit: 2000 + interval: PT1M + matchers: [] + ratelimit_reset_header: "RateLimit-Reset" + ratelimit_remaining_header: "RateLimit-Remaining" + status_codes_for_ratelimit_hit: [429] concurrency_level: type: ConcurrencyLevel diff --git a/airbyte-integrations/connectors/source-gitlab/metadata.yaml b/airbyte-integrations/connectors/source-gitlab/metadata.yaml index 43fcc17a6780..16e8daa20863 100644 --- a/airbyte-integrations/connectors/source-gitlab/metadata.yaml +++ b/airbyte-integrations/connectors/source-gitlab/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: api connectorType: source definitionId: 5e6175e5-68e1-4c17-bff9-56103bbb0d80 - dockerImageTag: 4.4.23-rc.3 + dockerImageTag: 4.4.23-rc.4 dockerRepository: airbyte/source-gitlab documentationUrl: https://docs.airbyte.com/integrations/sources/gitlab externalDocumentationUrls: diff --git a/docs/integrations/sources/gitlab.md b/docs/integrations/sources/gitlab.md index eb2e3a9be559..7e0ded5fd454 100644 --- a/docs/integrations/sources/gitlab.md +++ b/docs/integrations/sources/gitlab.md @@ -135,6 +135,7 @@ The connector silently skips any group, project, or resource that returns an HTT | Version | Date | Pull Request | Subject | | :------ | :--------- | :------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 4.4.23-rc.4 | 2026-03-31 | [75915](https://github.com/airbytehq/airbyte/pull/75915) | Re-enable HTTPAPIBudget with concurrency 10 for rate limit protection during progressive rollout | | 4.4.23-rc.3 | 2026-03-27 | [75537](https://github.com/airbytehq/airbyte/pull/75537) | Increase default concurrency from 8 to 10 for progressive rollout tuning | | 4.4.23-rc.2 | 2026-03-25 | [75480](https://github.com/airbytehq/airbyte/pull/75480) | Comment out HTTPAPIBudget to isolate concurrency tuning during progressive rollout | | 4.4.23-rc.1 | 2026-03-09 | [70858](https://github.com/airbytehq/airbyte/pull/70858) | Add HTTPAPIBudget and concurrency_level for improved sync performance | From 6ef0ce14d1e8dbb6bd47ce5d19bcae4882d1e434 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 13:24:37 -0700 Subject: [PATCH 302/379] ci(connectors): use admin bot for PR approval in connectors_up_to_date (#75920) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/connectors_up_to_date.yml | 28 +++++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/.github/workflows/connectors_up_to_date.yml b/.github/workflows/connectors_up_to_date.yml index 535e2f1649a3..95c123effd0c 100644 --- a/.github/workflows/connectors_up_to_date.yml +++ b/.github/workflows/connectors_up_to_date.yml @@ -271,19 +271,31 @@ jobs: PR_NUMBER: ${{ steps.create-pr.outputs.pull-request-number }} run: gh pr ready "$PR_NUMBER" - # --- Step 9: Apply bot approval --- - - name: Apply bot approval + # --- Step 9: Enable auto-merge --- + - name: Enable auto-merge on PR if: steps.check-changes.outputs.has_changes == 'true' - continue-on-error: true env: GH_TOKEN: ${{ steps.get-app-token.outputs.token }} PR_NUMBER: ${{ steps.create-pr.outputs.pull-request-number }} - run: gh pr review "$PR_NUMBER" --approve --body "Auto-approved by connectors up-to-date workflow." + run: gh pr merge "$PR_NUMBER" --squash --auto - # --- Step 10: Enable auto-merge --- - - name: Enable auto-merge on PR + # --- Step 10: Apply bot approval --- + # Use a different bot identity (admin) to approve, because the hoard bot + # that created the PR cannot approve its own PRs. + - name: Authenticate as 'octavia-bot-admin' GitHub App if: steps.check-changes.outputs.has_changes == 'true' + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 + id: get-admin-token + with: + owner: "airbytehq" + repositories: ${{ inputs.repo || github.event.repository.name }} + app-id: ${{ secrets.OCTAVIA_BOT_ADMIN_APP_ID }} + private-key: ${{ secrets.OCTAVIA_BOT_ADMIN_PRIVATE_KEY }} + + - name: Apply bot approval + if: steps.check-changes.outputs.has_changes == 'true' + continue-on-error: true env: - GH_TOKEN: ${{ steps.get-app-token.outputs.token }} + GH_TOKEN: ${{ steps.get-admin-token.outputs.token }} PR_NUMBER: ${{ steps.create-pr.outputs.pull-request-number }} - run: gh pr merge "$PR_NUMBER" --squash --auto + run: gh pr review "$PR_NUMBER" --approve --body "Auto-approved by connectors up-to-date workflow." From 3d4455c392c1bbc5c8467cccda40633c0ed09eec Mon Sep 17 00:00:00 2001 From: "Pedro S. Lopez" Date: Tue, 31 Mar 2026 13:29:32 -0700 Subject: [PATCH 303/379] ci(slash-commands): add /ai-dev command for testing dev playbooks (#75478) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/ai-dev-command.yml | 166 +++++++++++++++++++++++++++ .github/workflows/slash-commands.yml | 5 +- 2 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/ai-dev-command.yml diff --git a/.github/workflows/ai-dev-command.yml b/.github/workflows/ai-dev-command.yml new file mode 100644 index 000000000000..84cadf87851c --- /dev/null +++ b/.github/workflows/ai-dev-command.yml @@ -0,0 +1,166 @@ +name: AI Dev Playbook Command + +# Runs a dev version of an ai-skills playbook against an issue in this repo. +# Triggered via slash command: /ai-dev skills-pr= playbook= +# +# Examples: +# /ai-dev skills-pr=42 playbook=issue_triage +# /ai-dev skills-pr=42 playbook=issue_fix +# +# The dev playbook must already exist in the Devin API (created by the +# dev-playbooks.yml workflow in airbytehq/ai-skills when a PR is opened). + +on: + workflow_dispatch: + inputs: + issue: + description: "Issue number to test against" + type: string + required: false + skills-pr: + description: "ai-skills PR number with the dev playbook (named skills-pr to avoid collision with the pr static-arg)" + type: number + required: true + playbook: + description: "Playbook name (e.g. issue_triage, issue_fix)" + type: string + required: true + comment-id: + description: "The comment-id of the slash command. Used to update the comment with the status." + required: false + pr: + description: "PR number (passed by slash command dispatcher, unused)" + type: number + required: false + repo: + description: "Repo (passed by slash command dispatcher)" + required: false + default: "airbytehq/airbyte" + gitref: + description: "Git ref (passed by slash command dispatcher)" + required: false + +run-name: "AI Dev Playbook: !${{ github.event.inputs.playbook }}__dev-${{ github.event.inputs.skills-pr }}" + +permissions: + contents: read + issues: write + pull-requests: read + +jobs: + ai-dev: + runs-on: ubuntu-latest + steps: + - name: Get job variables + id: job-vars + run: | + echo "run-url=https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" >> $GITHUB_OUTPUT + + - name: Checkout code + uses: actions/checkout@v4 + + - name: Authenticate as GitHub App + uses: actions/create-github-app-token@v2 + id: get-app-token + with: + owner: "airbytehq" + repositories: "airbyte" + app-id: ${{ secrets.OCTAVIA_BOT_APP_ID }} + private-key: ${{ secrets.OCTAVIA_BOT_PRIVATE_KEY }} + + - name: Resolve inputs + id: resolve + env: + INPUT_PR_NUMBER: ${{ inputs.skills-pr }} + INPUT_PLAYBOOK_NAME: ${{ inputs.playbook }} + INPUT_ISSUE_NUMBER: ${{ inputs.issue }} + INPUT_COMMENT_ID: ${{ inputs.comment-id }} + GH_TOKEN: ${{ steps.get-app-token.outputs.token }} + run: | + set -euo pipefail + + # Resolve from env vars (safely passed via env: to avoid script injection) + pr_number="$INPUT_PR_NUMBER" + playbook_name="$INPUT_PLAYBOOK_NAME" + issue_number="$INPUT_ISSUE_NUMBER" + comment_id="$INPUT_COMMENT_ID" + + # When invoked via slash command, inputs.issue is empty because + # the slash-commands.yml static-args don't include issue=. + # Resolve the issue number from the comment-id via the GitHub API. + if [[ -z "$issue_number" || "$issue_number" == "0" ]] && [[ -n "$comment_id" ]]; then + echo "Resolving issue number from comment-id..." + issue_number=$(curl -s \ + -H "Authorization: Bearer $GH_TOKEN" \ + -H "Accept: application/vnd.github+json" \ + "https://api.github.com/repos/$GITHUB_REPOSITORY/issues/comments/$comment_id" \ + | jq -r '.issue_url | split("/") | last') + if [[ -z "$issue_number" || "$issue_number" == "null" ]]; then + echo "::warning::Could not resolve issue number from comment-id $comment_id" + issue_number="" + else + echo "Resolved issue number: $issue_number" + fi + fi + + if [[ -z "$pr_number" ]]; then + echo "::error::Missing required argument: pr (ai-skills PR number)" + exit 1 + fi + if ! [[ "$pr_number" =~ ^[0-9]+$ ]]; then + echo "::error::Invalid pr number: must be digits only" + exit 1 + fi + + if [[ -z "$playbook_name" ]]; then + echo "::error::Missing required argument: playbook (e.g. issue_triage)" + exit 1 + fi + if ! [[ "$playbook_name" =~ ^[a-z0-9_]+$ ]]; then + echo "::error::Invalid playbook name: must match [a-z0-9_]+" + exit 1 + fi + + dev_macro="!${playbook_name}__dev-${pr_number}" + + echo "pr_number=${pr_number}" >> $GITHUB_OUTPUT + echo "playbook_name=${playbook_name}" >> $GITHUB_OUTPUT + echo "issue_number=${issue_number}" >> $GITHUB_OUTPUT + echo "comment_id=${comment_id}" >> $GITHUB_OUTPUT + echo "dev_macro=${dev_macro}" >> $GITHUB_OUTPUT + + echo "Resolved inputs:" + echo " PR number: ${pr_number}" + echo " Playbook: ${playbook_name}" + echo " Issue: ${issue_number}" + echo " Dev macro: ${dev_macro}" + + - name: Post start comment + if: inputs.comment-id != '' + uses: peter-evans/create-or-update-comment@v4 + with: + token: ${{ steps.get-app-token.outputs.token }} + comment-id: ${{ inputs.comment-id }} + issue-number: ${{ steps.resolve.outputs.issue_number }} + body: | + > **AI Dev Playbook Starting** + > + > Using dev macro `${{ steps.resolve.outputs.dev_macro }}` from [ai-skills PR #${{ steps.resolve.outputs.pr_number }}](https://github.com/airbytehq/ai-skills/pull/${{ steps.resolve.outputs.pr_number }}) + > [View workflow run](${{ steps.job-vars.outputs.run-url }}) + + - name: Run dev playbook + uses: aaronsteers/devin-action@main + with: + comment-id: ${{ steps.resolve.outputs.comment_id }} + issue-number: ${{ steps.resolve.outputs.issue_number }} + playbook-macro: ${{ steps.resolve.outputs.dev_macro }} + devin-token: ${{ secrets.DEVIN_AI_API_KEY }} + github-token: ${{ steps.get-app-token.outputs.token }} + api-version: v3 + org-id: ${{ vars.DEVIN_AI_ORG_ID }} + start-message: "🔬 **Dev playbook session starting...** Using dev macro `${{ steps.resolve.outputs.dev_macro }}` from [ai-skills PR #${{ steps.resolve.outputs.pr_number }}](https://github.com/airbytehq/ai-skills/pull/${{ steps.resolve.outputs.pr_number }})" + bypass-approval: "true" + tags: | + ai-oncall + playbook-dev + dev-pr-${{ steps.resolve.outputs.pr_number }} diff --git a/.github/workflows/slash-commands.yml b/.github/workflows/slash-commands.yml index f38e748f32f0..f78009620975 100644 --- a/.github/workflows/slash-commands.yml +++ b/.github/workflows/slash-commands.yml @@ -58,15 +58,16 @@ jobs: commands: | ai-canary-prerelease - ai-docs-review ai-create-docs-pr + ai-dev + ai-docs-review ai-prove-fix ai-release-watch ai-review approve-regression-tests + build-connector-images bump-progressive-rollout-version bump-version - build-connector-images force-merge format-fix poe From 7285d569545165961647538c0a384baae62d22eb Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 13:43:27 -0700 Subject: [PATCH 304/379] ci(connectors): add step summary with PR links and no-op notes to connectors_up_to_date (#75924) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/connectors_up_to_date.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/connectors_up_to_date.yml b/.github/workflows/connectors_up_to_date.yml index 95c123effd0c..ba8bb9ce966c 100644 --- a/.github/workflows/connectors_up_to_date.yml +++ b/.github/workflows/connectors_up_to_date.yml @@ -210,6 +210,7 @@ jobs: else echo "has_changes=true" >> $GITHUB_OUTPUT echo "Changes detected for $CONNECTOR_NAME" + git diff --stat fi # --- Step 5: Create or update PR --- @@ -299,3 +300,20 @@ jobs: GH_TOKEN: ${{ steps.get-admin-token.outputs.token }} PR_NUMBER: ${{ steps.create-pr.outputs.pull-request-number }} run: gh pr review "$PR_NUMBER" --approve --body "Auto-approved by connectors up-to-date workflow." + + # --- Step 11: Write job summary --- + - name: Write step summary + if: always() + env: + PR_URL: ${{ steps.create-pr.outputs.pull-request-url }} + PR_NUMBER: ${{ steps.create-pr.outputs.pull-request-number }} + HAS_CHANGES: ${{ steps.check-changes.outputs.has_changes }} + run: | + if [ "$HAS_CHANGES" = "true" ] && [ -n "$PR_URL" ]; then + echo "### ✅ \`$CONNECTOR_NAME\` — PR created" >> $GITHUB_STEP_SUMMARY + echo "- **PR:** [#${PR_NUMBER}](${PR_URL})" >> $GITHUB_STEP_SUMMARY + elif [ "$HAS_CHANGES" = "true" ]; then + echo "### ❌ \`$CONNECTOR_NAME\` — changes detected but PR creation failed" >> $GITHUB_STEP_SUMMARY + else + echo "### ⏭️ \`$CONNECTOR_NAME\` — no changes (no-op)" >> $GITHUB_STEP_SUMMARY + fi From e7edab57b75579703fd052d6ae4c588c983300c8 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 13:55:02 -0700 Subject: [PATCH 305/379] ci(connectors): use structured CLI output instead of git diff for change detection (#75925) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/connectors_up_to_date.yml | 43 ++++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/.github/workflows/connectors_up_to_date.yml b/.github/workflows/connectors_up_to_date.yml index ba8bb9ce966c..509a463707c6 100644 --- a/.github/workflows/connectors_up_to_date.yml +++ b/.github/workflows/connectors_up_to_date.yml @@ -188,29 +188,48 @@ jobs: # --- Step 2: Bump dependencies (CDK + external) --- - name: Bump dependencies + id: bump-deps run: | - airbyte-ops local connector bump-deps \ - --name "$CONNECTOR_NAME" \ - --repo-path "$GITHUB_WORKSPACE" + BUMP_DEPS_OUTPUT=$( + airbyte-ops local connector bump-deps \ + --name "$CONNECTOR_NAME" \ + --repo-path "$GITHUB_WORKSPACE" + ) + echo "$BUMP_DEPS_OUTPUT" + DEPS_UPDATED=$(echo "$BUMP_DEPS_OUTPUT" | jq -r '.updated') + echo "updated=$DEPS_UPDATED" | tee -a $GITHUB_OUTPUT # --- Step 3: Update base image --- - name: Update base image in metadata.yaml + id: bump-base-image run: | - airbyte-ops local connector bump-base-image \ - --name "$CONNECTOR_NAME" \ - --repo-path "$GITHUB_WORKSPACE" + BUMP_IMAGE_OUTPUT=$( + airbyte-ops local connector bump-base-image \ + --name "$CONNECTOR_NAME" \ + --repo-path "$GITHUB_WORKSPACE" + ) + echo "$BUMP_IMAGE_OUTPUT" + IMAGE_UPDATED=$(echo "$BUMP_IMAGE_OUTPUT" | jq -r '.updated') + echo "updated=$IMAGE_UPDATED" | tee -a $GITHUB_OUTPUT # --- Step 4: Check for changes --- + # Use structured output from CLI commands instead of git diff to avoid + # false positives from Poetry lock file reformatting across versions. - name: Check for changes id: check-changes + env: + DEPS_UPDATED: ${{ steps.bump-deps.outputs.updated }} + IMAGE_UPDATED: ${{ steps.bump-base-image.outputs.updated }} run: | - if git diff --quiet; then - echo "has_changes=false" >> $GITHUB_OUTPUT - echo "No changes detected for $CONNECTOR_NAME" - else + echo "bump-deps updated: $DEPS_UPDATED" + echo "bump-base-image updated: $IMAGE_UPDATED" + if [ "$DEPS_UPDATED" = "true" ] || [ "$IMAGE_UPDATED" = "true" ]; then echo "has_changes=true" >> $GITHUB_OUTPUT echo "Changes detected for $CONNECTOR_NAME" git diff --stat + else + echo "has_changes=false" >> $GITHUB_OUTPUT + echo "No changes detected for $CONNECTOR_NAME (CLI reports no updates)" fi # --- Step 5: Create or update PR --- @@ -308,10 +327,14 @@ jobs: PR_URL: ${{ steps.create-pr.outputs.pull-request-url }} PR_NUMBER: ${{ steps.create-pr.outputs.pull-request-number }} HAS_CHANGES: ${{ steps.check-changes.outputs.has_changes }} + DEPS_UPDATED: ${{ steps.bump-deps.outputs.updated }} + IMAGE_UPDATED: ${{ steps.bump-base-image.outputs.updated }} run: | if [ "$HAS_CHANGES" = "true" ] && [ -n "$PR_URL" ]; then echo "### ✅ \`$CONNECTOR_NAME\` — PR created" >> $GITHUB_STEP_SUMMARY echo "- **PR:** [#${PR_NUMBER}](${PR_URL})" >> $GITHUB_STEP_SUMMARY + [ "$DEPS_UPDATED" = "true" ] && echo "- Dependencies updated" >> $GITHUB_STEP_SUMMARY + [ "$IMAGE_UPDATED" = "true" ] && echo "- Base image updated" >> $GITHUB_STEP_SUMMARY elif [ "$HAS_CHANGES" = "true" ]; then echo "### ❌ \`$CONNECTOR_NAME\` — changes detected but PR creation failed" >> $GITHUB_STEP_SUMMARY else From 09d7eae9df665f347e2e96133ba5ac4aeaafee2d Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 14:12:47 -0700 Subject: [PATCH 306/379] =?UTF-8?q?test:=20progressive=20rollout=20e2e=20t?= =?UTF-8?q?est=20=E2=80=94=20bump=20source-faker=20to=20RC2=20(7.1.0-rc.2)?= =?UTF-8?q?=20(#75926)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- airbyte-integrations/connectors/source-faker/metadata.yaml | 2 +- airbyte-integrations/connectors/source-faker/pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/airbyte-integrations/connectors/source-faker/metadata.yaml b/airbyte-integrations/connectors/source-faker/metadata.yaml index ccc5ad9946cd..0eabd0325ba8 100644 --- a/airbyte-integrations/connectors/source-faker/metadata.yaml +++ b/airbyte-integrations/connectors/source-faker/metadata.yaml @@ -9,7 +9,7 @@ data: connectorSubtype: api connectorType: source definitionId: dfd88b22-b603-4c3d-aad7-3701784586b1 - dockerImageTag: 7.1.0-rc.1 + dockerImageTag: 7.1.0-rc.2 dockerRepository: airbyte/source-faker documentationUrl: https://docs.airbyte.com/integrations/sources/faker externalDocumentationUrls: diff --git a/airbyte-integrations/connectors/source-faker/pyproject.toml b/airbyte-integrations/connectors/source-faker/pyproject.toml index 6136023c2721..eb8400c0326a 100644 --- a/airbyte-integrations/connectors/source-faker/pyproject.toml +++ b/airbyte-integrations/connectors/source-faker/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "7.1.0-rc.1" +version = "7.1.0-rc.2" name = "source-faker" description = "Source implementation for fake but realistic looking data." authors = [ "Airbyte ",] From 99943bcb2ed3a27d5bc305f5bf0f870088c39510 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 14:27:50 -0700 Subject: [PATCH 307/379] ci(connectors): include outdated package names in PR description and step summary (#75928) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/connectors_up_to_date.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/connectors_up_to_date.yml b/.github/workflows/connectors_up_to_date.yml index 509a463707c6..b069e8281817 100644 --- a/.github/workflows/connectors_up_to_date.yml +++ b/.github/workflows/connectors_up_to_date.yml @@ -198,6 +198,8 @@ jobs: echo "$BUMP_DEPS_OUTPUT" DEPS_UPDATED=$(echo "$BUMP_DEPS_OUTPUT" | jq -r '.updated') echo "updated=$DEPS_UPDATED" | tee -a $GITHUB_OUTPUT + OUTDATED_PKGS=$(echo "$BUMP_DEPS_OUTPUT" | jq -r '(.outdated_packages // []) | join(", ")') + echo "outdated_packages=$OUTDATED_PKGS" | tee -a $GITHUB_OUTPUT # --- Step 3: Update base image --- - name: Update base image in metadata.yaml @@ -249,6 +251,8 @@ jobs: body: | Updates dependencies for `${{ env.CONNECTOR_NAME }}`. + **Updated packages:** ${{ steps.bump-deps.outputs.outdated_packages || 'N/A' }} + 🤖 Generated by [automated workflow](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}). labels: | area/connectors @@ -329,11 +333,12 @@ jobs: HAS_CHANGES: ${{ steps.check-changes.outputs.has_changes }} DEPS_UPDATED: ${{ steps.bump-deps.outputs.updated }} IMAGE_UPDATED: ${{ steps.bump-base-image.outputs.updated }} + OUTDATED_PKGS: ${{ steps.bump-deps.outputs.outdated_packages }} run: | if [ "$HAS_CHANGES" = "true" ] && [ -n "$PR_URL" ]; then echo "### ✅ \`$CONNECTOR_NAME\` — PR created" >> $GITHUB_STEP_SUMMARY echo "- **PR:** [#${PR_NUMBER}](${PR_URL})" >> $GITHUB_STEP_SUMMARY - [ "$DEPS_UPDATED" = "true" ] && echo "- Dependencies updated" >> $GITHUB_STEP_SUMMARY + [ "$DEPS_UPDATED" = "true" ] && echo "- Dependencies updated: $OUTDATED_PKGS" >> $GITHUB_STEP_SUMMARY [ "$IMAGE_UPDATED" = "true" ] && echo "- Base image updated" >> $GITHUB_STEP_SUMMARY elif [ "$HAS_CHANGES" = "true" ]; then echo "### ❌ \`$CONNECTOR_NAME\` — changes detected but PR creation failed" >> $GITHUB_STEP_SUMMARY From 5d792a7309effcb0c387f14243d108c8b548d415 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 14:48:55 -0700 Subject: [PATCH 308/379] fix(connectors): prevent step summary exit code 1 from short-circuit evaluation (#75931) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/connectors_up_to_date.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/connectors_up_to_date.yml b/.github/workflows/connectors_up_to_date.yml index b069e8281817..30d6ea2b6e76 100644 --- a/.github/workflows/connectors_up_to_date.yml +++ b/.github/workflows/connectors_up_to_date.yml @@ -338,8 +338,8 @@ jobs: if [ "$HAS_CHANGES" = "true" ] && [ -n "$PR_URL" ]; then echo "### ✅ \`$CONNECTOR_NAME\` — PR created" >> $GITHUB_STEP_SUMMARY echo "- **PR:** [#${PR_NUMBER}](${PR_URL})" >> $GITHUB_STEP_SUMMARY - [ "$DEPS_UPDATED" = "true" ] && echo "- Dependencies updated: $OUTDATED_PKGS" >> $GITHUB_STEP_SUMMARY - [ "$IMAGE_UPDATED" = "true" ] && echo "- Base image updated" >> $GITHUB_STEP_SUMMARY + [ "$DEPS_UPDATED" = "true" ] && echo "- Dependencies updated: $OUTDATED_PKGS" >> $GITHUB_STEP_SUMMARY || true + [ "$IMAGE_UPDATED" = "true" ] && echo "- Base image updated" >> $GITHUB_STEP_SUMMARY || true elif [ "$HAS_CHANGES" = "true" ]; then echo "### ❌ \`$CONNECTOR_NAME\` — changes detected but PR creation failed" >> $GITHUB_STEP_SUMMARY else From 4a7f6ddb8e4af779d3c2b9191f3cf4521e8beab2 Mon Sep 17 00:00:00 2001 From: "octavia-bot[bot]" <108746235+octavia-bot[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 22:15:00 +0000 Subject: [PATCH 309/379] docs: sync agent connector docs from airbyte-agent-connectors repo (#75932) Co-authored-by: ian-at-airbyte <187576150+ian-at-airbyte@users.noreply.github.com> --- docs/ai-agents/connectors/linear/README.md | 6 +- docs/ai-agents/connectors/linear/REFERENCE.md | 117 ++++++++++++++++-- 2 files changed, 109 insertions(+), 14 deletions(-) diff --git a/docs/ai-agents/connectors/linear/README.md b/docs/ai-agents/connectors/linear/README.md index 914ab81a6009..612cc6dd0a07 100644 --- a/docs/ai-agents/connectors/linear/README.md +++ b/docs/ai-agents/connectors/linear/README.md @@ -124,7 +124,7 @@ See the official [Linear API reference](https://linear.app/developers/graphql). ## Version information -- **Package version:** 0.19.121 -- **Connector version:** 0.1.13 -- **Generated with Connector SDK commit SHA:** 2afeb237479950157f43a4d8bc3eeb181f5fd1c1 +- **Package version:** 0.19.122 +- **Connector version:** 0.1.14 +- **Generated with Connector SDK commit SHA:** 4a9d86940cf9c8e65c0668776b4d8f4e129753ec - **Changelog:** [View changelog](https://github.com/airbytehq/airbyte-agent-connectors/blob/main/connectors/linear/CHANGELOG.md) \ No newline at end of file diff --git a/docs/ai-agents/connectors/linear/REFERENCE.md b/docs/ai-agents/connectors/linear/REFERENCE.md index 4703c7726a3f..4bfb843e4240 100644 --- a/docs/ai-agents/connectors/linear/REFERENCE.md +++ b/docs/ai-agents/connectors/linear/REFERENCE.md @@ -117,7 +117,16 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | Field Name | Type | Description | |------------|------|-------------| -| `data` | `object` | | +| `id` | `string` | | +| `title` | `string` | | +| `description` | `string \| any` | | +| `state` | `object \| any` | | +| `priority` | `number \| any` | | +| `assignee` | `object \| any` | | +| `team` | `object \| any` | | +| `project` | `object \| any` | | +| `createdAt` | `string` | | +| `updatedAt` | `string` | | @@ -179,7 +188,17 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | Field Name | Type | Description | |------------|------|-------------| -| `data` | `object` | | +| `success` | `boolean` | | +| `issue` | `object` | | +| `issue.id` | `string` | | +| `issue.title` | `string` | | +| `issue.description` | `string \| any` | | +| `issue.state` | `object \| any` | | +| `issue.priority` | `number \| any` | | +| `issue.assignee` | `object \| any` | | +| `issue.project` | `object \| any` | | +| `issue.createdAt` | `string` | | +| `issue.updatedAt` | `string` | | @@ -247,7 +266,17 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | Field Name | Type | Description | |------------|------|-------------| -| `data` | `object` | | +| `success` | `boolean` | | +| `issue` | `object` | | +| `issue.id` | `string` | | +| `issue.title` | `string` | | +| `issue.description` | `string \| any` | | +| `issue.state` | `object \| any` | | +| `issue.priority` | `number \| any` | | +| `issue.assignee` | `object \| any` | | +| `issue.project` | `object \| any` | | +| `issue.createdAt` | `string` | | +| `issue.updatedAt` | `string` | | @@ -516,7 +545,15 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | Field Name | Type | Description | |------------|------|-------------| -| `data` | `object` | | +| `id` | `string` | | +| `name` | `string` | | +| `description` | `string \| any` | | +| `state` | `string \| any` | | +| `startDate` | `string \| any` | | +| `targetDate` | `string \| any` | | +| `lead` | `object \| any` | | +| `createdAt` | `string` | | +| `updatedAt` | `string` | | @@ -757,7 +794,13 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | Field Name | Type | Description | |------------|------|-------------| -| `data` | `object` | | +| `id` | `string` | | +| `name` | `string` | | +| `key` | `string` | | +| `description` | `string \| any` | | +| `timezone` | `string \| any` | | +| `createdAt` | `string` | | +| `updatedAt` | `string` | | @@ -938,8 +981,22 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | Field Name | Type | Description | |------------|------|-------------| -| `data` | `object` | | +| `id` | `string` | | +| `name` | `string` | | +| `email` | `string` | | +| `displayName` | `string \| any` | | +| `active` | `boolean` | | +| `admin` | `boolean` | | +| `createdAt` | `string` | | +| `updatedAt` | `string` | | + +#### Meta + +| Field Name | Type | Description | +|------------|------|-------------| +| `hasNextPage` | `boolean` | | +| `endCursor` | `string \| null` | | @@ -985,7 +1042,14 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | Field Name | Type | Description | |------------|------|-------------| -| `data` | `object` | | +| `id` | `string` | | +| `name` | `string` | | +| `email` | `string` | | +| `displayName` | `string \| any` | | +| `active` | `boolean` | | +| `admin` | `boolean` | | +| `createdAt` | `string` | | +| `updatedAt` | `string` | | @@ -1132,8 +1196,20 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | Field Name | Type | Description | |------------|------|-------------| -| `data` | `object` | | +| `id` | `string` | | +| `body` | `string` | | +| `user` | `object \| any` | | +| `issue` | `object \| any` | | +| `createdAt` | `string` | | +| `updatedAt` | `string` | | + + +#### Meta +| Field Name | Type | Description | +|------------|------|-------------| +| `hasNextPage` | `boolean` | | +| `endCursor` | `string \| null` | | @@ -1179,7 +1255,12 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | Field Name | Type | Description | |------------|------|-------------| -| `data` | `object` | | +| `id` | `string` | | +| `body` | `string` | | +| `user` | `object \| any` | | +| `issue` | `object \| any` | | +| `createdAt` | `string` | | +| `updatedAt` | `string` | | @@ -1229,7 +1310,14 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | Field Name | Type | Description | |------------|------|-------------| -| `data` | `object` | | +| `success` | `boolean` | | +| `comment` | `object` | | +| `comment.id` | `string` | | +| `comment.body` | `string` | | +| `comment.user` | `object \| any` | | +| `comment.issue` | `object \| any` | | +| `comment.createdAt` | `string` | | +| `comment.updatedAt` | `string` | | @@ -1279,7 +1367,14 @@ curl --location 'https://api.airbyte.ai/api/v1/integrations/connectors/{your_con | Field Name | Type | Description | |------------|------|-------------| -| `data` | `object` | | +| `success` | `boolean` | | +| `comment` | `object` | | +| `comment.id` | `string` | | +| `comment.body` | `string` | | +| `comment.user` | `object \| any` | | +| `comment.issue` | `object \| any` | | +| `comment.createdAt` | `string` | | +| `comment.updatedAt` | `string` | | From 7bd446d63233d056da3cd2880260af098b5a0623 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 22:15:06 +0000 Subject: [PATCH 310/379] docs(source-faker): add missing 7.1.0-rc.2 changelog entry (#75927) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- docs/integrations/sources/faker.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/integrations/sources/faker.md b/docs/integrations/sources/faker.md index 21b078c1eb8f..5968d4939977 100644 --- a/docs/integrations/sources/faker.md +++ b/docs/integrations/sources/faker.md @@ -47,6 +47,7 @@ Each purchase record includes: `id`, `user_id`, `product_id`, `created_at`, `upd | Version | Date | Pull Request | Subject | |:------------|:-----------| :-------------------------------------------------------------------------------------------------------------------- |:----------------------------------------------------------------------------------------------------------------| +| 7.1.0-rc.2 | 2026-03-31 | [75926](https://github.com/airbytehq/airbyte/pull/75926) | Bump source-faker to RC2 for progressive rollout e2e test | | 7.1.0-rc.1 | 2026-03-31 | [75908](https://github.com/airbytehq/airbyte/pull/75908) | test: progressive rollout e2e test on source-faker | | 7.0.4 | 2026-03-31 | [75657](https://github.com/airbytehq/airbyte/pull/75657) | Patch version bump (test publish) | | 7.0.3 | 2026-03-20 | [75256](https://github.com/airbytehq/airbyte/pull/75256) | Re-release to verify yank/un-yank behavior in ops CLI registry pipeline | From d1aa3cadd457e40b2844fe37c76a4a7db7bcdc22 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 22:15:12 +0000 Subject: [PATCH 311/379] docs(source-gitlab): fix concurrency default and rate limit documentation (#75923) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: bot_apk --- docs/integrations/sources/gitlab.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/integrations/sources/gitlab.md b/docs/integrations/sources/gitlab.md index 7e0ded5fd454..28e1342d599a 100644 --- a/docs/integrations/sources/gitlab.md +++ b/docs/integrations/sources/gitlab.md @@ -50,7 +50,7 @@ Log into [GitLab](https://gitlab.com) and then generate a [personal access token 7. **Start date** (Optional) - The date from which you'd like to replicate data for streams, in the format `YYYY-MM-DDT00:00:00Z`. 8. **Groups** (Optional) - List of GitLab group IDs, e.g. `airbytehq` for a single group. 9. **Projects** (Optional) - List of GitLab projects to pull data for, e.g. `airbytehq/airbyte`. -10. **Number of Concurrent Workers** (Optional) - The number of concurrent threads used for syncing. Higher values can speed up syncs but may hit rate limits. Defaults to 8. Adjust based on your GitLab instance's rate limits. +10. **Number of Concurrent Workers** (Optional) - The number of concurrent threads used for syncing. Higher values can speed up syncs but may hit rate limits. Defaults to 10. Adjust based on your GitLab instance's rate limits. 11. Click **Set up source**. **Note:** You can specify either Group IDs or Project IDs in the source configuration. If both fields are blank, the connector retrieves a list of all groups accessible to the configured token and ingests as normal. @@ -109,12 +109,13 @@ This connector uses GitLab API v4. It works with both GitLab.com and self-hosted ### Rate limits -GitLab.com enforces per-endpoint rate limits on its REST API. The following defaults apply to [Groups API](https://docs.gitlab.com/administration/settings/rate_limit_on_members_api/), [Projects API](https://docs.gitlab.com/administration/settings/rate_limit_on_projects_api/), and general authenticated traffic: +GitLab.com enforces per-endpoint rate limits on its REST API. The following defaults apply to the [Groups API](https://docs.gitlab.com/administration/settings/rate_limit_on_groups_api/), [Members API](https://docs.gitlab.com/administration/settings/rate_limit_on_members_api/), [Projects API](https://docs.gitlab.com/administration/settings/rate_limit_on_projects_api/), and general authenticated traffic: | Endpoint | Rate limit | | :--- | :--- | | `GET /groups` | 200 requests/min | | `GET /groups/:id` | 400 requests/min | +| `GET /groups/:id/descendant_groups` | 200 requests/min | | `GET /projects/:id` | 400 requests/min | | `GET /groups/:id/members/all` | 200 requests/min | | `GET /projects/:id/members/all` | 200 requests/min | From b38f9639249a827dfdda8098407af099bcddcd1a Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 15:19:08 -0700 Subject: [PATCH 312/379] fix(ci): add checkout step to finalize_rollout rc-cleanup job (#75934) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/finalize_rollout.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/finalize_rollout.yml b/.github/workflows/finalize_rollout.yml index b3d46b8b0bac..6eb2f7599f0d 100644 --- a/.github/workflows/finalize_rollout.yml +++ b/.github/workflows/finalize_rollout.yml @@ -44,6 +44,13 @@ jobs: fi shell: bash + # The cleanup CLI reads metadata.yaml from the local repo to + # resolve the connector's dockerRepository. + - name: Checkout Airbyte repo + uses: actions/checkout@v4 + with: + fetch-depth: 1 + - name: Install uv uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0 From d0eb7ee21e28d5dee92296b02a3315422daa022e Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 15:29:02 -0700 Subject: [PATCH 313/379] ci(auto-merge): rewrite as native GitHub Actions (#75929) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/auto_merge.yml | 386 +++++++++++++++++++++++++++++-- 1 file changed, 365 insertions(+), 21 deletions(-) diff --git a/.github/workflows/auto_merge.yml b/.github/workflows/auto_merge.yml index 8adff5140023..9a0b9bda9732 100644 --- a/.github/workflows/auto_merge.yml +++ b/.github/workflows/auto_merge.yml @@ -1,41 +1,385 @@ name: Auto merge connector PRs Cron +# Dry-run mode is controlled by the org-level variable ENABLE_CONNECTOR_AUTO_MERGE. +# Set to "true" to enable real merges; any other value (or unset) runs in dry-run mode. +# Manage at: https://github.com/organizations/airbytehq/settings/variables/actions on: schedule: # Every 2 hours on the hour. - cron: "0 */2 * * *" workflow_dispatch: + +# All repo operations use GitHub App tokens, not GITHUB_TOKEN. +permissions: {} + jobs: - run_auto_merge: - name: Run auto-merge + # ---------- Job 1: Discover candidate PRs ---------- + list-candidates: + name: List eligible PRs + runs-on: ubuntu-24.04 + steps: + # ---------- Authentication ---------- + - name: Authenticate as 'octavia-bot-hoard' GitHub App + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 + id: get-hoard-token + with: + owner: "airbytehq" + repositories: "airbyte" + app-id: ${{ secrets.OCTAVIA_BOT_HOARD_APP_ID }} + private-key: ${{ secrets.OCTAVIA_BOT_HOARD_PRIVATE_KEY }} + + # ---------- Find candidate PRs ---------- + - name: Find force-merge PRs (bypass-ci-checks label) + id: force-prs + env: + GH_TOKEN: ${{ steps.get-hoard-token.outputs.token }} + run: | + gh pr list \ + --repo airbytehq/airbyte \ + --label "auto-merge/bypass-ci-checks" \ + --state open \ + --base master \ + --json number,title \ + --limit 100 > /tmp/force.json + count=$(jq length /tmp/force.json) + echo "force-matrix=$(cat /tmp/force.json)" | tee -a $GITHUB_OUTPUT + echo "force-count=$count" | tee -a $GITHUB_OUTPUT + + - name: Find normal-merge PRs (auto-merge label, excluding force-merge) + id: normal-prs + env: + GH_TOKEN: ${{ steps.get-hoard-token.outputs.token }} + run: | + gh pr list \ + --repo airbytehq/airbyte \ + --label "auto-merge" \ + --state open \ + --base master \ + --json number,title \ + --limit 100 > /tmp/auto-merge.json + # Exclude PRs already in the force-merge set + jq -c --argjson force '${{ steps.force-prs.outputs.force-matrix }}' \ + '[.[] | select(.number as $n | $force | map(.number) | index($n) | not)]' \ + /tmp/auto-merge.json > /tmp/normal.json + count=$(jq length /tmp/normal.json) + echo "normal-matrix=$(cat /tmp/normal.json)" | tee -a $GITHUB_OUTPUT + echo "normal-count=$count" | tee -a $GITHUB_OUTPUT + + # ---------- Fetch required checks ---------- + - name: Fetch required checks for master branch + id: required-checks + if: fromJSON(steps.normal-prs.outputs.normal-count) > 0 + uses: actions/github-script@v7 + with: + github-token: ${{ steps.get-hoard-token.outputs.token }} + script: | + const { data: rules } = await github.request( + 'GET /repos/{owner}/{repo}/rules/branches/{branch}', + { owner: 'airbytehq', repo: 'airbyte', branch: 'master' } + ); + const checks = []; + for (const rule of rules) { + if (rule.type === 'required_status_checks') { + for (const check of (rule.parameters?.required_status_checks || [])) { + checks.push(check.context); + } + } + } + core.info(`Required checks (${checks.length}): ${JSON.stringify(checks)}`); + core.setOutput('checks', JSON.stringify(checks)); + outputs: + normal-matrix: ${{ steps.normal-prs.outputs.normal-matrix }} + normal-count: ${{ steps.normal-prs.outputs.normal-count }} + force-matrix: ${{ steps.force-prs.outputs.force-matrix }} + force-count: ${{ steps.force-prs.outputs.force-count }} + required-checks: ${{ steps.required-checks.outputs.checks }} + + # ---------- Job 2: Normal merge (verify CI first) ---------- + normal-merge: + name: "Merge #${{ matrix.pr.number }}" + needs: list-candidates + if: fromJSON(needs.list-candidates.outputs.normal-count) > 0 runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + pr: ${{ fromJSON(needs.list-candidates.outputs.normal-matrix) }} + env: + PR_NUMBER: ${{ matrix.pr.number }} + PR_TITLE: ${{ matrix.pr.title }} steps: - - name: Authenticate as GitHub App + # ---------- Authentication ---------- + - name: Authenticate as 'octavia-bot-hoard' GitHub App uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 - id: get-app-token + id: get-hoard-token with: owner: "airbytehq" repositories: "airbyte" app-id: ${{ secrets.OCTAVIA_BOT_HOARD_APP_ID }} private-key: ${{ secrets.OCTAVIA_BOT_HOARD_PRIVATE_KEY }} - - name: Checkout - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - - name: Set up Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + + # ---------- Validation ---------- + - name: Check PR is still open + id: check-open + env: + GH_TOKEN: ${{ steps.get-hoard-token.outputs.token }} + run: | + state=$(gh pr view "$PR_NUMBER" --repo airbytehq/airbyte --json state --jq '.state') + echo "state=$state" | tee -a $GITHUB_OUTPUT + + - name: Validate connector-only file paths + if: steps.check-open.outputs.state == 'OPEN' + id: validate-paths + env: + GH_TOKEN: ${{ steps.get-hoard-token.outputs.token }} + run: | + set -e + gh pr diff "$PR_NUMBER" --repo airbytehq/airbyte --name-only > /tmp/changed-files.txt + valid=true + while IFS= read -r file; do + case "$file" in + airbyte-integrations/connectors/*) ;; + docs/integrations/sources/*) ;; + docs/integrations/destinations/*) ;; + docs/ai-agents/connectors/*) ;; + docs/developers/pyairbyte/*) ;; + docusaurus/src/data/*) ;; + *) valid=false; echo "::warning::Non-connector file: $file"; break ;; + esac + done < /tmp/changed-files.txt + echo "valid=$valid" | tee -a $GITHUB_OUTPUT + + - name: Verify required status checks pass + if: steps.check-open.outputs.state == 'OPEN' && steps.validate-paths.outputs.valid == 'true' + id: verify-checks + uses: actions/github-script@v7 + env: + REQUIRED_CHECKS_JSON: ${{ needs.list-candidates.outputs.required-checks }} + with: + github-token: ${{ steps.get-hoard-token.outputs.token }} + script: | + const prNum = Number(process.env.PR_NUMBER); + const requiredChecks = new Set(JSON.parse(process.env.REQUIRED_CHECKS_JSON || '[]')); + + const { data: pr } = await github.rest.pulls.get({ + owner: 'airbytehq', repo: 'airbyte', pull_number: prNum, + }); + const sha = pr.head.sha; + + const statuses = await github.paginate( + github.rest.repos.listCommitStatusesForRef, + { owner: 'airbytehq', repo: 'airbyte', ref: sha, per_page: 100 } + ); + const successStatuses = new Set( + statuses.filter(s => s.state === 'success').map(s => s.context) + ); + + const checkRuns = await github.paginate( + github.rest.checks.listForRef, + { owner: 'airbytehq', repo: 'airbyte', ref: sha, per_page: 100 }, + (response) => response.data + ); + const successChecks = new Set( + checkRuns + .filter(cr => cr.conclusion === 'success' || cr.conclusion === 'skipped') + .map(cr => cr.name) + ); + + const allPassing = new Set([...successStatuses, ...successChecks]); + const missing = [...requiredChecks].filter(c => !allPassing.has(c)); + + if (missing.length > 0) { + core.info(`Missing checks: ${missing.join(', ')}`); + core.setOutput('ready', 'false'); + } else { + core.info('All required checks passing'); + core.setOutput('ready', 'true'); + } + + # ---------- Eligibility gate ---------- + - name: Determine merge eligibility + id: eligible + run: > + echo "result=${{ + steps.check-open.outputs.state == 'OPEN' + && steps.validate-paths.outputs.valid == 'true' + && steps.verify-checks.outputs.ready == 'true' + }}" | tee -a $GITHUB_OUTPUT + + # ---------- Prepare PR for merge ---------- + - name: Check if PR is a draft + if: steps.eligible.outputs.result == 'true' + id: check-draft + env: + GH_TOKEN: ${{ steps.get-hoard-token.outputs.token }} + run: | + is_draft=$(gh pr view "$PR_NUMBER" --repo airbytehq/airbyte --json isDraft --jq '.isDraft') + echo "is_draft=$is_draft" | tee -a $GITHUB_OUTPUT + + - name: Mark draft PR as ready for review + if: steps.eligible.outputs.result == 'true' && steps.check-draft.outputs.is_draft == 'true' + env: + GH_TOKEN: ${{ steps.get-hoard-token.outputs.token }} + run: gh pr ready "$PR_NUMBER" --repo airbytehq/airbyte + + # ---------- Approve and merge ---------- + - name: Authenticate as 'octavia-bot-admin' GitHub App + if: steps.eligible.outputs.result == 'true' + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 + id: get-admin-token with: - python-version: "3.11" - check-latest: true - update-environment: true - - name: Install and configure Poetry - uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1.4.1 + owner: "airbytehq" + repositories: "airbyte" + app-id: ${{ secrets.OCTAVIA_BOT_ADMIN_APP_ID }} + private-key: ${{ secrets.OCTAVIA_BOT_ADMIN_PRIVATE_KEY }} + + - name: Approve PR with admin bot + if: steps.eligible.outputs.result == 'true' + env: + GH_TOKEN: ${{ steps.get-admin-token.outputs.token }} + run: > + gh pr review "$PR_NUMBER" + --repo airbytehq/airbyte + --approve + --body "Auto-approved by auto-merge workflow." + + - name: Squash merge PR + if: steps.eligible.outputs.result == 'true' && vars.ENABLE_CONNECTOR_AUTO_MERGE == 'true' + env: + GH_TOKEN: ${{ steps.get-hoard-token.outputs.token }} + run: | + for attempt in 1 2 3; do + if gh pr merge "$PR_NUMBER" --repo airbytehq/airbyte --squash; then + echo "::notice::Merged PR #$PR_NUMBER: $PR_TITLE" + exit 0 + fi + echo "::warning::Merge attempt $attempt/3 failed, retrying in 60s..." + sleep 60 + done + echo "::error::Failed to merge PR #$PR_NUMBER after 3 attempts" + exit 1 + + - name: Dry-run notice + if: steps.eligible.outputs.result == 'true' && vars.ENABLE_CONNECTOR_AUTO_MERGE != 'true' + run: echo "::notice::DRY RUN — would merge PR #$PR_NUMBER" + + # ---------- Job 3: Force merge (bypass CI checks) ---------- + force-merge: + name: "Force-merge #${{ matrix.pr.number }}" + needs: list-candidates + if: fromJSON(needs.list-candidates.outputs.force-count) > 0 + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + pr: ${{ fromJSON(needs.list-candidates.outputs.force-matrix) }} + env: + PR_NUMBER: ${{ matrix.pr.number }} + PR_TITLE: ${{ matrix.pr.title }} + steps: + # ---------- Authentication ---------- + - name: Authenticate as 'octavia-bot-hoard' GitHub App + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 + id: get-hoard-token with: - version: 1.8.5 - - name: Run auto merge - shell: bash - working-directory: airbyte-ci/connectors/auto_merge + owner: "airbytehq" + repositories: "airbyte" + app-id: ${{ secrets.OCTAVIA_BOT_HOARD_APP_ID }} + private-key: ${{ secrets.OCTAVIA_BOT_HOARD_PRIVATE_KEY }} + + # ---------- Validation ---------- + - name: Check PR is still open + id: check-open env: - GITHUB_TOKEN: ${{ steps.get-app-token.outputs.token }} - AUTO_MERGE_PRODUCTION: ${{ vars.ENABLE_CONNECTOR_AUTO_MERGE }} + GH_TOKEN: ${{ steps.get-hoard-token.outputs.token }} run: | - poetry install - poetry run auto-merge + state=$(gh pr view "$PR_NUMBER" --repo airbytehq/airbyte --json state --jq '.state') + echo "state=$state" | tee -a $GITHUB_OUTPUT + + - name: Validate connector-only file paths + if: steps.check-open.outputs.state == 'OPEN' + id: validate-paths + env: + GH_TOKEN: ${{ steps.get-hoard-token.outputs.token }} + run: | + set -e + gh pr diff "$PR_NUMBER" --repo airbytehq/airbyte --name-only > /tmp/changed-files.txt + valid=true + while IFS= read -r file; do + case "$file" in + airbyte-integrations/connectors/*) ;; + docs/integrations/sources/*) ;; + docs/integrations/destinations/*) ;; + docs/ai-agents/connectors/*) ;; + docs/developers/pyairbyte/*) ;; + docusaurus/src/data/*) ;; + *) valid=false; echo "::warning::Non-connector file: $file"; break ;; + esac + done < /tmp/changed-files.txt + echo "valid=$valid" | tee -a $GITHUB_OUTPUT + + # ---------- Eligibility gate ---------- + - name: Determine merge eligibility + id: eligible + run: > + echo "result=${{ + steps.check-open.outputs.state == 'OPEN' + && steps.validate-paths.outputs.valid == 'true' + }}" | tee -a $GITHUB_OUTPUT + + # ---------- Prepare PR for merge ---------- + - name: Check if PR is a draft + if: steps.eligible.outputs.result == 'true' + id: check-draft + env: + GH_TOKEN: ${{ steps.get-hoard-token.outputs.token }} + run: | + is_draft=$(gh pr view "$PR_NUMBER" --repo airbytehq/airbyte --json isDraft --jq '.isDraft') + echo "is_draft=$is_draft" | tee -a $GITHUB_OUTPUT + + - name: Mark draft PR as ready for review + if: steps.eligible.outputs.result == 'true' && steps.check-draft.outputs.is_draft == 'true' + env: + GH_TOKEN: ${{ steps.get-hoard-token.outputs.token }} + run: gh pr ready "$PR_NUMBER" --repo airbytehq/airbyte + + # ---------- Approve and merge ---------- + - name: Authenticate as 'octavia-bot-admin' GitHub App + if: steps.eligible.outputs.result == 'true' + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 + id: get-admin-token + with: + owner: "airbytehq" + repositories: "airbyte" + app-id: ${{ secrets.OCTAVIA_BOT_ADMIN_APP_ID }} + private-key: ${{ secrets.OCTAVIA_BOT_ADMIN_PRIVATE_KEY }} + + - name: Approve PR with admin bot + if: steps.eligible.outputs.result == 'true' + env: + GH_TOKEN: ${{ steps.get-admin-token.outputs.token }} + run: > + gh pr review "$PR_NUMBER" + --repo airbytehq/airbyte + --approve + --body "Auto-approved by auto-merge workflow (bypass-ci)." + + - name: Force squash merge PR + if: steps.eligible.outputs.result == 'true' && vars.ENABLE_CONNECTOR_AUTO_MERGE == 'true' + env: + GH_TOKEN: ${{ steps.get-hoard-token.outputs.token }} + run: | + for attempt in 1 2 3; do + if gh pr merge "$PR_NUMBER" --repo airbytehq/airbyte --squash; then + echo "::notice::Force-merged PR #$PR_NUMBER: $PR_TITLE" + exit 0 + fi + echo "::warning::Merge attempt $attempt/3 failed, retrying in 60s..." + sleep 60 + done + echo "::error::Failed to force-merge PR #$PR_NUMBER after 3 attempts" + exit 1 + + - name: Dry-run notice + if: steps.eligible.outputs.result == 'true' && vars.ENABLE_CONNECTOR_AUTO_MERGE != 'true' + run: echo "::notice::DRY RUN — would force-merge PR #$PR_NUMBER" From a56b541f1fcee2b37a51ae5b2fc723492ffccded Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 15:42:57 -0700 Subject: [PATCH 314/379] fix(ci): use admin bot for approval and force-merge in finalize_rollout (#75937) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/finalize_rollout.yml | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/.github/workflows/finalize_rollout.yml b/.github/workflows/finalize_rollout.yml index 6eb2f7599f0d..7656644fa4e7 100644 --- a/.github/workflows/finalize_rollout.yml +++ b/.github/workflows/finalize_rollout.yml @@ -218,10 +218,33 @@ jobs: GH_TOKEN: ${{ steps.get-app-token.outputs.token }} run: gh pr ready "${{ steps.create-pr.outputs.pull-request-number }}" + # Use a different bot identity (admin) to approve and merge, + # because the bot that created the PR cannot approve its own PRs + # and needs admin privileges to bypass branch protection. + - name: Authenticate as GitHub App (Admin) + if: steps.create-pr.outputs.pull-request-number + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 + id: get-admin-token + with: + owner: "airbytehq" + repositories: "airbyte" + app-id: ${{ secrets.OCTAVIA_BOT_ADMIN_APP_ID }} + private-key: ${{ secrets.OCTAVIA_BOT_ADMIN_PRIVATE_KEY }} + + - name: Approve cleanup PR + if: steps.create-pr.outputs.pull-request-number + env: + GH_TOKEN: ${{ steps.get-admin-token.outputs.token }} + run: > + gh pr review "${{ steps.create-pr.outputs.pull-request-number }}" + --repo "${{ github.repository }}" + --approve + --body "Auto-approved by finalize_rollout workflow." + - name: Force-merge cleanup PR if: steps.create-pr.outputs.pull-request-number env: - GH_TOKEN: ${{ steps.get-app-token.outputs.token }} + GH_TOKEN: ${{ steps.get-admin-token.outputs.token }} run: | gh pr merge "${{ steps.create-pr.outputs.pull-request-number }}" \ --repo "${{ github.repository }}" \ From 6d40154a99058fea501f59040fa8bf97e07de6a0 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 15:56:13 -0700 Subject: [PATCH 315/379] fix(ci): replace second create-pull-request with git push to preserve version bump (#75938) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/finalize_rollout.yml | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/.github/workflows/finalize_rollout.yml b/.github/workflows/finalize_rollout.yml index 7656644fa4e7..9d5937322a9d 100644 --- a/.github/workflows/finalize_rollout.yml +++ b/.github/workflows/finalize_rollout.yml @@ -181,6 +181,12 @@ jobs: auto-merge/bypass-ci-checks draft: true + # Switch to the PR branch so changelog add reads the bumped + # GA version from metadata.yaml (not the RC version on master). + - name: "Checkout PR branch" + if: steps.create-pr.outputs.pull-request-number + run: git fetch origin "finalize-rollout/promote/${CONNECTOR_NAME}" && git checkout "finalize-rollout/promote/${CONNECTOR_NAME}" + # changelog add reads the current version from metadata.yaml # (already bumped to GA by the promote step above) and writes # a changelog entry — no version files are modified. @@ -194,21 +200,13 @@ jobs: --message "Promoted release candidate to GA" --pr-number "${{ steps.create-pr.outputs.pull-request-number }}" - # Second create-pull-request call pushes the changelog commit - # to the existing PR branch. + # Commit and push the changelog entry to the existing PR branch. - name: "Push changelog to PR" if: steps.create-pr.outputs.pull-request-number - uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 - with: - token: ${{ steps.get-app-token.outputs.token }} - commit-message: "chore: add changelog for ${{ env.CONNECTOR_NAME }}" - branch: "finalize-rollout/promote/${{ env.CONNECTOR_NAME }}" - base: ${{ github.event.repository.default_branch }} - title: "chore: finalize promote for ${{ env.CONNECTOR_NAME }}" - body: | - Automated cleanup after connector rollout **promote** for `${{ env.CONNECTOR_NAME }}`. - - Generated by [`finalize_rollout` workflow](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}). + run: | + git add docs/ + git commit -m "chore: add changelog for ${CONNECTOR_NAME}" + git push origin "finalize-rollout/promote/${CONNECTOR_NAME}" # The merge triggers the publish pipeline that # verifyDefaultVersionActivity is waiting for. From 001f33e062836a9b915644f432e2c1883f390645 Mon Sep 17 00:00:00 2001 From: "Aaron (\"AJ\") Steers" Date: Tue, 31 Mar 2026 15:59:08 -0700 Subject: [PATCH 316/379] ci: delete airbyte-ci/ directory, composite actions, and connectors_insights workflow (#75935) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/actions/install-airbyte-ci/action.yml | 118 - .github/actions/run-airbyte-ci/action.yml | 217 - .github/workflows/connectors_insights.yml | 57 - airbyte-ci/.gitignore | 172 - airbyte-ci/.python-version | 1 - airbyte-ci/README.md | 17 - airbyte-ci/connectors/README.md | 6 - airbyte-ci/connectors/auto_merge/README.md | 66 - airbyte-ci/connectors/auto_merge/poetry.lock | 765 --- .../connectors/auto_merge/pyproject.toml | 47 - .../auto_merge/src/auto_merge/__init__.py | 0 .../auto_merge/src/auto_merge/consts.py | 17 - .../auto_merge/src/auto_merge/env.py | 8 - .../auto_merge/src/auto_merge/helpers.py | 27 - .../auto_merge/src/auto_merge/main.py | 252 - .../src/auto_merge/pr_validators.py | 85 - .../connectors/ci_credentials/README.md | 129 - .../ci_credentials/ci_credentials/__init__.py | 6 - .../ci_credentials/google_api.py | 90 - .../ci_credentials/ci_credentials/logger.py | 85 - .../ci_credentials/ci_credentials/main.py | 69 - .../ci_credentials/ci_credentials/models.py | 57 - .../ci_credentials/secrets_manager.py | 302 -- .../connectors/ci_credentials/poetry.lock | 507 -- .../connectors/ci_credentials/pyproject.toml | 38 - .../ci_credentials/tests/__init__.py | 1 - .../ci_credentials/tests/test_models.py | 48 - .../tests/test_secrets_manager.py | 209 - airbyte-ci/connectors/connector_ops/README.md | 44 - .../connector_ops/connector_ops/__init__.py | 3 - .../connector_ops/connector_ops/utils.py | 793 --- .../connectors/connector_ops/poetry.lock | 1454 ----- .../connectors/connector_ops/pyproject.toml | 38 - .../connectors/connector_ops/pytest.ini | 4 - .../connector_ops/tests/conftest.py | 65 - .../tests/test_migration_files/bad-header.md | 9 - .../tests/test_migration_files/bad-title.md | 9 - .../test_migration_files/extra-header.md | 13 - .../test_migration_files/missing-entry.md | 5 - .../test_migration_files/out-of-order.md | 9 - .../connector_ops/tests/test_utils.py | 184 - .../connectors/connectors_insights/README.md | 97 - .../connectors_insights/poetry.lock | 2379 --------- .../connectors_insights/pyproject.toml | 48 - .../src/connectors_insights/__init__.py | 0 .../src/connectors_insights/cli.py | 123 - .../src/connectors_insights/hacks.py | 68 - .../src/connectors_insights/insights.py | 263 - .../src/connectors_insights/models.py | 43 - .../src/connectors_insights/pylint.py | 58 - .../cdk_deprecation_checkers.py | 77 - .../connectors_insights/result_backends.py | 87 - .../src/connectors_insights/utils.py | 92 - airbyte-ci/connectors/erd/README.md | 40 - airbyte-ci/connectors/erd/poetry.lock | 2369 --------- airbyte-ci/connectors/erd/pyproject.toml | 49 - airbyte-ci/connectors/erd/src/erd/__init__.py | 1 - .../connectors/erd/src/erd/dbml_assembler.py | 240 - .../connectors/erd/src/erd/erd_service.py | 151 - .../connectors/erd/src/erd/relationships.py | 79 - airbyte-ci/connectors/erd/tests/__init__.py | 1 - airbyte-ci/connectors/erd/tests/builder.py | 27 - .../erd/tests/test_dbml_assembler.py | 69 - .../erd/tests/test_relationships.py | 130 - airbyte-ci/connectors/live-tests/.gitignore | 1 - airbyte-ci/connectors/live-tests/README.md | 420 -- airbyte-ci/connectors/live-tests/poetry.lock | 4667 ----------------- .../connectors/live-tests/pyproject.toml | 75 - .../live-tests/src/live_tests/__init__.py | 2 - .../src/live_tests/commons/__init__.py | 1 - .../live_tests/commons/backends/__init__.py | 8 - .../commons/backends/base_backend.py | 16 - .../commons/backends/duckdb_backend.py | 80 - .../commons/backends/file_backend.py | 152 - .../commons/connection_objects_retrieval.py | 316 -- .../live_tests/commons/connector_runner.py | 220 - .../src/live_tests/commons/errors.py | 7 - .../live_tests/commons/evaluation_modes.py | 25 - .../src/live_tests/commons/hacks.py | 23 - .../live_tests/commons/json_schema_helper.py | 367 -- .../src/live_tests/commons/mitm_addons.py | 33 - .../src/live_tests/commons/models.py | 543 -- .../src/live_tests/commons/proxy.py | 184 - .../src/live_tests/commons/secret_access.py | 39 - .../live_tests/commons/segment_tracking.py | 45 - .../src/live_tests/commons/utils.py | 192 - .../live-tests/src/live_tests/conftest.py | 646 --- .../live-tests/src/live_tests/consts.py | 4 - .../live-tests/src/live_tests/pytest.ini | 9 - .../live_tests/regression_tests/__init__.py | 1 - .../regression_tests/llm_evaluation/README.md | 37 - .../llm_evaluation/__init__.py | 1 - .../llm_evaluation/evaluate_report.py | 299 -- .../live_tests/regression_tests/test_check.py | 50 - .../regression_tests/test_discover.py | 104 - .../live_tests/regression_tests/test_read.py | 551 -- .../live_tests/regression_tests/test_spec.py | 42 - .../live-tests/src/live_tests/report.py | 411 -- .../live-tests/src/live_tests/stash_keys.py | 39 - .../src/live_tests/templates/__init__.py | 0 .../templates/private_details.html.j2 | 305 -- .../src/live_tests/templates/report.html.j2 | 515 -- .../live-tests/src/live_tests/utils.py | 162 - .../live_tests/validation_tests/__init__.py | 0 .../live_tests/validation_tests/test_check.py | 45 - .../validation_tests/test_discover.py | 172 - .../live_tests/validation_tests/test_read.py | 143 - .../live_tests/validation_tests/test_spec.py | 514 -- .../connectors/live-tests/tests/__init__.py | 1 - .../live-tests/tests/backends/__init__.py | 0 .../tests/backends/test_file_backend.py | 71 - .../test_get_connection_objects_retrieval.py | 702 --- .../tests/test_json_schema_helper.py | 480 -- .../connectors/metadata_service/README.md | 15 - .../docs/external_documentation_urls.md | 554 -- .../connectors/metadata_service/lib/README.md | 91 - .../lib/bin/bundle-schemas.js | 48 - .../lib/bin/generate-metadata-models.sh | 36 - .../lib/metadata_service/commands.py | 252 - .../lib/metadata_service/constants.py | 65 - .../lib/metadata_service/docker_hub.py | 137 - .../lib/metadata_service/gcs_upload.py | 679 --- .../lib/metadata_service/helpers/files.py | 36 - .../lib/metadata_service/helpers/gcs.py | 36 - .../helpers/object_helpers.py | 47 - .../lib/metadata_service/helpers/slack.py | 55 - .../ActorDefinitionResourceRequirements.py | 54 - .../models/generated/AirbyteInternal.py | 22 - .../models/generated/AllowedHosts.py | 18 - .../generated/ConnectorBreakingChanges.py | 65 - .../models/generated/ConnectorBuildOptions.py | 15 - .../models/generated/ConnectorIPCOptions.py | 25 - .../ConnectorMetadataDefinitionV0.json | 897 ---- .../ConnectorMetadataDefinitionV0.py | 479 -- .../models/generated/ConnectorMetrics.py | 24 - .../models/generated/ConnectorPackageInfo.py | 12 - .../ConnectorRegistryDestinationDefinition.py | 407 -- .../generated/ConnectorRegistryReleases.py | 406 -- .../ConnectorRegistrySourceDefinition.py | 407 -- .../models/generated/ConnectorRegistryV0.py | 413 -- .../models/generated/ConnectorReleases.py | 98 - .../generated/ConnectorTestSuiteOptions.py | 58 - .../models/generated/GeneratedFields.py | 62 - .../models/generated/GitInfo.py | 31 - .../models/generated/JobType.py | 23 - ...ormalizationDestinationDefinitionConfig.py | 24 - .../models/generated/RegistryOverrides.py | 111 - .../models/generated/ReleaseStage.py | 15 - .../models/generated/RemoteRegistries.py | 23 - .../models/generated/ResourceRequirements.py | 18 - .../models/generated/RolloutConfiguration.py | 29 - .../models/generated/Secret.py | 34 - .../models/generated/SecretStore.py | 22 - .../models/generated/SourceFileInfo.py | 16 - .../models/generated/SuggestedStreams.py | 18 - .../models/generated/SupportLevel.py | 15 - .../models/generated/TestConnections.py | 14 - .../models/generated/__init__.py | 31 - .../ActorDefinitionResourceRequirements.yaml | 30 - .../models/src/AirbyteInternal.yaml | 32 - .../models/src/AllowedHosts.yaml | 13 - .../models/src/ConnectorBreakingChanges.yaml | 65 - .../models/src/ConnectorBuildOptions.yaml | 10 - .../models/src/ConnectorIPCOptions.yaml | 29 - .../src/ConnectorMetadataDefinitionV0.yaml | 173 - .../models/src/ConnectorMetrics.yaml | 30 - .../models/src/ConnectorPackageInfo.yaml | 9 - ...onnectorRegistryDestinationDefinition.yaml | 90 - .../models/src/ConnectorRegistryReleases.yaml | 35 - .../ConnectorRegistrySourceDefinition.yaml | 92 - .../models/src/ConnectorRegistryV0.yaml | 18 - .../models/src/ConnectorReleases.yaml | 16 - .../models/src/ConnectorTestSuiteOptions.yaml | 28 - .../models/src/GeneratedFields.yaml | 16 - .../metadata_service/models/src/GitInfo.yaml | 21 - .../metadata_service/models/src/JobType.yaml | 14 - ...malizationDestinationDefinitionConfig.yaml | 21 - .../models/src/RegistryOverrides.yaml | 38 - .../models/src/ReleaseStage.yaml | 11 - .../models/src/RemoteRegistries.yaml | 25 - .../models/src/ResourceRequirements.yaml | 16 - .../models/src/RolloutConfiguration.yaml | 29 - .../metadata_service/models/src/Secret.yaml | 19 - .../models/src/SecretStore.yaml | 16 - .../models/src/SourceFileInfo.yaml | 17 - .../models/src/SuggestedStreams.yaml | 13 - .../models/src/SupportLevel.yaml | 10 - .../models/src/TestConnections.yaml | 17 - .../lib/metadata_service/models/transform.py | 71 - .../lib/metadata_service/registry.py | 367 -- .../lib/metadata_service/registry_entry.py | 572 -- .../lib/metadata_service/registry_report.py | 353 -- .../lib/metadata_service/sentry.py | 49 - .../lib/metadata_service/spec_cache.py | 120 - .../metadata_service/specs_secrets_mask.py | 100 - .../metadata_service/stale_metadata_report.py | 262 - .../lib/metadata_service/templates/base.html | 74 - .../connector_registry_locations.html | 16 - .../lib/metadata_service/templates/render.py | 101 - .../validators/metadata_validator.py | 335 -- .../metadata_service/lib/package-lock.json | 62 - .../metadata_service/lib/package.json | 12 - .../metadata_service/lib/poetry.lock | 2294 -------- .../metadata_service/lib/pyproject.toml | 56 - .../metadata_service/lib/tests/conftest.py | 25 - .../lib/tests/fixtures/__init__.py | 58 - .../lib/tests/fixtures/doc.md | 1 - .../metadata_cloud_repo_does_not_exist.yaml | 27 - .../metadata_main_repo_does_not_exist.yaml | 23 - ...ata_normalization_repo_does_not_exist.yaml | 27 - .../metadata_oss_repo_does_not_exist.yaml | 27 - ...aking_change_image_tag_does_not_exist.yaml | 25 - ...tadata_cloud_image_tag_does_not_exist.yaml | 27 - ...etadata_main_image_tag_does_not_exist.yaml | 23 - ...ormalization_image_tag_does_not_exist.yaml | 27 - .../metadata_oss_repo_does_not_exist.yaml | 27 - ...ge_tag_does_not_exist_but_is_overrode.yaml | 27 - ...n_repo_does_not_exist_but_is_overrode.yaml | 27 - .../metadata_all_images_exist.yaml | 32 - ...etadata_all_images_exist_no_overrides.yaml | 14 - ...exist_no_overrides_with_normalization.yaml | 18 - .../metadata_base_image_exists.yaml | 29 - .../metadata_release_candidate.yaml | 24 - .../invalid/metadata_extra_data.yaml | 15 - ...tadata_major_bump_no_breaking_changes.yaml | 14 - ...data_progressive_rollout_no_rc_suffix.yaml | 22 - ...a_release_candidate_for_major_version.yaml | 22 - ...ease_candidate_no_progressive_rollout.yaml | 20 - .../metadata_validate/invalid/nonsense.json | 1 - .../metadata_validate/invalid/nonsense.yaml | 1 - ...ata_base_image_digest_does_not_exists.yaml | 29 - ...adata_base_image_name_does_not_exists.yaml | 29 - ...tadata_base_image_tag_does_not_exists.yaml | 29 - .../metadata_build_base_image_wrong_type.yaml | 29 - .../metadata_invalid_base_image_no_sha.yml | 29 - .../metadata_invalid_internal_fields.yaml | 17 - .../metadata_invalid_remote_registries.yaml | 16 - .../metadata_invalid_support_refreshes.yaml | 15 - .../metadata_unknown_support_level.yaml | 15 - ...data_wrong_language_remote_registries.yaml | 18 - .../metadata_registry_no_id_override.yaml | 22 - .../metadata_registry_no_type_override.yaml | 22 - .../metadata_registry_unknown_override.yaml | 22 - ...reaking_changes_empty_impacted_stream.yaml | 23 - ...nges_impact_scopes_unknown_scope_type.yaml | 23 - ...reaking_change_versions_under_releases.yml | 18 - ...ta_breaking_changes_not_under_releases.yml | 18 - ...d_breaking_change_additional_property.yaml | 20 - ...alid_breaking_change_invalid_deadline.yaml | 19 - ...a_invalid_breaking_change_no_deadline.yaml | 18 - ...ta_invalid_breaking_change_no_message.yaml | 18 - ...adata_invalid_breaking_change_version.yaml | 19 - ..._no_breaking_change_entry_for_version.yaml | 25 - .../metadata_major_version_no_releases.yaml | 20 - .../tags_invalid/metadata_empty_tags.yaml | 13 - .../metadata_invalid_tag_format.yaml | 14 - .../tags_invalid/metadata_no_lang_tag.yaml | 14 - .../metadata_missing_connector_type.yaml | 13 - .../metadata_missing_definition_id.yaml | 17 - .../metadata_missing_docker_image_tag.yaml | 17 - .../metadata_missing_docker_repo.yaml | 17 - .../metadata_missing_tags.yaml | 12 - .../metadata_missing_version.yaml | 17 - ...anifest_major_bump_no_breaking_change.yaml | 14 - .../valid/metadata_simple.yaml | 14 - .../metadata_build_base_image.yaml | 29 - .../metadata_internal_fields.yaml | 17 - .../metadata_registry_allowed_hosts.yaml | 18 - .../metadata_registry_required_resources.yaml | 20 - .../metadata_remote_registries.yaml | 18 - .../metadata_support_level.yaml | 15 - .../metadata_support_level_archived.yaml | 15 - .../metadata_support_refreshes.yaml | 15 - .../metadata_registry_complex_override.yaml | 31 - .../metadata_registry_enabled.yaml | 21 - .../metadata_breaking_change_prerelease.yaml | 19 - .../metadata_breaking_changes.yaml | 19 - ...a_breaking_changes_with_impact_scopes.yaml | 22 - ...eaking_changes_with_migration_doc_url.yaml | 21 - ...g_changes_with_multipel_impact_scopes.yaml | 24 - ...sion_with_breaking_change_for_version.yaml | 19 - ...candidate_disable_progressive_rollout.yaml | 22 - ..._candidate_enable_progressive_rollout.yaml | 22 - .../stale_metadata_report_fixtures.py | 128 - .../lib/tests/helpers/test_slack.py | 86 - .../lib/tests/test_commands.py | 267 - .../lib/tests/test_docker_hub.py | 33 - .../lib/tests/test_gcs_upload.py | 868 --- .../lib/tests/test_registry.py | 328 -- .../lib/tests/test_registry_entry.py | 550 -- .../lib/tests/test_spec_cache.py | 102 - .../lib/tests/test_specs_secrets_mask.py | 311 -- .../lib/tests/test_stale_metadata_report.py | 238 - .../lib/tests/test_transform.py | 89 - .../lib/tests/test_validators/__init__.py | 0 .../test_metadata_validators.py | 158 - airbyte-ci/connectors/pipelines/.gitignore | 2 - .../connectors/pipelines/CONTRIBUTING.md | 366 -- airbyte-ci/connectors/pipelines/README.md | 1249 ----- .../pipelines/pipelines/__init__.py | 30 - .../pipelines/airbyte_ci/__init__.py | 3 - .../airbyte_ci/connectors/__init__.py | 3 - .../connectors/build_image/__init__.py | 3 - .../connectors/build_image/commands.py | 85 - .../connectors/build_image/pipeline.py | 3 - .../connectors/build_image/steps/__init__.py | 57 - .../build_image/steps/build_customization.py | 104 - .../connectors/build_image/steps/common.py | 147 - .../build_image/steps/java_connectors.py | 69 - .../steps/manifest_only_connectors.py | 71 - .../build_image/steps/normalization.py | 40 - .../build_image/steps/python_connectors.py | 113 - .../connectors/bump_version/__init__.py | 3 - .../connectors/bump_version/commands.py | 93 - .../connectors/bump_version/pipeline.py | 109 - .../airbyte_ci/connectors/commands.py | 275 - .../pipelines/airbyte_ci/connectors/consts.py | 42 - .../airbyte_ci/connectors/context.py | 273 - .../connectors/generate_erd/__init__.py | 1 - .../connectors/generate_erd/commands.py | 57 - .../connectors/generate_erd/pipeline.py | 169 - .../airbyte_ci/connectors/list/__init__.py | 3 - .../airbyte_ci/connectors/list/commands.py | 56 - .../migrate_to_inline_schemas/__init__.py | 3 - .../migrate_to_inline_schemas/commands.py | 33 - .../migrate_to_inline_schemas/pipeline.py | 437 -- .../migrate_to_manifest_only/__init__.py | 0 .../migrate_to_manifest_only/commands.py | 46 - .../declarative_component_schema.py | 1598 ------ .../manifest_component_transformer.py | 268 - .../manifest_resolver.py | 204 - .../migrate_to_manifest_only/pipeline.py | 324 -- .../templates/README.md.j2 | 65 - .../migrate_to_manifest_only/utils.py | 88 - .../airbyte_ci/connectors/pipeline.py | 126 - .../airbyte_ci/connectors/publish/__init__.py | 3 - .../airbyte_ci/connectors/publish/commands.py | 212 - .../airbyte_ci/connectors/publish/context.py | 164 - .../airbyte_ci/connectors/publish/pipeline.py | 819 --- .../connectors/pull_request/__init__.py | 3 - .../connectors/pull_request/commands.py | 82 - .../connectors/pull_request/pipeline.py | 108 - .../airbyte_ci/connectors/reports.py | 195 - .../airbyte_ci/connectors/test/__init__.py | 3 - .../airbyte_ci/connectors/test/commands.py | 200 - .../airbyte_ci/connectors/test/context.py | 198 - .../airbyte_ci/connectors/test/pipeline.py | 77 - .../connectors/test/steps/__init__.py | 3 - .../connectors/test/steps/common.py | 838 --- .../connectors/test/steps/java_connectors.py | 142 - .../test/steps/manifest_only_connectors.py | 172 - .../test/steps/python_connectors.py | 326 -- .../test/steps/templates/test_report.html.j2 | 201 - .../connectors/up_to_date/__init__.py | 3 - .../connectors/up_to_date/commands.py | 76 - .../connectors/up_to_date/pipeline.py | 204 - .../airbyte_ci/connectors/up_to_date/steps.py | 173 - .../templates/up_to_date_pr_body.md.j2 | 32 - .../connectors/upgrade_cdk/__init__.py | 3 - .../connectors/upgrade_cdk/commands.py | 57 - .../connectors/upgrade_cdk/pipeline.py | 177 - .../pipelines/airbyte_ci/metadata/__init__.py | 3 - .../pipelines/airbyte_ci/metadata/commands.py | 16 - .../pipelines/airbyte_ci/metadata/pipeline.py | 160 - .../pipelines/airbyte_ci/poetry/__init__.py | 3 - .../pipelines/airbyte_ci/poetry/commands.py | 36 - .../airbyte_ci/poetry/publish/__init__.py | 3 - .../airbyte_ci/poetry/publish/commands.py | 114 - .../pipelines/airbyte_ci/steps/__init__.py | 3 - .../pipelines/airbyte_ci/steps/base_image.py | 158 - .../airbyte_ci/steps/bump_version.py | 151 - .../pipelines/airbyte_ci/steps/changelog.py | 70 - .../pipelines/airbyte_ci/steps/docker.py | 112 - .../pipelines/airbyte_ci/steps/gradle.py | 323 -- .../pipelines/airbyte_ci/steps/no_op.py | 22 - .../pipelines/airbyte_ci/steps/poetry.py | 37 - .../airbyte_ci/steps/pull_request.py | 61 - .../airbyte_ci/steps/python_registry.py | 171 - .../pipelines/airbyte_ci/test/__init__.py | 19 - .../pipelines/airbyte_ci/test/commands.py | 131 - .../pipelines/airbyte_ci/test/models.py | 38 - .../pipelines/airbyte_ci/test/pipeline.py | 355 -- .../pipelines/airbyte_ci/update/__init__.py | 3 - .../pipelines/airbyte_ci/update/commands.py | 24 - .../pipelines/pipelines/cli/airbyte_ci.py | 218 - .../pipelines/pipelines/cli/auto_update.py | 145 - .../pipelines/cli/click_decorators.py | 153 - .../pipelines/pipelines/cli/confirm_prompt.py | 33 - .../pipelines/cli/dagger_pipeline_command.py | 108 - .../pipelines/pipelines/cli/dagger_run.py | 127 - .../pipelines/cli/ensure_repo_root.py | 59 - .../pipelines/pipelines/cli/lazy_group.py | 46 - .../pipelines/pipelines/cli/secrets.py | 41 - .../pipelines/pipelines/cli/telemetry.py | 74 - .../connectors/pipelines/pipelines/consts.py | 101 - .../pipelines/pipelines/dagger/__init__.py | 3 - .../pipelines/dagger/actions/__init__.py | 3 - .../dagger/actions/connector/__init__.py | 3 - .../dagger/actions/connector/hooks.py | 69 - .../dagger/actions/connector/normalization.py | 78 - .../dagger/actions/python/__init__.py | 3 - .../pipelines/dagger/actions/python/common.py | 350 -- .../pipelines/dagger/actions/python/pipx.py | 54 - .../pipelines/dagger/actions/python/poetry.py | 93 - .../dagger/actions/remote_storage.py | 90 - .../pipelines/dagger/actions/secrets.py | 83 - .../dagger/actions/system/__init__.py | 3 - .../pipelines/dagger/actions/system/common.py | 21 - .../pipelines/dagger/actions/system/docker.py | 248 - .../pipelines/dagger/containers/__init__.py | 3 - .../pipelines/dagger/containers/git.py | 53 - .../dagger/containers/internal_tools.py | 40 - .../pipelines/dagger/containers/java.py | 193 - .../pipelines/dagger/containers/python.py | 92 - .../pipelines/external_scripts/__init__.py | 1 - .../external_scripts/airbyte_ci_check.sh | 55 - .../external_scripts/airbyte_ci_clean.sh | 43 - .../airbyte_ci_dev_install.py | 51 - .../external_scripts/airbyte_ci_install.py | 138 - .../connectors/pipelines/pipelines/hacks.py | 145 - .../pipelines/pipelines/helpers/__init__.py | 3 - .../pipelines/pipelines/helpers/cache_keys.py | 13 - .../pipelines/pipelines/helpers/changelog.py | 126 - .../pipelines/pipelines/helpers/cli.py | 101 - .../pipelines/helpers/connectors/__init__.py | 3 - .../helpers/connectors/cdk_helpers.py | 26 - .../pipelines/helpers/connectors/command.py | 97 - .../pipelines/helpers/connectors/dagger_fs.py | 41 - .../pipelines/helpers/connectors/format.py | 35 - .../pipelines/helpers/connectors/modifed.py | 89 - .../pipelines/helpers/connectors/yaml.py | 43 - .../pipelines/helpers/execution/__init__.py | 0 .../helpers/execution/argument_parsing.py | 66 - .../pipelines/helpers/execution/run_steps.py | 345 -- .../pipelines/pipelines/helpers/gcs.py | 50 - .../pipelines/pipelines/helpers/git.py | 129 - .../pipelines/pipelines/helpers/github.py | 237 - .../pipelines/pipelines/helpers/pip.py | 21 - .../pipelines/helpers/sentry_utils.py | 92 - .../pipelines/pipelines/helpers/slack.py | 29 - .../pipelines/pipelines/helpers/utils.py | 409 -- .../pipelines/pipelines/models/__init__.py | 3 - .../pipelines/pipelines/models/artifacts.py | 49 - .../pipelines/models/ci_requirements.py | 27 - .../pipelines/models/contexts/__init__.py | 3 - .../models/contexts/click_pipeline_context.py | 122 - .../models/contexts/pipeline_context.py | 351 -- .../contexts/python_registry_publish.py | 116 - .../pipelines/pipelines/models/reports.py | 212 - .../pipelines/pipelines/models/secrets.py | 140 - .../pipelines/pipelines/models/singleton.py | 26 - .../pipelines/pipelines/models/steps.py | 439 -- airbyte-ci/connectors/pipelines/poetry.lock | 3324 ------------ .../pyinstaller_hooks/hook-certifi.py | 6 - .../connectors/pipelines/pyproject.toml | 82 - airbyte-ci/connectors/pipelines/pytest.ini | 5 - airbyte-ci/connectors/pipelines/ruff.toml | 15 - .../connectors/pipelines/tests/__init__.py | 3 - .../connectors/pipelines/tests/conftest.py | 84 - .../tests/test_actions/test_environments.py | 69 - .../connectors/pipelines/tests/test_bases.py | 111 - .../tests/test_build_image/__init__.py | 3 - .../dummy_build_customization.py | 36 - .../test_manifest_only_connectors.py | 122 - .../test_python_connectors.py | 180 - .../test_steps/test_common.py | 131 - .../pipelines/tests/test_changelog.py | 110 - .../changelog_header_no_newline.md | 11 - .../changelog_header_no_separator.md | 11 - .../initial_files/no_changelog_header.md | 11 - .../initial_files/valid_changelog_at_end.md | 12 - .../valid_changelog_in_middle.md | 14 - .../changelog_header_no_newline.md | 1 - .../changelog_header_no_separator.md | 1 - ...ate_version_date_valid_changelog_at_end.md | 14 - ..._version_date_valid_changelog_in_middle.md | 16 - ...upicate_versions_valid_changelog_at_end.md | 14 - ...cate_versions_valid_changelog_in_middle.md | 16 - .../duplicate_entry_valid_changelog_at_end.md | 13 - ...plicate_entry_valid_changelog_in_middle.md | 15 - ...existing_entries_valid_changelog_at_end.md | 12 - ...sting_entries_valid_changelog_in_middle.md | 14 - .../result_files/no_changelog_header.md | 1 - .../single_insert_valid_changelog_at_end.md | 13 - ...single_insert_valid_changelog_in_middle.md | 15 - .../pipelines/tests/test_cli/__init__.py | 3 - .../tests/test_cli/test_click_decorators.py | 85 - .../pipelines/tests/test_commands/__init__.py | 3 - .../test_commands/test_groups/__init__.py | 3 - .../test_groups/test_connectors.py | 346 -- .../pipelines/tests/test_dagger/__init__.py | 3 - .../test_dagger/test_actions/__init__.py | 3 - .../test_actions/test_python/__init__.py | 3 - .../test_actions/test_python/test_common.py | 63 - .../connectors/pipelines/tests/test_gradle.py | 43 - .../pipelines/tests/test_helpers/__init__.py | 3 - .../test_helpers/test_execution/__init__.py | 0 .../test_execution/test_argument_parsing.py | 37 - .../test_execution/test_run_steps.py | 439 -- .../pipelines/tests/test_helpers/test_pip.py | 24 - .../tests/test_helpers/test_utils.py | 287 - .../pipelines/tests/test_models/__init__.py | 3 - .../test_click_pipeline_context.py | 68 - .../tests/test_models/test_singleton.py | 31 - .../tests/test_poetry/test_poetry_publish.py | 95 - .../pipelines/tests/test_publish.py | 431 -- .../pipelines/tests/test_steps/__init__.py | 3 - .../test_steps/test_simple_docker_step.py | 103 - .../tests/test_steps/test_version_check.py | 164 - .../pipelines/tests/test_tests/__init__.py | 3 - .../pipelines/tests/test_tests/test_common.py | 265 - .../tests/test_tests/test_context.py | 70 - .../test_tests/test_python_connectors.py | 183 - .../pipelines/tests/test_upgrade_java_cdk.py | 136 - .../connectors/pipelines/tests/utils.py | 68 - 515 files changed, 68772 deletions(-) delete mode 100644 .github/actions/install-airbyte-ci/action.yml delete mode 100644 .github/actions/run-airbyte-ci/action.yml delete mode 100644 .github/workflows/connectors_insights.yml delete mode 100644 airbyte-ci/.gitignore delete mode 100644 airbyte-ci/.python-version delete mode 100644 airbyte-ci/README.md delete mode 100644 airbyte-ci/connectors/README.md delete mode 100644 airbyte-ci/connectors/auto_merge/README.md delete mode 100644 airbyte-ci/connectors/auto_merge/poetry.lock delete mode 100644 airbyte-ci/connectors/auto_merge/pyproject.toml delete mode 100644 airbyte-ci/connectors/auto_merge/src/auto_merge/__init__.py delete mode 100644 airbyte-ci/connectors/auto_merge/src/auto_merge/consts.py delete mode 100644 airbyte-ci/connectors/auto_merge/src/auto_merge/env.py delete mode 100644 airbyte-ci/connectors/auto_merge/src/auto_merge/helpers.py delete mode 100644 airbyte-ci/connectors/auto_merge/src/auto_merge/main.py delete mode 100644 airbyte-ci/connectors/auto_merge/src/auto_merge/pr_validators.py delete mode 100644 airbyte-ci/connectors/ci_credentials/README.md delete mode 100644 airbyte-ci/connectors/ci_credentials/ci_credentials/__init__.py delete mode 100644 airbyte-ci/connectors/ci_credentials/ci_credentials/google_api.py delete mode 100644 airbyte-ci/connectors/ci_credentials/ci_credentials/logger.py delete mode 100644 airbyte-ci/connectors/ci_credentials/ci_credentials/main.py delete mode 100644 airbyte-ci/connectors/ci_credentials/ci_credentials/models.py delete mode 100644 airbyte-ci/connectors/ci_credentials/ci_credentials/secrets_manager.py delete mode 100644 airbyte-ci/connectors/ci_credentials/poetry.lock delete mode 100644 airbyte-ci/connectors/ci_credentials/pyproject.toml delete mode 100644 airbyte-ci/connectors/ci_credentials/tests/__init__.py delete mode 100644 airbyte-ci/connectors/ci_credentials/tests/test_models.py delete mode 100644 airbyte-ci/connectors/ci_credentials/tests/test_secrets_manager.py delete mode 100644 airbyte-ci/connectors/connector_ops/README.md delete mode 100644 airbyte-ci/connectors/connector_ops/connector_ops/__init__.py delete mode 100644 airbyte-ci/connectors/connector_ops/connector_ops/utils.py delete mode 100644 airbyte-ci/connectors/connector_ops/poetry.lock delete mode 100644 airbyte-ci/connectors/connector_ops/pyproject.toml delete mode 100644 airbyte-ci/connectors/connector_ops/pytest.ini delete mode 100644 airbyte-ci/connectors/connector_ops/tests/conftest.py delete mode 100644 airbyte-ci/connectors/connector_ops/tests/test_migration_files/bad-header.md delete mode 100644 airbyte-ci/connectors/connector_ops/tests/test_migration_files/bad-title.md delete mode 100644 airbyte-ci/connectors/connector_ops/tests/test_migration_files/extra-header.md delete mode 100644 airbyte-ci/connectors/connector_ops/tests/test_migration_files/missing-entry.md delete mode 100644 airbyte-ci/connectors/connector_ops/tests/test_migration_files/out-of-order.md delete mode 100644 airbyte-ci/connectors/connector_ops/tests/test_utils.py delete mode 100644 airbyte-ci/connectors/connectors_insights/README.md delete mode 100644 airbyte-ci/connectors/connectors_insights/poetry.lock delete mode 100644 airbyte-ci/connectors/connectors_insights/pyproject.toml delete mode 100644 airbyte-ci/connectors/connectors_insights/src/connectors_insights/__init__.py delete mode 100644 airbyte-ci/connectors/connectors_insights/src/connectors_insights/cli.py delete mode 100644 airbyte-ci/connectors/connectors_insights/src/connectors_insights/hacks.py delete mode 100644 airbyte-ci/connectors/connectors_insights/src/connectors_insights/insights.py delete mode 100644 airbyte-ci/connectors/connectors_insights/src/connectors_insights/models.py delete mode 100644 airbyte-ci/connectors/connectors_insights/src/connectors_insights/pylint.py delete mode 100644 airbyte-ci/connectors/connectors_insights/src/connectors_insights/pylint_plugins/cdk_deprecation_checkers.py delete mode 100644 airbyte-ci/connectors/connectors_insights/src/connectors_insights/result_backends.py delete mode 100644 airbyte-ci/connectors/connectors_insights/src/connectors_insights/utils.py delete mode 100644 airbyte-ci/connectors/erd/README.md delete mode 100644 airbyte-ci/connectors/erd/poetry.lock delete mode 100644 airbyte-ci/connectors/erd/pyproject.toml delete mode 100644 airbyte-ci/connectors/erd/src/erd/__init__.py delete mode 100644 airbyte-ci/connectors/erd/src/erd/dbml_assembler.py delete mode 100644 airbyte-ci/connectors/erd/src/erd/erd_service.py delete mode 100644 airbyte-ci/connectors/erd/src/erd/relationships.py delete mode 100644 airbyte-ci/connectors/erd/tests/__init__.py delete mode 100644 airbyte-ci/connectors/erd/tests/builder.py delete mode 100644 airbyte-ci/connectors/erd/tests/test_dbml_assembler.py delete mode 100644 airbyte-ci/connectors/erd/tests/test_relationships.py delete mode 100644 airbyte-ci/connectors/live-tests/.gitignore delete mode 100644 airbyte-ci/connectors/live-tests/README.md delete mode 100644 airbyte-ci/connectors/live-tests/poetry.lock delete mode 100644 airbyte-ci/connectors/live-tests/pyproject.toml delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/__init__.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/__init__.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/__init__.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/base_backend.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/duckdb_backend.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/file_backend.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/connection_objects_retrieval.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/connector_runner.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/errors.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/evaluation_modes.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/hacks.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/json_schema_helper.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/mitm_addons.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/models.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/proxy.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/secret_access.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/segment_tracking.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/commons/utils.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/conftest.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/consts.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/pytest.ini delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/__init__.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/llm_evaluation/README.md delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/llm_evaluation/__init__.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/llm_evaluation/evaluate_report.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_check.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_discover.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_read.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_spec.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/report.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/stash_keys.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/templates/__init__.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/templates/private_details.html.j2 delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/templates/report.html.j2 delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/utils.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/__init__.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_check.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_discover.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_read.py delete mode 100644 airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_spec.py delete mode 100644 airbyte-ci/connectors/live-tests/tests/__init__.py delete mode 100644 airbyte-ci/connectors/live-tests/tests/backends/__init__.py delete mode 100644 airbyte-ci/connectors/live-tests/tests/backends/test_file_backend.py delete mode 100644 airbyte-ci/connectors/live-tests/tests/test_get_connection_objects_retrieval.py delete mode 100644 airbyte-ci/connectors/live-tests/tests/test_json_schema_helper.py delete mode 100644 airbyte-ci/connectors/metadata_service/README.md delete mode 100644 airbyte-ci/connectors/metadata_service/docs/external_documentation_urls.md delete mode 100644 airbyte-ci/connectors/metadata_service/lib/README.md delete mode 100755 airbyte-ci/connectors/metadata_service/lib/bin/bundle-schemas.js delete mode 100755 airbyte-ci/connectors/metadata_service/lib/bin/generate-metadata-models.sh delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/commands.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/constants.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/docker_hub.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/gcs_upload.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/files.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/gcs.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/object_helpers.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/slack.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ActorDefinitionResourceRequirements.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/AirbyteInternal.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/AllowedHosts.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorBreakingChanges.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorBuildOptions.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorIPCOptions.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorMetadataDefinitionV0.json delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorMetadataDefinitionV0.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorMetrics.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorPackageInfo.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistryDestinationDefinition.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistryReleases.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistrySourceDefinition.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistryV0.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorReleases.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorTestSuiteOptions.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/GeneratedFields.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/GitInfo.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/JobType.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/NormalizationDestinationDefinitionConfig.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/RegistryOverrides.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ReleaseStage.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/RemoteRegistries.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ResourceRequirements.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/RolloutConfiguration.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/Secret.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SecretStore.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SourceFileInfo.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SuggestedStreams.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SupportLevel.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/TestConnections.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/__init__.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ActorDefinitionResourceRequirements.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/AirbyteInternal.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/AllowedHosts.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorBreakingChanges.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorBuildOptions.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorIPCOptions.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorMetadataDefinitionV0.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorMetrics.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorPackageInfo.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistryDestinationDefinition.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistryReleases.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistrySourceDefinition.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistryV0.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorReleases.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorTestSuiteOptions.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/GeneratedFields.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/GitInfo.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/JobType.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/NormalizationDestinationDefinitionConfig.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/RegistryOverrides.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ReleaseStage.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/RemoteRegistries.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ResourceRequirements.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/RolloutConfiguration.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/Secret.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SecretStore.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SourceFileInfo.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SuggestedStreams.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SupportLevel.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/TestConnections.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/models/transform.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/registry.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/registry_entry.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/registry_report.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/sentry.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/spec_cache.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/specs_secrets_mask.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/stale_metadata_report.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/templates/base.html delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/templates/connector_registry_locations.html delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/templates/render.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/metadata_service/validators/metadata_validator.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/package-lock.json delete mode 100644 airbyte-ci/connectors/metadata_service/lib/package.json delete mode 100644 airbyte-ci/connectors/metadata_service/lib/poetry.lock delete mode 100644 airbyte-ci/connectors/metadata_service/lib/pyproject.toml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/conftest.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/__init__.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/doc.md delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_cloud_repo_does_not_exist.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_main_repo_does_not_exist.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_normalization_repo_does_not_exist.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_oss_repo_does_not_exist.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_breaking_change_image_tag_does_not_exist.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_cloud_image_tag_does_not_exist.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_main_image_tag_does_not_exist.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_normalization_image_tag_does_not_exist.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_oss_repo_does_not_exist.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/valid_overrides_but_image_nonexistent/metadata_main_image_tag_does_not_exist_but_is_overrode.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/valid_overrides_but_image_nonexistent/metadata_main_repo_does_not_exist_but_is_overrode.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_all_images_exist.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_all_images_exist_no_overrides.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_all_images_exist_no_overrides_with_normalization.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_base_image_exists.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_release_candidate.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_extra_data.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_major_bump_no_breaking_changes.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_progressive_rollout_no_rc_suffix.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_release_candidate_for_major_version.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_release_candidate_no_progressive_rollout.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/nonsense.json delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/nonsense.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_base_image_digest_does_not_exists.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_base_image_name_does_not_exists.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_base_image_tag_does_not_exists.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_build_base_image_wrong_type.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_invalid_base_image_no_sha.yml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_invalid_internal_fields.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_invalid_remote_registries.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_invalid_support_refreshes.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_unknown_support_level.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_wrong_language_remote_registries.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/overrides_invalid/metadata_registry_no_id_override.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/overrides_invalid/metadata_registry_no_type_override.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/overrides_invalid/metadata_registry_unknown_override.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/impact_scopes_invalid/metadata_breaking_changes_empty_impacted_stream.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/impact_scopes_invalid/metadata_breaking_changes_impact_scopes_unknown_scope_type.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_breaking_change_versions_under_releases.yml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_breaking_changes_not_under_releases.yml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_additional_property.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_invalid_deadline.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_no_deadline.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_no_message.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_version.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_major_version_no_breaking_change_entry_for_version.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_major_version_no_releases.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_invalid/tags_invalid/metadata_empty_tags.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_invalid/tags_invalid/metadata_invalid_tag_format.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_invalid/tags_invalid/metadata_no_lang_tag.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_connector_type.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_definition_id.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_docker_image_tag.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_docker_repo.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_tags.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_version.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/metadata_declarative_manifest_major_bump_no_breaking_change.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/metadata_simple.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_build_base_image.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_internal_fields.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_registry_allowed_hosts.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_registry_required_resources.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_remote_registries.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_support_level.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_support_level_archived.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_support_refreshes.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_overrides/metadata_registry_complex_override.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_overrides/metadata_registry_enabled.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_change_prerelease.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes_with_impact_scopes.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes_with_migration_doc_url.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes_with_multipel_impact_scopes.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_major_version_with_breaking_change_for_version.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_release_candidate_disable_progressive_rollout.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_release_candidate_enable_progressive_rollout.yaml delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/fixtures/stale_metadata_report_fixtures.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/helpers/test_slack.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/test_commands.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/test_docker_hub.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/test_gcs_upload.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/test_registry.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/test_registry_entry.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/test_spec_cache.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/test_specs_secrets_mask.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/test_stale_metadata_report.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/test_transform.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/test_validators/__init__.py delete mode 100644 airbyte-ci/connectors/metadata_service/lib/tests/test_validators/test_metadata_validators.py delete mode 100644 airbyte-ci/connectors/pipelines/.gitignore delete mode 100644 airbyte-ci/connectors/pipelines/CONTRIBUTING.md delete mode 100644 airbyte-ci/connectors/pipelines/README.md delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/pipeline.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/build_customization.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/common.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/java_connectors.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/manifest_only_connectors.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/normalization.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/python_connectors.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/pipeline.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/consts.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/context.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/generate_erd/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/generate_erd/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/generate_erd/pipeline.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/list/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/list/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_inline_schemas/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_inline_schemas/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_inline_schemas/pipeline.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/declarative_component_schema.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/manifest_component_transformer.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/manifest_resolver.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/pipeline.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/templates/README.md.j2 delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/utils.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pipeline.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/context.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/pipeline.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pull_request/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pull_request/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pull_request/pipeline.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/reports.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/context.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/pipeline.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/common.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/java_connectors.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/manifest_only_connectors.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/python_connectors.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/templates/test_report.html.j2 delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/pipeline.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/steps.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/templates/up_to_date_pr_body.md.j2 delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/pipeline.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/metadata/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/metadata/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/metadata/pipeline.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/publish/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/publish/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/base_image.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/bump_version.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/changelog.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/docker.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/gradle.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/no_op.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/poetry.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/pull_request.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/python_registry.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/models.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/pipeline.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/update/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/update/commands.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/cli/airbyte_ci.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/cli/auto_update.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/cli/click_decorators.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/cli/confirm_prompt.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/cli/dagger_pipeline_command.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/cli/dagger_run.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/cli/ensure_repo_root.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/cli/lazy_group.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/cli/secrets.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/cli/telemetry.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/consts.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/actions/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/actions/connector/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/actions/connector/hooks.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/actions/connector/normalization.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/common.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/pipx.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/poetry.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/actions/remote_storage.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/actions/secrets.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/actions/system/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/actions/system/common.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/actions/system/docker.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/containers/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/containers/git.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/containers/internal_tools.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/containers/java.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/dagger/containers/python.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/external_scripts/__init__.py delete mode 100755 airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_check.sh delete mode 100755 airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_clean.sh delete mode 100755 airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_dev_install.py delete mode 100755 airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_install.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/hacks.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/cache_keys.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/changelog.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/cli.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/cdk_helpers.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/command.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/dagger_fs.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/format.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/modifed.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/yaml.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/execution/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/execution/argument_parsing.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/execution/run_steps.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/gcs.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/git.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/github.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/pip.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/sentry_utils.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/slack.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/helpers/utils.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/models/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/models/artifacts.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/models/ci_requirements.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/models/contexts/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/models/contexts/click_pipeline_context.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/models/contexts/pipeline_context.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/models/contexts/python_registry_publish.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/models/reports.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/models/secrets.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/models/singleton.py delete mode 100644 airbyte-ci/connectors/pipelines/pipelines/models/steps.py delete mode 100644 airbyte-ci/connectors/pipelines/poetry.lock delete mode 100644 airbyte-ci/connectors/pipelines/pyinstaller_hooks/hook-certifi.py delete mode 100644 airbyte-ci/connectors/pipelines/pyproject.toml delete mode 100644 airbyte-ci/connectors/pipelines/pytest.ini delete mode 100644 airbyte-ci/connectors/pipelines/ruff.toml delete mode 100644 airbyte-ci/connectors/pipelines/tests/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/conftest.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_actions/test_environments.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_bases.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_build_image/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_build_image/dummy_build_customization.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_build_image/test_manifest_only_connectors.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_build_image/test_python_connectors.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_build_image/test_steps/test_common.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/initial_files/changelog_header_no_newline.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/initial_files/changelog_header_no_separator.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/initial_files/no_changelog_header.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/initial_files/valid_changelog_at_end.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/initial_files/valid_changelog_in_middle.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/result_files/changelog_header_no_newline.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/result_files/changelog_header_no_separator.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/result_files/dupicate_version_date_valid_changelog_at_end.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/result_files/dupicate_version_date_valid_changelog_in_middle.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/result_files/dupicate_versions_valid_changelog_at_end.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/result_files/dupicate_versions_valid_changelog_in_middle.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/result_files/duplicate_entry_valid_changelog_at_end.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/result_files/duplicate_entry_valid_changelog_in_middle.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/result_files/existing_entries_valid_changelog_at_end.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/result_files/existing_entries_valid_changelog_in_middle.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/result_files/no_changelog_header.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/result_files/single_insert_valid_changelog_at_end.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_changelog/result_files/single_insert_valid_changelog_in_middle.md delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_cli/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_cli/test_click_decorators.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_commands/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_commands/test_groups/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_commands/test_groups/test_connectors.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_dagger/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_dagger/test_actions/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_dagger/test_actions/test_python/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_dagger/test_actions/test_python/test_common.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_gradle.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_helpers/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_helpers/test_execution/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_helpers/test_execution/test_argument_parsing.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_helpers/test_execution/test_run_steps.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_helpers/test_pip.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_helpers/test_utils.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_models/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_models/test_click_pipeline_context.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_models/test_singleton.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_poetry/test_poetry_publish.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_publish.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_steps/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_steps/test_simple_docker_step.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_steps/test_version_check.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_tests/__init__.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_tests/test_common.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_tests/test_context.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_tests/test_python_connectors.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/test_upgrade_java_cdk.py delete mode 100644 airbyte-ci/connectors/pipelines/tests/utils.py diff --git a/.github/actions/install-airbyte-ci/action.yml b/.github/actions/install-airbyte-ci/action.yml deleted file mode 100644 index 0abae543bb56..000000000000 --- a/.github/actions/install-airbyte-ci/action.yml +++ /dev/null @@ -1,118 +0,0 @@ -name: "Install Airbyte CI" -description: "Install Airbyte CI from source or from a binary according to changed files. Pulls the Dagger Engine image according to the dagger version used in airbyte-ci." - -inputs: - airbyte_ci_binary_url: - description: "URL to airbyte-ci binary" - required: false - default: https://connectors.airbyte.com/airbyte-ci/releases/ubuntu/latest/airbyte-ci - path_to_airbyte_ci_source: - description: "Path to airbyte-ci source" - required: false - default: airbyte-ci/connectors/pipelines - is_fork: - description: "Whether the PR is from a fork" - required: false - default: "false" -runs: - using: "composite" - steps: - - name: Get changed files - uses: tj-actions/changed-files@2d756ea4c53f7f6b397767d8723b3a10a9f35bf2 # v44.0.0 - # When the PR is from a fork, we always install from binary, so we don't need to check for changes - if: inputs.is_fork == 'false' - id: changes - with: - files_yaml: | - pipelines: - - '${{ inputs.path_to_airbyte_ci_source }}/**' - - - name: "Determine how Airbyte CI should be installed" - shell: bash - id: determine-install-mode - run: | - echo "install-mode=binary" >> $GITHUB_OUTPUT - echo "SENTRY_ENVIRONMENT=dev" >> $GITHUB_ENV - - # When the PR is from a fork, we always install from binary - # if: inputs.is_fork == 'false' - # run: | - # if [[ "${{ github.ref }}" != "refs/heads/master" ]] && [[ "${{ steps.changes.outputs.pipelines_any_changed }}" == "true" ]]; then - # echo "Making changes to Airbyte CI on a non-master branch. Airbyte-CI will be installed from source." - # echo "install-mode=source" >> $GITHUB_OUTPUT - # echo "SENTRY_ENVIRONMENT=dev" >> $GITHUB_ENV - # else - # echo "install-mode=binary" >> $GITHUB_OUTPUT - # echo "SENTRY_ENVIRONMENT=production" >> $GITHUB_ENV - # fi - - - name: Install Airbyte CI from binary - id: install-airbyte-ci-binary - if: steps.determine-install-mode.outputs.install-mode == 'binary' || ${{ inputs.is_fork }} == 'true' - shell: bash - run: | - curl -sSL ${{ inputs.airbyte_ci_binary_url }} --output airbyte-ci-bin - sudo mv airbyte-ci-bin /usr/local/bin/airbyte-ci - sudo chmod +x /usr/local/bin/airbyte-ci - - - name: Install Python 3.11 - id: install-python-3-11 - uses: actions/setup-python@7f4fc3e22c37d6ff65e88745f38bd3157c663f7c # v4.9.1 - if: steps.determine-install-mode.outputs.install-mode == 'source' - with: - python-version: "3.11" - token: ${{ inputs.github_token }} - cache: "pip" - check-latest: true - update-environment: true - - - name: Install the latest version of uv - if: steps.determine-install-mode.outputs.install-mode == 'source' - uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0 - - name: Install Airbyte CI from source - id: install-airbyte-ci-source - if: steps.determine-install-mode.outputs.install-mode == 'source' - shell: bash - run: | - uv tool install ${{ inputs.path_to_airbyte_ci_source }} - - - name: Upload uv logs as artifacts on failure - if: failure() - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: uv-logs - path: /opt/uv/logs/ - - - name: Upload pipx logs as artifacts on failure - # E.g. /opt/pipx/logs/cmd_2025-05-01_16.46.50_1_pip_errors.log - if: failure() - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: pipx-logs - path: /opt/pipx/logs/ - - - name: Print installed `airbyte-ci` version - shell: bash - run: | - airbyte-ci --version - - - name: Get dagger engine image name - id: get-dagger-engine-image-name - shell: bash - run: | - dagger_engine_image=$(airbyte-ci --ci-requirements | tail -n 1 | jq -r '.dagger_engine_image') - echo "dagger_engine_image=${dagger_engine_image}" >> "$GITHUB_OUTPUT" - - - name: Get dagger engine image - id: get-dagger-engine-image - uses: ./.github/actions/get-dagger-engine-image - with: - dagger_engine_image: ${{ steps.get-dagger-engine-image-name.outputs.dagger_engine_image }} - -outputs: - install_mode: - description: "Whether Airbyte CI was installed from source or from a binary" - value: ${{ steps.determine-install-mode.outputs.install-mode }} - dagger_engine_image_name: - description: "Dagger engine image name" - value: ${{ steps.get-dagger-engine-image-name.outputs.dagger_engine_image }} diff --git a/.github/actions/run-airbyte-ci/action.yml b/.github/actions/run-airbyte-ci/action.yml deleted file mode 100644 index 60212620535e..000000000000 --- a/.github/actions/run-airbyte-ci/action.yml +++ /dev/null @@ -1,217 +0,0 @@ -name: "Run Dagger pipeline" -description: "Runs a given dagger pipeline" -inputs: - subcommand: - description: "Subcommand for airbyte-ci" - required: true - context: - description: "CI context (e.g., pull_request, manual)" - required: true - github_token: - description: "GitHub token" - required: false - dagger_cloud_token: - description: "Dagger Cloud token" - required: false - docker_hub_username: - description: "Dockerhub username" - required: false - docker_hub_password: - description: "Dockerhub password" - required: false - options: - description: "Options for the subcommand" - required: false - production: - description: "Whether to run in production mode" - required: false - default: "True" - report_bucket_name: - description: "Bucket name for CI reports" - required: false - default: "airbyte-ci-reports-multi" - gcp_gsm_credentials: - description: "GCP credentials for GCP Secret Manager" - required: false - default: "" - gcp_integration_tester_credentials: - description: "GCP credentials for integration tests" - required: false - default: "" - git_repo_url: - description: "Git repository URL" - default: https://github.com/airbytehq/airbyte.git - required: false - git_branch: - description: "Git branch to checkout" - required: false - git_revision: - description: "Git revision to checkout" - required: false - slack_webhook_url: - description: "Slack webhook URL" - required: false - metadata_service_gcs_credentials: - description: "GCP credentials for metadata service" - required: false - metadata_service_bucket_name: - description: "Bucket name for metadata service" - required: false - default: "prod-airbyte-cloud-connector-metadata-service" - sentry_dsn: - description: "Sentry DSN" - required: false - spec_cache_bucket_name: - description: "Bucket name for GCS spec cache" - required: false - default: "io-airbyte-cloud-spec-cache" - spec_cache_gcs_credentials: - description: "GCP credentials for GCS spec cache" - required: false - gcs_credentials: - description: "GCP credentials for GCS" - required: false - ci_job_key: - description: "CI job key" - required: false - s3_build_cache_access_key_id: - description: "Gradle S3 Build Cache AWS access key ID" - required: false - s3_build_cache_secret_key: - description: "Gradle S3 Build Cache AWS secret key" - required: false - airbyte_ci_binary_url: - description: "URL to airbyte-ci binary" - required: false - default: https://connectors.airbyte.com/airbyte-ci/releases/ubuntu/latest/airbyte-ci - python_registry_token: - description: "Python registry API token to publish python package" - required: false - is_fork: - description: "Whether the PR is from a fork" - required: false - default: "false" - max_attempts: - description: "Number of attempts at running the airbyte-ci command" - required: false - default: 1 - retry_wait_seconds: - description: "Number of seconds to wait between retry attempts" - required: false - default: 60 - -runs: - using: "composite" - steps: - - name: Get start timestamp - id: get-start-timestamp - shell: bash - run: echo "start-timestamp=$(date +%s)" >> $GITHUB_OUTPUT - - name: Debug-print local paths checked out - shell: bash - run: | - set -x - echo "Working directory: $(pwd)" - ls -la - ls -la airbyte-python-cdk || echo "No airbyte-python-cdk directory" - ls -laL ../airbyte-python-cdk || echo "No airbyte-python-cdk symlink" - - name: Install Java Environment - id: install-java-environment - uses: ./.github/actions/install-java-environment - - name: Docker login - id: docker-login - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 - if: ${{ inputs.docker_hub_username != '' && inputs.docker_hub_password != '' }} - with: - username: ${{ inputs.docker_hub_username }} - password: ${{ inputs.docker_hub_password }} - - name: Install Airbyte CI - id: install-airbyte-ci - uses: ./.github/actions/install-airbyte-ci - with: - airbyte_ci_binary_url: ${{ inputs.airbyte_ci_binary_url }} - is_fork: ${{ inputs.is_fork }} - - name: Run airbyte-ci - id: run-airbyte-ci - uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2 - env: - CI: "True" - CI_GIT_USER: ${{ github.repository_owner }} - CI_PIPELINE_START_TIMESTAMP: ${{ steps.get-start-timestamp.outputs.start-timestamp }} - PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} - # Next environment variables are workflow inputs based and can be set with empty values if the inputs are not required and passed - CI_CONTEXT: "${{ inputs.context }}" - CI_GIT_BRANCH: ${{ inputs.git_branch || github.head_ref }} - CI_GIT_REPO_URL: ${{ inputs.git_repo_url }} - CI_GIT_REVISION: ${{ inputs.git_revision || github.sha }} - CI_GITHUB_ACCESS_TOKEN: ${{ inputs.github_token }} - CI_JOB_KEY: ${{ inputs.ci_job_key }} - CI_REPORT_BUCKET_NAME: ${{ inputs.report_bucket_name }} - # Disabling Dagger Cloud, as it is not used in the current workflow - # and it is causing log spam in the GitHub Actions logs. - # If this is desired in the future, uncomment the following line and remove the line below setting DO_NOT_TRACK - # DAGGER_CLOUD_TOKEN: "${{ inputs.dagger_cloud_token }}" - DO_NOT_TRACK: "1" # Disable Dagger telemetry (noisy errors) - DOCKER_HUB_PASSWORD: ${{ inputs.docker_hub_password }} - DOCKER_HUB_USERNAME: ${{ inputs.docker_hub_username }} - GCP_GSM_CREDENTIALS: ${{ inputs.gcp_gsm_credentials }} - GCP_INTEGRATION_TESTER_CREDENTIALS: ${{ inputs.gcp_integration_tester_credentials }} - GCS_CREDENTIALS: ${{ inputs.gcs_credentials }} - METADATA_SERVICE_BUCKET_NAME: ${{ inputs.metadata_service_bucket_name }} - METADATA_SERVICE_GCS_CREDENTIALS: ${{ inputs.metadata_service_gcs_credentials }} - PRODUCTION: ${{ inputs.production }} - PYTHON_REGISTRY_TOKEN: ${{ inputs.python_registry_token }} - PYTHON_REGISTRY_URL: ${{ inputs.python_registry_url }} - S3_BUILD_CACHE_ACCESS_KEY_ID: ${{ inputs.s3_build_cache_access_key_id }} - S3_BUILD_CACHE_SECRET_KEY: ${{ inputs.s3_build_cache_secret_key }} - SENTRY_DSN: ${{ inputs.sentry_dsn }} - SLACK_WEBHOOK: ${{ inputs.slack_webhook_url }} - SPEC_CACHE_BUCKET_NAME: ${{ inputs.spec_cache_bucket_name }} - SPEC_CACHE_GCS_CREDENTIALS: ${{ inputs.spec_cache_gcs_credentials }} - with: - shell: bash - max_attempts: ${{ inputs.max_attempts }} - retry_wait_seconds: ${{ inputs.retry_wait_seconds }} - # 360mn > 6 hours: it's the GitHub runner max job duration - timeout_minutes: 360 - command: | - airbyte-ci --disable-update-check --disable-dagger-run --is-ci --gha-workflow-run-id=${{ github.run_id }} ${{ inputs.subcommand }} ${{ inputs.options }} - - name: Stop Engine - id: stop-engine - if: always() - shell: bash - run: | - mapfile -t containers < <(docker ps --filter name="dagger-engine-*" -q) - if [[ "${#containers[@]}" -gt 0 ]]; then - # give 5mn to the Dagger Engine to push cache data to Dagger Cloud - docker stop -t 300 "${containers[@]}"; - fi - - - name: Collect dagger engine logs - id: collect-dagger-engine-logs - if: always() - uses: jwalton/gh-docker-logs@2741064ab9d7af54b0b1ffb6076cf64c16f0220e # v2.2.2 - with: - dest: "./dagger_engine_logs" - images: "registry.dagger.io/engine" - - - name: Tar logs - id: tar-logs - if: always() - shell: bash - run: tar cvzf ./dagger_engine_logs.tgz ./dagger_engine_logs - - - name: Hash subcommand - id: hash-subcommand - shell: bash - if: always() - run: echo "subcommand_hash=$(echo ${{ inputs.subcommand }} | sha256sum | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT - - - name: Upload logs to GitHub - id: upload-dagger-engine-logs - if: always() - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: ${{ github.job }}_${{ steps.hash-subcommand.outputs.subcommand_hash }}_dagger_engine_logs.tgz - path: ./dagger_engine_logs.tgz - retention-days: 7 diff --git a/.github/workflows/connectors_insights.yml b/.github/workflows/connectors_insights.yml deleted file mode 100644 index 2be10c889b10..000000000000 --- a/.github/workflows/connectors_insights.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: Connectors Insights - -on: - schedule: - - cron: "0 0,12 * * *" # Run every 12 hours UTC - workflow_dispatch: - inputs: - rewrite: - default: false -jobs: - connectors_insights: - name: Connectors Insights generation - runs-on: connector-nightly-xlarge - timeout-minutes: 1440 # 24 hours - steps: - - name: Checkout Airbyte - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - - name: Docker login - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_PASSWORD }} - - name: Get Dagger Engine Image - uses: ./.github/actions/get-dagger-engine-image - with: - dagger_engine_image: "registry.dagger.io/engine:v0.9.6" - - name: Set up Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 - with: - python-version: "3.11" - - name: Install Poetry - uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1.4.1 - with: - version: 1.8.5 - virtualenvs-create: true - virtualenvs-in-project: true - installer-parallel: true - - name: Load cached venv - id: cached-poetry-dependencies - uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c # v3.5.0 - with: - path: .venv - key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }} - - name: Install dependencies - if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' - run: poetry -C airbyte-ci/connectors/connectors_insights install --no-interaction --no-root - - name: Install project - run: poetry -C airbyte-ci/connectors/connectors_insights install --no-interaction - - name: Write Google service account key to file - run: echo "$GCP_SA_KEY" > $HOME/gcp-sa-key.json - env: - GCP_SA_KEY: ${{ secrets.METADATA_SERVICE_PROD_GCS_CREDENTIALS }} - - name: Set GOOGLE_APPLICATION_CREDENTIALS - run: echo "GOOGLE_APPLICATION_CREDENTIALS=$HOME/gcp-sa-key.json" >> $GITHUB_ENV - - name: Run connectors insights - run: | - poetry -C airbyte-ci/connectors/connectors_insights run connectors-insights generate --gcs-uri=gs://prod-airbyte-cloud-connector-metadata-service/connector_insights --connector-directory airbyte-integrations/connectors/ --concurrency 10 ${{ inputs.rewrite == 'true' && '--rewrite' || ''}} diff --git a/airbyte-ci/.gitignore b/airbyte-ci/.gitignore deleted file mode 100644 index b33a803302af..000000000000 --- a/airbyte-ci/.gitignore +++ /dev/null @@ -1,172 +0,0 @@ -### Python ### -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/#use-with-ide -.pdm.toml - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ - -### Python Patch ### -# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration -poetry.toml - -# ruff -.ruff_cache/ - -# LSP config files -pyrightconfig.json - -tmp* diff --git a/airbyte-ci/.python-version b/airbyte-ci/.python-version deleted file mode 100644 index 2c0733315e41..000000000000 --- a/airbyte-ci/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.11 diff --git a/airbyte-ci/README.md b/airbyte-ci/README.md deleted file mode 100644 index 8e5c231603cb..000000000000 --- a/airbyte-ci/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Airbyte CI - -This folder is a collection of systems, tools and scripts that are used to run Airbyte's CI/CD - -The installation instructions for the `airbyte-ci` CLI tool cal be found here -[airbyte-ci/connectors/pipelines](connectors/pipelines/README.md) - -## Tools - -| Directory | Description | -| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | -| [`ci_credentials`](connectors/ci_credentials) | A CLI tool to fetch connector secrets from GCP Secrets Manager. | -| [`connector_ops`](connectors/connector_ops) | A python package with utils reused in internal packages. | -| [`connectors_qa`](connectors/connectors_qa/) | A tool to verify connectors have sounds assets and metadata. | -| [`metadata_service`](connectors/metadata_service/) | Tools to generate connector metadata and registry. | -| [`pipelines`](connectors/pipelines/) | Airbyte CI pipelines, including formatting, linting, building, testing connectors, etc. Connector acceptance tests live here. | -| [`auto_merge`](connectors/auto_merge/) | A tool to automatically merge connector pull requests. | diff --git a/airbyte-ci/connectors/README.md b/airbyte-ci/connectors/README.md deleted file mode 100644 index 0af1e828f1b8..000000000000 --- a/airbyte-ci/connectors/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Airbyte Connectors CI - -This folder is a collection of systems, tools and scripts that are used to run CI/CD systems -specific to our connectors. - -For the list of tools and subfolders, please see [README in `airbyte-ci`](../README.md). diff --git a/airbyte-ci/connectors/auto_merge/README.md b/airbyte-ci/connectors/auto_merge/README.md deleted file mode 100644 index 12c280908a80..000000000000 --- a/airbyte-ci/connectors/auto_merge/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# `Auto merge` - -## Purpose - -This Python package is made to merge pull requests automatically on the Airbyte Repo. It is used in -the [following workflow](.github/workflows/auto_merge.yml). - -A pull request is currently considered as auto-mergeable if: - -- It has the `auto-merge` Github label -- It only modifies files in connector-related directories -- All the required checks have passed - -We want to auto-merge a specific set of connector pull requests to simplify the connector updates in -the following use cases: - -- Pull requests updating Python dependencies or the connector base image -- Community contributions when they've been reviewed and approved by our team but CI is still - running: to avoid an extra review iteration just to check CI status. - -## Install and usage - -### Get a Github token - -You need to create a Github token with the following permissions: - -- Read access to the repository to list open pull requests and their statuses -- Write access to the repository to merge pull requests - -### Local install and run - -``` -poetry install -export GITHUB_TOKEN= -# By default no merge will be done, you need to set the AUTO_MERGE_PRODUCTION environment variable to true to actually merge the PRs -poetry run auto-merge -``` - -### In CI - -``` -export GITHUB_TOKEN= -export AUTO_MERGE_PRODUCTION=true -poetry install -poetry run auto-merge -``` - -The execution will set the `GITHUB_STEP_SUMMARY` env var with a markdown summary of the PRs that -have been merged. - -## Changelog - -### 0.1.5 -Update Python version requirement from 3.10 to 3.11. - -### 0.1.3 -Adds `auto-merge/bypass-ci-checks` label which does not require CI checks to pass to auto-merge PR. - -### 0.1.2 -Set merge method to `squash`. - -### 0.1.1 -Consider skipped check runs as successful. - -### 0.1.0 -Initial release. diff --git a/airbyte-ci/connectors/auto_merge/poetry.lock b/airbyte-ci/connectors/auto_merge/poetry.lock deleted file mode 100644 index 0483a94d6505..000000000000 --- a/airbyte-ci/connectors/auto_merge/poetry.lock +++ /dev/null @@ -1,765 +0,0 @@ -# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. - -[[package]] -name = "anyio" -version = "4.3.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"}, - {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"}, -] - -[package.dependencies] -idna = ">=2.8" -sniffio = ">=1.1" - -[package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (>=0.23)"] - -[[package]] -name = "certifi" -version = "2024.2.2" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, -] - -[[package]] -name = "cffi" -version = "1.16.0" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, - {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, - {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, - {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, - {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, - {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, - {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, - {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, - {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, - {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, - {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, - {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, - {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, - {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, - {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, -] - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "charset-normalizer" -version = "3.3.2" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7.0" -groups = ["main"] -files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, -] - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["dev"] -markers = "sys_platform == \"win32\"" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "cryptography" -version = "42.0.7" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"}, - {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"}, - {file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"}, - {file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"}, - {file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"}, - {file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"}, - {file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"}, - {file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"}, -] - -[package.dependencies] -cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] -docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] -nox = ["nox"] -pep8test = ["check-sdist", "click", "mypy", "ruff"] -sdist = ["build"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] -test-randomorder = ["pytest-randomly"] - -[[package]] -name = "deprecated" -version = "1.2.14" -description = "Python @deprecated decorator to deprecate old python classes, functions or methods." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] -files = [ - {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, - {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, -] - -[package.dependencies] -wrapt = ">=1.10,<2" - -[package.extras] -dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] - -[[package]] -name = "idna" -version = "3.7" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.5" -groups = ["main"] -files = [ - {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, - {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, -] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - -[[package]] -name = "mypy" -version = "1.10.0" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "mypy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da1cbf08fb3b851ab3b9523a884c232774008267b1f83371ace57f412fe308c2"}, - {file = "mypy-1.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:12b6bfc1b1a66095ab413160a6e520e1dc076a28f3e22f7fb25ba3b000b4ef99"}, - {file = "mypy-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e36fb078cce9904c7989b9693e41cb9711e0600139ce3970c6ef814b6ebc2b2"}, - {file = "mypy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2b0695d605ddcd3eb2f736cd8b4e388288c21e7de85001e9f85df9187f2b50f9"}, - {file = "mypy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:cd777b780312ddb135bceb9bc8722a73ec95e042f911cc279e2ec3c667076051"}, - {file = "mypy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3be66771aa5c97602f382230165b856c231d1277c511c9a8dd058be4784472e1"}, - {file = "mypy-1.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8b2cbaca148d0754a54d44121b5825ae71868c7592a53b7292eeb0f3fdae95ee"}, - {file = "mypy-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ec404a7cbe9fc0e92cb0e67f55ce0c025014e26d33e54d9e506a0f2d07fe5de"}, - {file = "mypy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e22e1527dc3d4aa94311d246b59e47f6455b8729f4968765ac1eacf9a4760bc7"}, - {file = "mypy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:a87dbfa85971e8d59c9cc1fcf534efe664d8949e4c0b6b44e8ca548e746a8d53"}, - {file = "mypy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a781f6ad4bab20eef8b65174a57e5203f4be627b46291f4589879bf4e257b97b"}, - {file = "mypy-1.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b808e12113505b97d9023b0b5e0c0705a90571c6feefc6f215c1df9381256e30"}, - {file = "mypy-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f55583b12156c399dce2df7d16f8a5095291354f1e839c252ec6c0611e86e2e"}, - {file = "mypy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cf18f9d0efa1b16478c4c129eabec36148032575391095f73cae2e722fcf9d5"}, - {file = "mypy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:bc6ac273b23c6b82da3bb25f4136c4fd42665f17f2cd850771cb600bdd2ebeda"}, - {file = "mypy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9fd50226364cd2737351c79807775136b0abe084433b55b2e29181a4c3c878c0"}, - {file = "mypy-1.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f90cff89eea89273727d8783fef5d4a934be2fdca11b47def50cf5d311aff727"}, - {file = "mypy-1.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fcfc70599efde5c67862a07a1aaf50e55bce629ace26bb19dc17cece5dd31ca4"}, - {file = "mypy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:075cbf81f3e134eadaf247de187bd604748171d6b79736fa9b6c9685b4083061"}, - {file = "mypy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:3f298531bca95ff615b6e9f2fc0333aae27fa48052903a0ac90215021cdcfa4f"}, - {file = "mypy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa7ef5244615a2523b56c034becde4e9e3f9b034854c93639adb667ec9ec2976"}, - {file = "mypy-1.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3236a4c8f535a0631f85f5fcdffba71c7feeef76a6002fcba7c1a8e57c8be1ec"}, - {file = "mypy-1.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2b5cdbb5dd35aa08ea9114436e0d79aceb2f38e32c21684dcf8e24e1e92821"}, - {file = "mypy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92f93b21c0fe73dc00abf91022234c79d793318b8a96faac147cd579c1671746"}, - {file = "mypy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:28d0e038361b45f099cc086d9dd99c15ff14d0188f44ac883010e172ce86c38a"}, - {file = "mypy-1.10.0-py3-none-any.whl", hash = "sha256:f8c083976eb530019175aabadb60921e73b4f45736760826aa1689dda8208aee"}, - {file = "mypy-1.10.0.tar.gz", hash = "sha256:3d087fcbec056c4ee34974da493a826ce316947485cef3901f511848e687c131"}, -] - -[package.dependencies] -mypy-extensions = ">=1.0.0" -typing-extensions = ">=4.1.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -groups = ["dev"] -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "packaging" -version = "24.0" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, - {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, -] - -[[package]] -name = "pluggy" -version = "1.5.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, -] - -[[package]] -name = "pygithub" -version = "2.3.0" -description = "Use the full Github API v3" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "PyGithub-2.3.0-py3-none-any.whl", hash = "sha256:65b499728be3ce7b0cd2cd760da3b32f0f4d7bc55e5e0677617f90f6564e793e"}, - {file = "PyGithub-2.3.0.tar.gz", hash = "sha256:0148d7347a1cdeed99af905077010aef81a4dad988b0ba51d4108bf66b443f7e"}, -] - -[package.dependencies] -Deprecated = "*" -pyjwt = {version = ">=2.4.0", extras = ["crypto"]} -pynacl = ">=1.4.0" -requests = ">=2.14.0" -typing-extensions = ">=4.0.0" -urllib3 = ">=1.26.0" - -[[package]] -name = "pyinstrument" -version = "4.6.2" -description = "Call stack profiler for Python. Shows you why your code is slow!" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "pyinstrument-4.6.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7a1b1cd768ea7ea9ab6f5490f7e74431321bcc463e9441dbc2f769617252d9e2"}, - {file = "pyinstrument-4.6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8a386b9d09d167451fb2111eaf86aabf6e094fed42c15f62ec51d6980bce7d96"}, - {file = "pyinstrument-4.6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23c3e3ca8553b9aac09bd978c73d21b9032c707ac6d803bae6a20ecc048df4a8"}, - {file = "pyinstrument-4.6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f329f5534ca069420246f5ce57270d975229bcb92a3a3fd6b2ca086527d9764"}, - {file = "pyinstrument-4.6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4dcdcc7ba224a0c5edfbd00b0f530f5aed2b26da5aaa2f9af5519d4aa8c7e41"}, - {file = "pyinstrument-4.6.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73db0c2c99119c65b075feee76e903b4ed82e59440fe8b5724acf5c7cb24721f"}, - {file = "pyinstrument-4.6.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:da58f265326f3cf3975366ccb8b39014f1e69ff8327958a089858d71c633d654"}, - {file = "pyinstrument-4.6.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:feebcf860f955401df30d029ec8de7a0c5515d24ea809736430fd1219686fe14"}, - {file = "pyinstrument-4.6.2-cp310-cp310-win32.whl", hash = "sha256:b2b66ff0b16c8ecf1ec22de001cfff46872b2c163c62429055105564eef50b2e"}, - {file = "pyinstrument-4.6.2-cp310-cp310-win_amd64.whl", hash = "sha256:8d104b7a7899d5fa4c5bf1ceb0c1a070615a72c5dc17bc321b612467ad5c5d88"}, - {file = "pyinstrument-4.6.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:62f6014d2b928b181a52483e7c7b82f2c27e22c577417d1681153e5518f03317"}, - {file = "pyinstrument-4.6.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dcb5c8d763c5df55131670ba2a01a8aebd0d490a789904a55eb6a8b8d497f110"}, - {file = "pyinstrument-4.6.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ed4e8c6c84e0e6429ba7008a66e435ede2d8cb027794c20923c55669d9c5633"}, - {file = "pyinstrument-4.6.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c0f0e1d8f8c70faa90ff57f78ac0dda774b52ea0bfb2d9f0f41ce6f3e7c869e"}, - {file = "pyinstrument-4.6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b3c44cb037ad0d6e9d9a48c14d856254ada641fbd0ae9de40da045fc2226a2a"}, - {file = "pyinstrument-4.6.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:be9901f17ac2f527c352f2fdca3d717c1d7f2ce8a70bad5a490fc8cc5d2a6007"}, - {file = "pyinstrument-4.6.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8a9791bf8916c1cf439c202fded32de93354b0f57328f303d71950b0027c7811"}, - {file = "pyinstrument-4.6.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d6162615e783c59e36f2d7caf903a7e3ecb6b32d4a4ae8907f2760b2ef395bf6"}, - {file = "pyinstrument-4.6.2-cp311-cp311-win32.whl", hash = "sha256:28af084aa84bbfd3620ebe71d5f9a0deca4451267f363738ca824f733de55056"}, - {file = "pyinstrument-4.6.2-cp311-cp311-win_amd64.whl", hash = "sha256:dd6007d3c2e318e09e582435dd8d111cccf30d342af66886b783208813caf3d7"}, - {file = "pyinstrument-4.6.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:e3813c8ecfab9d7d855c5f0f71f11793cf1507f40401aa33575c7fd613577c23"}, - {file = "pyinstrument-4.6.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6c761372945e60fc1396b7a49f30592e8474e70a558f1a87346d27c8c4ce50f7"}, - {file = "pyinstrument-4.6.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4fba3244e94c117bf4d9b30b8852bbdcd510e7329fdd5c7c8b3799e00a9215a8"}, - {file = "pyinstrument-4.6.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:803ac64e526473d64283f504df3b0d5c2c203ea9603cab428641538ffdc753a7"}, - {file = "pyinstrument-4.6.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2e554b1bb0df78f5ce8a92df75b664912ca93aa94208386102af454ec31b647"}, - {file = "pyinstrument-4.6.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7c671057fad22ee3ded897a6a361204ea2538e44c1233cad0e8e30f6d27f33db"}, - {file = "pyinstrument-4.6.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:d02f31fa13a9e8dc702a113878419deba859563a32474c9f68e04619d43d6f01"}, - {file = "pyinstrument-4.6.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b55983a884f083f93f0fc6d12ff8df0acd1e2fb0580d2f4c7bfe6def33a84b58"}, - {file = "pyinstrument-4.6.2-cp312-cp312-win32.whl", hash = "sha256:fdc0a53b27e5d8e47147489c7dab596ddd1756b1e053217ef5bc6718567099ff"}, - {file = "pyinstrument-4.6.2-cp312-cp312-win_amd64.whl", hash = "sha256:dd5c53a0159126b5ce7cbc4994433c9c671e057c85297ff32645166a06ad2c50"}, - {file = "pyinstrument-4.6.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b082df0bbf71251a7f4880a12ed28421dba84ea7110bb376e0533067a4eaff40"}, - {file = "pyinstrument-4.6.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90350533396071cb2543affe01e40bf534c35cb0d4b8fa9fdb0f052f9ca2cfe3"}, - {file = "pyinstrument-4.6.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:67268bb0d579330cff40fd1c90b8510363ca1a0e7204225840614068658dab77"}, - {file = "pyinstrument-4.6.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20e15b4e1d29ba0b7fc81aac50351e0dc0d7e911e93771ebc3f408e864a2c93b"}, - {file = "pyinstrument-4.6.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:2e625fc6ffcd4fd420493edd8276179c3f784df207bef4c2192725c1b310534c"}, - {file = "pyinstrument-4.6.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:113d2fc534c9ca7b6b5661d6ada05515bf318f6eb34e8d05860fe49eb7cfe17e"}, - {file = "pyinstrument-4.6.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3098cd72b71a322a72dafeb4ba5c566465e193d2030adad4c09566bd2f89bf4f"}, - {file = "pyinstrument-4.6.2-cp37-cp37m-win32.whl", hash = "sha256:08fdc7f88c989316fa47805234c37a40fafe7b614afd8ae863f0afa9d1707b37"}, - {file = "pyinstrument-4.6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:5ebeba952c0056dcc9b9355328c78c4b5c2a33b4b4276a9157a3ab589f3d1bac"}, - {file = "pyinstrument-4.6.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:34e59e91c88ec9ad5630c0964eca823949005e97736bfa838beb4789e94912a2"}, - {file = "pyinstrument-4.6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cd0320c39e99e3c0a3129d1ed010ac41e5a7eb96fb79900d270080a97962e995"}, - {file = "pyinstrument-4.6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46992e855d630575ec635eeca0068a8ddf423d4fd32ea0875a94e9f8688f0b95"}, - {file = "pyinstrument-4.6.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e474c56da636253dfdca7cd1998b240d6b39f7ed34777362db69224fcf053b1"}, - {file = "pyinstrument-4.6.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4b559322f30509ad8f082561792352d0805b3edfa508e492a36041fdc009259"}, - {file = "pyinstrument-4.6.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:06a8578b2943eb1dbbf281e1e59e44246acfefd79e1b06d4950f01b693de12af"}, - {file = "pyinstrument-4.6.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7bd3da31c46f1c1cb7ae89031725f6a1d1015c2041d9c753fe23980f5f9fd86c"}, - {file = "pyinstrument-4.6.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e63f4916001aa9c625976a50779282e0a5b5e9b17c52a50ef4c651e468ed5b88"}, - {file = "pyinstrument-4.6.2-cp38-cp38-win32.whl", hash = "sha256:32ec8db6896b94af790a530e1e0edad4d0f941a0ab8dd9073e5993e7ea46af7d"}, - {file = "pyinstrument-4.6.2-cp38-cp38-win_amd64.whl", hash = "sha256:a59fc4f7db738a094823afe6422509fa5816a7bf74e768ce5a7a2ddd91af40ac"}, - {file = "pyinstrument-4.6.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3a165e0d2deb212d4cf439383982a831682009e1b08733c568cac88c89784e62"}, - {file = "pyinstrument-4.6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7ba858b3d6f6e5597c641edcc0e7e464f85aba86d71bc3b3592cb89897bf43f6"}, - {file = "pyinstrument-4.6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fd8e547cf3df5f0ec6e4dffbe2e857f6b28eda51b71c3c0b5a2fc0646527835"}, - {file = "pyinstrument-4.6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0de2c1714a37a820033b19cf134ead43299a02662f1379140974a9ab733c5f3a"}, - {file = "pyinstrument-4.6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01fc45dedceec3df81668d702bca6d400d956c8b8494abc206638c167c78dfd9"}, - {file = "pyinstrument-4.6.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5b6e161ef268d43ee6bbfae7fd2cdd0a52c099ddd21001c126ca1805dc906539"}, - {file = "pyinstrument-4.6.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6ba8e368d0421f15ba6366dfd60ec131c1b46505d021477e0f865d26cf35a605"}, - {file = "pyinstrument-4.6.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edca46f04a573ac2fb11a84b937844e6a109f38f80f4b422222fb5be8ecad8cb"}, - {file = "pyinstrument-4.6.2-cp39-cp39-win32.whl", hash = "sha256:baf375953b02fe94d00e716f060e60211ede73f49512b96687335f7071adb153"}, - {file = "pyinstrument-4.6.2-cp39-cp39-win_amd64.whl", hash = "sha256:af1a953bce9fd530040895d01ff3de485e25e1576dccb014f76ba9131376fcad"}, - {file = "pyinstrument-4.6.2.tar.gz", hash = "sha256:0002ee517ed8502bbda6eb2bb1ba8f95a55492fcdf03811ba13d4806e50dd7f6"}, -] - -[package.extras] -bin = ["click", "nox"] -docs = ["furo (==2021.6.18b36)", "myst-parser (==0.15.1)", "sphinx (==4.2.0)", "sphinxcontrib-programoutput (==0.17)"] -examples = ["django", "numpy"] -test = ["flaky", "greenlet (>=3.0.0a1)", "ipython", "pytest", "pytest-asyncio (==0.12.0)", "sphinx-autobuild (==2021.3.14)", "trio"] -types = ["typing-extensions"] - -[[package]] -name = "pyjwt" -version = "2.8.0" -description = "JSON Web Token implementation in Python" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, - {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, -] - -[package.dependencies] -cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"crypto\""} - -[package.extras] -crypto = ["cryptography (>=3.4.0)"] -dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] -docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] - -[[package]] -name = "pynacl" -version = "1.5.0" -description = "Python binding to the Networking and Cryptography (NaCl) library" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, - {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, -] - -[package.dependencies] -cffi = ">=1.4.1" - -[package.extras] -docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] -tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] - -[[package]] -name = "pytest" -version = "8.2.0" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pytest-8.2.0-py3-none-any.whl", hash = "sha256:1733f0620f6cda4095bbf0d9ff8022486e91892245bb9e7d5542c018f612f233"}, - {file = "pytest-8.2.0.tar.gz", hash = "sha256:d507d4482197eac0ba2bae2e9babf0672eb333017bcedaa5fb1a3d42c1174b3f"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=1.5,<2.0" - -[package.extras] -dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "requests" -version = "2.31.0" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "ruff" -version = "0.4.3" -description = "An extremely fast Python linter and code formatter, written in Rust." -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "ruff-0.4.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b70800c290f14ae6fcbb41bbe201cf62dfca024d124a1f373e76371a007454ce"}, - {file = "ruff-0.4.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:08a0d6a22918ab2552ace96adeaca308833873a4d7d1d587bb1d37bae8728eb3"}, - {file = "ruff-0.4.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba1f14df3c758dd7de5b55fbae7e1c8af238597961e5fb628f3de446c3c40c5"}, - {file = "ruff-0.4.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:819fb06d535cc76dfddbfe8d3068ff602ddeb40e3eacbc90e0d1272bb8d97113"}, - {file = "ruff-0.4.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bfc9e955e6dc6359eb6f82ea150c4f4e82b660e5b58d9a20a0e42ec3bb6342b"}, - {file = "ruff-0.4.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:510a67d232d2ebe983fddea324dbf9d69b71c4d2dfeb8a862f4a127536dd4cfb"}, - {file = "ruff-0.4.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9ff11cd9a092ee7680a56d21f302bdda14327772cd870d806610a3503d001f"}, - {file = "ruff-0.4.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29efff25bf9ee685c2c8390563a5b5c006a3fee5230d28ea39f4f75f9d0b6f2f"}, - {file = "ruff-0.4.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18b00e0bcccf0fc8d7186ed21e311dffd19761cb632241a6e4fe4477cc80ef6e"}, - {file = "ruff-0.4.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:262f5635e2c74d80b7507fbc2fac28fe0d4fef26373bbc62039526f7722bca1b"}, - {file = "ruff-0.4.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7363691198719c26459e08cc17c6a3dac6f592e9ea3d2fa772f4e561b5fe82a3"}, - {file = "ruff-0.4.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:eeb039f8428fcb6725bb63cbae92ad67b0559e68b5d80f840f11914afd8ddf7f"}, - {file = "ruff-0.4.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:927b11c1e4d0727ce1a729eace61cee88a334623ec424c0b1c8fe3e5f9d3c865"}, - {file = "ruff-0.4.3-py3-none-win32.whl", hash = "sha256:25cacda2155778beb0d064e0ec5a3944dcca9c12715f7c4634fd9d93ac33fd30"}, - {file = "ruff-0.4.3-py3-none-win_amd64.whl", hash = "sha256:7a1c3a450bc6539ef00da6c819fb1b76b6b065dec585f91456e7c0d6a0bbc725"}, - {file = "ruff-0.4.3-py3-none-win_arm64.whl", hash = "sha256:71ca5f8ccf1121b95a59649482470c5601c60a416bf189d553955b0338e34614"}, - {file = "ruff-0.4.3.tar.gz", hash = "sha256:ff0a3ef2e3c4b6d133fbedcf9586abfbe38d076041f2dc18ffb2c7e0485d5a07"}, -] - -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - -[[package]] -name = "types-requests" -version = "2.32.4.20260107" -description = "Typing stubs for requests" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "types_requests-2.32.4.20260107-py3-none-any.whl", hash = "sha256:b703fe72f8ce5b31ef031264fe9395cac8f46a04661a79f7ed31a80fb308730d"}, - {file = "types_requests-2.32.4.20260107.tar.gz", hash = "sha256:018a11ac158f801bfa84857ddec1650750e393df8a004a8a9ae2a9bec6fcb24f"}, -] - -[package.dependencies] -urllib3 = ">=2" - -[[package]] -name = "typing-extensions" -version = "4.11.0" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"}, - {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, -] - -[[package]] -name = "urllib3" -version = "2.2.1" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "wrapt" -version = "1.16.0" -description = "Module for decorators, wrappers and monkey patching." -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, - {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, - {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, - {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, - {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, - {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, - {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, - {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, - {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, - {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, - {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, - {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, - {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, - {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, - {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, - {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, - {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, - {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, - {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, - {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, - {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, - {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, - {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, - {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, - {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, - {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, - {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, - {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, -] - -[metadata] -lock-version = "2.1" -python-versions = "^3.11" -content-hash = "1a6eba17c6fa90cca5ad3d50ad6b16b1794845be537b4b6f4f1e2dd335fec66a" diff --git a/airbyte-ci/connectors/auto_merge/pyproject.toml b/airbyte-ci/connectors/auto_merge/pyproject.toml deleted file mode 100644 index 9651ef70fdbc..000000000000 --- a/airbyte-ci/connectors/auto_merge/pyproject.toml +++ /dev/null @@ -1,47 +0,0 @@ -[tool.poetry] -name = "auto-merge" -version = "0.1.5" -description = "" -authors = ["Airbyte "] -readme = "README.md" -packages = [ - { include = "auto_merge", from = "src" }, -] - -[tool.poetry.dependencies] -python = "^3.11" -pygithub = "^2.3.0" -anyio = "^4.3.0" - - -[tool.poetry.group.dev.dependencies] -mypy = "^1.10.0" -ruff = "^0.4.3" -pytest = "^8.2.0" -pyinstrument = "^4.6.2" -types-requests = "^2.32.4.20260107" - -[tool.ruff] -line-length = 140 - -[tool.ruff.lint] -select = [ - "I" # isort -] - -[tool.poetry.scripts] -auto-merge = "auto_merge.main:auto_merge" - -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" - -[tool.poe.tasks] -test = "pytest tests" -type_check = "mypy src --disallow-untyped-defs" -lint = "ruff check src" - -[tool.airbyte_ci] -python_versions = ["3.11"] -optional_poetry_groups = ["dev"] -poe_tasks = ["type_check", "lint",] diff --git a/airbyte-ci/connectors/auto_merge/src/auto_merge/__init__.py b/airbyte-ci/connectors/auto_merge/src/auto_merge/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/airbyte-ci/connectors/auto_merge/src/auto_merge/consts.py b/airbyte-ci/connectors/auto_merge/src/auto_merge/consts.py deleted file mode 100644 index cce847b02427..000000000000 --- a/airbyte-ci/connectors/auto_merge/src/auto_merge/consts.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -AIRBYTE_REPO = "airbytehq/airbyte" -AUTO_MERGE_LABEL = "auto-merge" -AUTO_MERGE_BYPASS_CI_CHECKS_LABEL = "auto-merge/bypass-ci-checks" -BASE_BRANCH = "master" -CONNECTOR_PATH_PREFIXES = { - "airbyte-integrations/connectors", - "docs/integrations/sources", - "docs/integrations/destinations", - "docs/ai-agents/connectors", - "docs/developers/pyairbyte", - "docusaurus/src/data", -} -MERGE_METHOD = "squash" diff --git a/airbyte-ci/connectors/auto_merge/src/auto_merge/env.py b/airbyte-ci/connectors/auto_merge/src/auto_merge/env.py deleted file mode 100644 index cfb82f108bee..000000000000 --- a/airbyte-ci/connectors/auto_merge/src/auto_merge/env.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -import os - -GITHUB_TOKEN = os.environ["GITHUB_TOKEN"] -PRODUCTION = os.environ.get("AUTO_MERGE_PRODUCTION", "false").lower() == "true" diff --git a/airbyte-ci/connectors/auto_merge/src/auto_merge/helpers.py b/airbyte-ci/connectors/auto_merge/src/auto_merge/helpers.py deleted file mode 100644 index ba56389226bf..000000000000 --- a/airbyte-ci/connectors/auto_merge/src/auto_merge/helpers.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -import time -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from github.PullRequest import PullRequest - - -def generate_job_summary_as_markdown(merged_prs: list[PullRequest]) -> str: - """Generate a markdown summary of the merged PRs - - Args: - merged_prs (list[PullRequest]): The PRs that were merged - - Returns: - str: The markdown summary - """ - summary_time = time.strftime("%Y-%m-%d %H:%M:%S") - header = "# Auto-merged PRs" - details = f"Summary generated at {summary_time}" - if not merged_prs: - return f"{header}\n\n{details}\n\n**No PRs were auto-merged**\n" - merged_pr_list = "\n".join([f"- [#{pr.number} - {pr.title}]({pr.html_url})" for pr in merged_prs]) - return f"{header}\n\n{details}\n\n{merged_pr_list}\n" diff --git a/airbyte-ci/connectors/auto_merge/src/auto_merge/main.py b/airbyte-ci/connectors/auto_merge/src/auto_merge/main.py deleted file mode 100644 index 2ac5dd00cc95..000000000000 --- a/airbyte-ci/connectors/auto_merge/src/auto_merge/main.py +++ /dev/null @@ -1,252 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -import logging -import os -import time -from collections.abc import Iterator -from contextlib import contextmanager -from pathlib import Path -from typing import TYPE_CHECKING, Callable, Optional - -import requests -from github import Auth, Github - -from .consts import ( - AIRBYTE_REPO, - AUTO_MERGE_BYPASS_CI_CHECKS_LABEL, - AUTO_MERGE_LABEL, - BASE_BRANCH, - MERGE_METHOD, -) -from .env import GITHUB_TOKEN, PRODUCTION -from .helpers import generate_job_summary_as_markdown -from .pr_validators import VALIDATOR_MAPPING - -if TYPE_CHECKING: - from github.Commit import Commit as GithubCommit - from github.PullRequest import PullRequest - from github.Repository import Repository as GithubRepo - -logging.basicConfig() -logger = logging.getLogger("auto_merge") -logger.setLevel(logging.INFO) - - -@contextmanager -def github_client() -> Iterator[Github]: - client = None - try: - client = Github(auth=Auth.Token(GITHUB_TOKEN), seconds_between_requests=0) - yield client - finally: - if client: - client.close() - - -def check_if_pr_is_auto_mergeable(head_commit: GithubCommit, pr: PullRequest, required_checks: set[str]) -> bool: - """Run all enabled validators and return if they all pass. - - Args: - head_commit (GithubCommit): The head commit of the PR - pr (PullRequest): The PR to check - required_checks (set[str]): The set of required passing checks - - Returns: - bool: True if the PR is auto-mergeable, False otherwise - """ - - validators = get_pr_validators(pr) - for validator in validators: - is_valid, error = validator(head_commit, pr, required_checks) - if not is_valid: - if error: - logger.info(f"PR #{pr.number} - {error}") - return False - return True - - -def get_pr_validators(pr: PullRequest) -> set[Callable]: - """ - Get the validator for a PR based on its labels - - Args: - pr (PullRequest): The PR to get the validator for - - Returns: - list[callable]: The validators - """ - validators: set[Callable] = set() - for label in pr.labels: - if label.name in VALIDATOR_MAPPING: - # Add these to our validators set: - validators |= VALIDATOR_MAPPING[label.name] - - if not validators: - # We shouldn't reach this point, but if we do, we raise an error. - # TODO: We could consider returning a dummy callable which always returns False, - # but for now, we raise an error to ensure we catch any misconfigurations. - raise ValueError( - f"PR #{pr.number} does not have a valid auto-merge label. " - f"Expected one of [{', '.join(VALIDATOR_MAPPING.keys())}], but got: " - f"[{'; '.join(label.name for label in pr.labels)}]", - ) - - return validators - - -def mark_pr_as_ready(node_id: str) -> None: - """Mark a draft PR as ready for review using the GitHub GraphQL API. - - The REST API PATCH endpoint does not support changing draft status. - The GraphQL markPullRequestReadyForReview mutation is required instead. - - Args: - node_id (str): The GraphQL node ID of the pull request - """ - query = """ - mutation($prId: ID!) { - markPullRequestReadyForReview(input: {pullRequestId: $prId}) { - pullRequest { isDraft } - } - } - """ - response = requests.post( - "https://api.github.com/graphql", - json={"query": query, "variables": {"prId": node_id}}, - headers={ - "Authorization": f"token {GITHUB_TOKEN}", - "Accept": "application/vnd.github+json", - }, - ) - response.raise_for_status() - data = response.json() - if "errors" in data: - raise RuntimeError(f"GraphQL error marking PR as ready: {data['errors']}") - - -def merge_with_retries(pr: PullRequest, max_retries: int = 3, wait_time: int = 60) -> Optional[PullRequest]: - """Merge a PR with retries - - Args: - pr (PullRequest): The PR to merge - max_retries (int, optional): The maximum number of retries. Defaults to 3. - wait_time (int, optional): The time to wait between retries in seconds. Defaults to 60. - """ - if pr.draft: - logger.info(f"PR #{pr.number} is a draft, marking as ready for review before merging") - mark_pr_as_ready(pr.node_id) - pr.update() - logger.info(f"PR #{pr.number} draft status after marking ready: {pr.draft}") - for i in range(max_retries): - try: - pr.merge(merge_method=MERGE_METHOD) - logger.info(f"PR #{pr.number} was auto-merged") - return pr - except Exception as e: - logger.error(f"Failed to merge PR #{pr.number} - {e}") - if i < max_retries - 1: - logger.info(f"Retrying to merge PR #{pr.number}") - time.sleep(wait_time) - else: - logger.error(f"Failed to merge PR #{pr.number} after {max_retries} retries") - return None - - -def process_pr(repo: GithubRepo, pr: PullRequest, required_passing_contexts: set[str], dry_run: bool) -> None | PullRequest: - """Process a PR to see if it is auto-mergeable and merge it if it is. - - Args: - repo (GithubRepo): The repository the PR is in - pr (PullRequest): The PR to process - required_passing_contexts (set[str]): The set of required passing checks - dry_run (bool): Whether to actually merge the PR or not - - Returns: - None | PullRequest: The PR if it was merged, None otherwise - """ - logger.info(f"Processing PR #{pr.number}") - head_commit = repo.get_commit(sha=pr.head.sha) - if check_if_pr_is_auto_mergeable(head_commit, pr, required_passing_contexts): - if not dry_run: - merge_with_retries(pr) - return pr - else: - logger.info(f"PR #{pr.number} is auto-mergeable but dry-run is enabled") - return None - - -def get_required_passing_contexts(repo_name: str, branch: str, token: str) -> set[str]: - """Fetch required status check contexts from GitHub rulesets for a branch. - - Uses the GitHub Rules API (GET /repos/{owner}/{repo}/rules/branches/{branch}) - which returns active rules from repository rulesets. - - Args: - repo_name (str): The repository in owner/repo format - branch (str): The branch name - token (str): The GitHub token for authentication - - Returns: - set[str]: The set of required status check context strings - """ - url = f"https://api.github.com/repos/{repo_name}/rules/branches/{branch}" - headers = { - "Authorization": f"token {token}", - "Accept": "application/vnd.github+json", - } - response = requests.get(url, headers=headers) - response.raise_for_status() - contexts: set[str] = set() - for rule in response.json(): - if rule["type"] == "required_status_checks": - for check in rule.get("parameters", {}).get("required_status_checks", []): - contexts.add(check["context"]) - return contexts - - -def back_off_if_rate_limited(github_client: Github) -> None: - """Sleep if the rate limit is reached - - Args: - github_client (Github): The Github client to check the rate limit of - """ - remaining_requests, _ = github_client.rate_limiting - if remaining_requests < 100: - logging.warning(f"Rate limit almost reached. Remaining requests: {remaining_requests}") - if remaining_requests == 0: - logging.warning(f"Rate limited. Sleeping for {github_client.rate_limiting_resettime - time.time()} seconds") - time.sleep(github_client.rate_limiting_resettime - time.time()) - return None - - -def auto_merge() -> None: - """Main function to auto-merge PRs that are candidates for auto-merge. - If the AUTO_MERGE_PRODUCTION environment variable is not set to "true", this will be a dry run. - """ - dry_run = PRODUCTION is False - if PRODUCTION: - logger.info("Running auto-merge in production mode. Mergeable PRs will be merged!") - else: - logger.info("Running auto-merge in dry mode mode. Mergeable PRs won't be merged!") - - with github_client() as gh_client: - repo = gh_client.get_repo(AIRBYTE_REPO) - logger.info(f"Fetching required passing contexts for {BASE_BRANCH}") - required_passing_contexts = get_required_passing_contexts(AIRBYTE_REPO, BASE_BRANCH, GITHUB_TOKEN) - candidate_issues = gh_client.search_issues( - f"repo:{AIRBYTE_REPO} is:pr label:{AUTO_MERGE_LABEL},{AUTO_MERGE_BYPASS_CI_CHECKS_LABEL} base:{BASE_BRANCH} state:open" - ) - prs = [issue.as_pull_request() for issue in candidate_issues] - logger.info( - f"Found {len(prs)} open PRs targeting {BASE_BRANCH} with the '{AUTO_MERGE_LABEL}' or '{AUTO_MERGE_BYPASS_CI_CHECKS_LABEL}' label" - ) - merged_prs = [] - for pr in prs: - back_off_if_rate_limited(gh_client) - if merged_pr := process_pr(repo, pr, required_passing_contexts, dry_run): - merged_prs.append(merged_pr) - if "GITHUB_STEP_SUMMARY" in os.environ: - job_summary_path = Path(os.environ["GITHUB_STEP_SUMMARY"]).write_text(generate_job_summary_as_markdown(merged_prs)) - logger.info(f"Job summary written to {job_summary_path}") diff --git a/airbyte-ci/connectors/auto_merge/src/auto_merge/pr_validators.py b/airbyte-ci/connectors/auto_merge/src/auto_merge/pr_validators.py deleted file mode 100644 index f08c71b33a56..000000000000 --- a/airbyte-ci/connectors/auto_merge/src/auto_merge/pr_validators.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -from typing import TYPE_CHECKING, Callable, Optional, Tuple - -from .consts import ( - AUTO_MERGE_BYPASS_CI_CHECKS_LABEL, - AUTO_MERGE_LABEL, - BASE_BRANCH, - CONNECTOR_PATH_PREFIXES, -) - -if TYPE_CHECKING: - from github.Commit import Commit as GithubCommit - from github.PullRequest import PullRequest - - -def has_auto_merge_label(head_commit: GithubCommit, pr: PullRequest, required_checks: set[str]) -> Tuple[bool, Optional[str]]: - has_auto_merge_label = any(label.name == AUTO_MERGE_LABEL for label in pr.labels) - if not has_auto_merge_label: - return False, f"does not have the {AUTO_MERGE_LABEL} label" - return True, None - - -def has_auto_merge_bypass_ci_checks_label( - head_commit: GithubCommit, pr: PullRequest, required_checks: set[str] -) -> Tuple[bool, Optional[str]]: - has_auto_merge_bypass_ci_checks_label = any(label.name == AUTO_MERGE_BYPASS_CI_CHECKS_LABEL for label in pr.labels) - if not has_auto_merge_bypass_ci_checks_label: - return False, f"does not have the {AUTO_MERGE_BYPASS_CI_CHECKS_LABEL} label" - return True, None - - -def targets_main_branch(head_commit: GithubCommit, pr: PullRequest, required_checks: set[str]) -> Tuple[bool, Optional[str]]: - if not pr.base.ref == BASE_BRANCH: - return False, f"does not target {BASE_BRANCH}" - return True, None - - -def only_modifies_connectors(head_commit: GithubCommit, pr: PullRequest, required_checks: set[str]) -> Tuple[bool, Optional[str]]: - modified_files = pr.get_files() - for file in modified_files: - if not any(file.filename.startswith(prefix) for prefix in CONNECTOR_PATH_PREFIXES): - return False, "is not only modifying connectors" - return True, None - - -def head_commit_passes_all_required_checks( - head_commit: GithubCommit, pr: PullRequest, required_checks: set[str] -) -> Tuple[bool, Optional[str]]: - successful_status_contexts = [commit_status.context for commit_status in head_commit.get_statuses() if commit_status.state == "success"] - successful_check_runs = [ - check_run.name - for check_run in head_commit.get_check_runs() - # Github considers a required check as passing if it has a conclusion of "success" or "skipped" - if check_run.conclusion == "success" or check_run.conclusion == "skipped" - ] - successful_contexts = set(successful_status_contexts + successful_check_runs) - if not required_checks.issubset(successful_contexts): - return False, "not all required checks passed" - return True, None - - -# A PR is considered auto-mergeable if: -# - it has the AUTO_MERGE_LABEL -# - it targets the BASE_BRANCH -# - it touches only files in CONNECTOR_PATH_PREFIXES -# - the head commit passes all required checks - -# PLEASE BE CAREFUL OF THE VALIDATOR ORDERING -# Let's declare faster checks first as the check_if_pr_is_auto_mergeable function fails fast. -COMMON_VALIDATORS = { - targets_main_branch, - only_modifies_connectors, -} -# Let's declare faster checks first as the check_if_pr_is_auto_mergeable function fails fast. -VALIDATOR_MAPPING: dict[str, set[Callable]] = { - # Until we have an auto-approve mechanism, we use this pipeline to force-merge, - # as long as all required checks pass. This doesn't bypass checks but it bypasses the - # approval requirement: - AUTO_MERGE_LABEL: COMMON_VALIDATORS | {has_auto_merge_label, head_commit_passes_all_required_checks}, - # These are pure registry updates, and can be auto-merged without any CI checks: - AUTO_MERGE_BYPASS_CI_CHECKS_LABEL: COMMON_VALIDATORS | {has_auto_merge_bypass_ci_checks_label}, -} diff --git a/airbyte-ci/connectors/ci_credentials/README.md b/airbyte-ci/connectors/ci_credentials/README.md deleted file mode 100644 index 314cdde32d7b..000000000000 --- a/airbyte-ci/connectors/ci_credentials/README.md +++ /dev/null @@ -1,129 +0,0 @@ -# CI Credentials - -CLI tooling to read and manage GSM secrets: - -- `write-to-storage` download a connector's secrets locally in the connector's `secrets` folder -- `update-secrets` uploads new connector secret version that were locally updated. - -## Requirements - -This project requires Python 3.11 and `pipx`. - -## Installation - -The recommended way to install `ci_credentials` is using pipx. This ensures the tool and its dependencies are isolated from your other Python projects. - -First, install `pyenv`. If you don't have it yet, you can install it using Homebrew: - -```bash -brew update -brew install pyenv -``` - -If you haven't installed pipx, you can do it with pip: - -```bash -cd airbyte-ci/connectors/ci_credentials/ -pyenv install # ensure you have the correct python version -python -m pip install --user pipx -python -m pipx ensurepath -``` - -Once pyenv and pipx is installed then run the following (assuming you're in Airbyte repo root): - -```bash -pipx install --editable --force --python=python3.11 airbyte-ci/connectors/ci_credentials/ -``` - -Or install with a link to the default branch of the repo: - -```bash -pipx install git+https://github.com/airbytehq/airbyte.git#subdirectory=airbyte-ci/connectors/ci_credentials -``` - -This command installs `ci_credentials` and makes it globally available in your terminal. - -> [!Note] -> -> - `--force` is required to ensure updates are applied on subsequent installs. -> - `--python=python3.11` is required to ensure the correct python version is used. - -## Get GSM access - -Download a Service account json key that has access to Google Secrets Manager. -`ci_credentials` expects `GCP_GSM_CREDENTIALS` to be set in environment to be able to access secrets. - -### Create Service Account - -- Go to https://console.cloud.google.com/iam-admin/serviceaccounts/create?project=dataline-integration-testing -- In step #1 `Service account details`, set a name and a relevant description -- In step #2 `Grant this service account access to project`, select role `Owner` (there is a role that is more scope but I based this decision on others `-testing` service account) - -### Create Service Account Token - -- Go to https://console.cloud.google.com/iam-admin/serviceaccounts?project=dataline-integration-testing -- Find your service account and click on it -- Go in the tab "KEYS" -- Click on "ADD KEY -> Create new key" and select JSON. This will download a file on your computer - -### Setup ci_credentials - -- In your .zshrc, add: `export GCP_GSM_CREDENTIALS=$(cat )` - -## Development - -During development, you can use the `--editable` option to make changes to the `ci_credentials` package and have them immediately take effect without needing to reinstall the package: - -```bash -pipx install --editable airbyte-ci/connectors/ci_credentials/ -``` - -This is useful when you are making changes to the package and want to test them in real-time. - -> [!Note] -> -> - The package name is `ci_credentials`, not `airbyte-ci`. You will need this when uninstalling or reinstalling. - -## Usage - -After installation, you can use the `ci_credentials` command in your terminal. - -## Run it - -The `VERSION=dev` will make it so it knows to use your local current working directory and not the Github Action one. - -### Write credentials for a specific connector to local storage - -To download GSM secrets to `airbyte-integrations/connectors/source-bings-ads/secrets`: - -```bash -VERSION=dev ci_credentials source-bing-ads write-to-storage -``` - -### Write credentials for all connectors to local storage - -To download GSM secrets to for all available connectors into their respective `secrets` directories: - -```bash -VERSION=dev ci_credentials all write-to-storage -``` - -### Update secrets - -To upload to GSM newly updated configurations from `airbyte-integrations/connectors/source-bings-ads/secrets/updated_configurations`: - -```bash -VERSION=dev ci_credentials source-bing-ads update-secrets -``` - -## FAQ - -### Help - -```bash -VERSION=dev ci_credentials --help -``` - -### What is `VERSION=dev`? - -This is a way to tell the tool to write secrets using your local current working directory and not the Github Action runner one. diff --git a/airbyte-ci/connectors/ci_credentials/ci_credentials/__init__.py b/airbyte-ci/connectors/ci_credentials/ci_credentials/__init__.py deleted file mode 100644 index c49b12f7a07d..000000000000 --- a/airbyte-ci/connectors/ci_credentials/ci_credentials/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from .secrets_manager import SecretsManager - -__all__ = ("SecretsManager",) diff --git a/airbyte-ci/connectors/ci_credentials/ci_credentials/google_api.py b/airbyte-ci/connectors/ci_credentials/ci_credentials/google_api.py deleted file mode 100644 index 69d12894ac90..000000000000 --- a/airbyte-ci/connectors/ci_credentials/ci_credentials/google_api.py +++ /dev/null @@ -1,90 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import time -from dataclasses import dataclass -from typing import Any, ClassVar, List, Mapping - -import jwt -import requests - -from .logger import Logger - - -TOKEN_TTL = 3600 - - -@dataclass -class GoogleApi: - """ - Simple Google API client - """ - - logger: ClassVar[Logger] = Logger() - - config: Mapping[str, Any] - scopes: List[str] - _access_token: str = None - - def get(self, url: str, params: Mapping = None) -> Mapping[str, Any]: - """Sends a GET request""" - token = self.get_access_token() - headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json", "X-Goog-User-Project": self.project_id} - # Making a get request - response = requests.get(url, headers=headers, params=params) - response.raise_for_status() - return response.json() - - def post(self, url: str, json: Mapping = None, params: Mapping = None) -> Mapping[str, Any]: - """Sends a POST request""" - token = self.get_access_token() - - headers = {"Authorization": f"Bearer {token}", "X-Goog-User-Project": self.project_id} - # Making a get request - response = requests.post(url, headers=headers, json=json, params=params) - try: - response.raise_for_status() - except Exception: - self.logger.error(f"error body: {response.text}") - raise - return response.json() - - @property - def token_uri(self): - return self.config["token_uri"] - - @property - def project_id(self): - return self.config["project_id"] - - def __generate_jwt(self) -> str: - """Generates JWT token by a service account json file and scopes""" - now = int(time.time()) - claim = { - "iat": now, - "iss": self.config["client_email"], - "scope": ",".join(self.scopes), - "aud": self.token_uri, - "exp": now + TOKEN_TTL, - } - return jwt.encode(claim, self.config["private_key"].encode(), algorithm="RS256") - - def get_access_token(self) -> str: - """Generates an access token by a service account json file and scopes""" - - if self._access_token is None: - self._access_token = self.__get_access_token() - - return self._access_token - - def __get_access_token(self) -> str: - jwt = self.__generate_jwt() - resp = requests.post( - self.token_uri, - data={ - "assertion": jwt, - "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", - }, - ) - return resp.json()["access_token"] diff --git a/airbyte-ci/connectors/ci_credentials/ci_credentials/logger.py b/airbyte-ci/connectors/ci_credentials/ci_credentials/logger.py deleted file mode 100644 index 639a38e465b0..000000000000 --- a/airbyte-ci/connectors/ci_credentials/ci_credentials/logger.py +++ /dev/null @@ -1,85 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import datetime as dt -import inspect -import logging -import logging.handlers -import sys -from typing import Callable - - -class MyFormatter(logging.Formatter): - """Custom formatter for logging""" - - converter = dt.datetime.fromtimestamp - - def formatTime(self, record, datefmt=None): - """! @brief redefinition of format of log""" - ct = self.converter(record.created) - if datefmt: - s = ct.strftime(datefmt) - else: - t = ct.strftime("%Y-%m-%d %H:%M:%S") - s = "%s,%03d" % (t, record.msecs) - return s - - -class Logger: - """Simple logger with a pretty log header - the method error returns the value 1 - the method critical terminates a script work - """ - - def __init__(self): - formatter = MyFormatter(fmt="[%(asctime)s] - %(levelname)s - %(message)s", datefmt="%d/%m/%Y %H:%M:%S.%f") - - logger_name = __name__ - stack_items = inspect.stack() - for i in range(len(stack_items)): - if stack_items[i].filename.endswith("ci_credentials/logger.py"): - logger_name = ".".join(stack_items[i + 1].filename.split("/")[-3:])[:-3] - - self._logger = logging.getLogger(logger_name) - self._logger.setLevel(logging.DEBUG) - self._logger.propagate = False - - handler = logging.StreamHandler() - handler.setLevel(logging.DEBUG) - handler.setFormatter(formatter) - self._logger.addHandler(handler) - - @classmethod - def __prepare_log_line(cls, func_name: str, func: Callable) -> Callable: - def wrapper(*args): - prefix = "" - stack_items = inspect.stack() - for i in range(len(stack_items)): - if stack_items[i].filename.endswith("ci_credentials/logger.py"): - filepath = stack_items[i + 1].filename - line_number = stack_items[i + 1].lineno - - # show last 3 path items only - filepath = "/".join(filepath.split("/")[-3:]) - prefix = f"[{filepath}:{line_number}] # " - break - if prefix: - args = list(args) - args[0] = f"{prefix}{args[0]}" - func(*args) - if func_name == "critical": - sys.exit(1) - elif func_name == "error": - return 1 - return 0 - - return wrapper - - def __getattr__(self, function_name: str): - if not hasattr(self._logger, function_name): - return super().__getattr__(function_name) - return self.__prepare_log_line( - function_name, - getattr(self._logger, function_name), - ) diff --git a/airbyte-ci/connectors/ci_credentials/ci_credentials/main.py b/airbyte-ci/connectors/ci_credentials/ci_credentials/main.py deleted file mode 100644 index fa1b3ade1df5..000000000000 --- a/airbyte-ci/connectors/ci_credentials/ci_credentials/main.py +++ /dev/null @@ -1,69 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import json -import sys -from json.decoder import JSONDecodeError - -import click - -from .logger import Logger -from .secrets_manager import SecretsManager - - -logger = Logger() - -ENV_GCP_GSM_CREDENTIALS = "GCP_GSM_CREDENTIALS" - - -# credentials of GSM and GitHub secrets should be shared via shell environment -@click.group() -@click.argument("connector_name") -@click.option("--gcp-gsm-credentials", envvar="GCP_GSM_CREDENTIALS") -@click.pass_context -def ci_credentials(ctx, connector_name: str, gcp_gsm_credentials): - ctx.ensure_object(dict) - ctx.obj["connector_name"] = connector_name - # parse unique connector name, because it can have the common prefix "connectors/" - connector_name = connector_name.split("/")[-1] - if connector_name == "all": - # if needed to load all secrets - connector_name = None - - # parse GCP_GSM_CREDENTIALS - try: - gsm_credentials = json.loads(gcp_gsm_credentials) if gcp_gsm_credentials else {} - except JSONDecodeError as e: - return logger.error(f"incorrect GCP_GSM_CREDENTIALS value, error: {e}") - - if not gsm_credentials: - return logger.error("GCP_GSM_CREDENTIALS shouldn't be empty!") - - secret_manager = SecretsManager( - connector_name=connector_name, - gsm_credentials=gsm_credentials, - ) - ctx.obj["secret_manager"] = secret_manager - ctx.obj["connector_secrets"] = secret_manager.read_from_gsm() - - -@ci_credentials.command(help="Download GSM secrets locally to the connector's secrets directory.") -@click.pass_context -def write_to_storage(ctx): - written_files = ctx.obj["secret_manager"].write_to_storage(ctx.obj["connector_secrets"]) - written_files_count = len(written_files) - click.echo(f"{written_files_count} secret files were written: {','.join([str(path) for path in written_files])}") - - -@ci_credentials.command(help="Update GSM secrets according to the content of the secrets/updated_configurations directory.") -@click.pass_context -def update_secrets(ctx): - new_remote_secrets = ctx.obj["secret_manager"].update_secrets(ctx.obj["connector_secrets"]) - updated_secret_names = [secret.name for secret in new_remote_secrets] - updated_secrets_count = len(new_remote_secrets) - click.echo(f"Updated {updated_secrets_count} secrets: {','.join(updated_secret_names)}") - - -if __name__ == "__main__": - sys.exit(ci_credentials(obj={})) diff --git a/airbyte-ci/connectors/ci_credentials/ci_credentials/models.py b/airbyte-ci/connectors/ci_credentials/ci_credentials/models.py deleted file mode 100644 index 84295b70de45..000000000000 --- a/airbyte-ci/connectors/ci_credentials/ci_credentials/models.py +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from __future__ import ( # Used to evaluate type hints at runtime, a NameError: name 'RemoteSecret' is not defined is thrown otherwise - annotations, -) - -from dataclasses import dataclass - - -DEFAULT_SECRET_FILE = "config" - - -@dataclass -class Secret: - connector_name: str - configuration_file_name: str - value: str - - @property - def name(self) -> str: - return self.generate_secret_name(self.connector_name, self.configuration_file_name) - - @staticmethod - def generate_secret_name(connector_name: str, configuration_file_name: str) -> str: - """ - Generates an unique GSM secret name. - Format of secret name: SECRET____CREDS - Examples: - 1. connector_name: source-linnworks, filename: dsdssds_a-b---_---_config.json - => SECRET_SOURCE-LINNWORKS_DSDSSDS_A-B__CREDS - 2. connector_name: source-s3, filename: config.json - => SECRET_SOURCE-LINNWORKS__CREDS - """ - name_parts = ["secret", connector_name] - filename_wo_ext = configuration_file_name.replace(".json", "") - if filename_wo_ext != DEFAULT_SECRET_FILE: - name_parts.append(filename_wo_ext.replace(DEFAULT_SECRET_FILE, "").strip("_-")) - name_parts.append("_creds") - return "_".join(name_parts).upper() - - @property - def directory(self) -> str: - if self.connector_name == "base-normalization": - return f"airbyte-integrations/bases/{self.connector_name}/secrets" - else: - return f"airbyte-integrations/connectors/{self.connector_name}/secrets" - - -@dataclass -class RemoteSecret(Secret): - enabled_version: str - - @classmethod - def from_secret(cls, secret: Secret, enabled_version: str) -> RemoteSecret: - return RemoteSecret(secret.connector_name, secret.configuration_file_name, secret.value, enabled_version) diff --git a/airbyte-ci/connectors/ci_credentials/ci_credentials/secrets_manager.py b/airbyte-ci/connectors/ci_credentials/ci_credentials/secrets_manager.py deleted file mode 100644 index d64cb201f621..000000000000 --- a/airbyte-ci/connectors/ci_credentials/ci_credentials/secrets_manager.py +++ /dev/null @@ -1,302 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import base64 -import json -import os -import re -from glob import glob -from json.decoder import JSONDecodeError -from pathlib import Path -from typing import Any, ClassVar, List, Mapping - -import requests -import yaml - -from .google_api import GoogleApi -from .logger import Logger -from .models import DEFAULT_SECRET_FILE, RemoteSecret, Secret - - -DEFAULT_SECRET_FILE_WITH_EXT = DEFAULT_SECRET_FILE + ".json" - -GSM_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) - -DEFAULT_MASK_KEY_PATTERNS = [ - "password", - "host", - "user", - "_key", - "_id", - "token", - "secret", - "bucket", - "role_arn", - "service_account_info", - "account_id", - "api", - "domain_url", - "client_id", - "access", - "jwt", - "base_url", - "key", - "credentials", - "_sid", - "survey_", - "appid", - "apikey", - "api_key", -] - - -class SecretsManager: - """Loading, saving and updating all requested secrets into connector folders""" - - SPEC_MASK_URL = "https://connectors.airbyte.com/files/registries/v0/specs_secrets_mask.yaml" - - logger: ClassVar[Logger] = Logger() - if os.getenv("VERSION") in ["dev", "dagger_ci"]: - base_folder = Path(os.getcwd()) - else: - base_folder = Path("/actions-runner/_work/airbyte/airbyte") - - def __init__(self, connector_name: str, gsm_credentials: Mapping[str, Any]): - self.gsm_credentials = gsm_credentials - self.connector_name = connector_name - self._api = None - - @property - def api(self) -> GoogleApi: - if self._api is None: - self._api = GoogleApi(self.gsm_credentials, GSM_SCOPES) - return self._api - - @property - def mask_key_patterns(self) -> List[str]: - return self._get_spec_mask() + DEFAULT_MASK_KEY_PATTERNS - - def __load_gsm_secrets(self) -> List[RemoteSecret]: - """Loads needed GSM secrets""" - secrets = [] - # docs: https://cloud.google.com/secret-manager/docs/filtering#api - filter = "name:SECRET_" - if self.connector_name: - filter += f" AND labels.connector={self.connector_name}" - url = f"https://secretmanager.googleapis.com/v1/projects/{self.api.project_id}/secrets" - next_token = None - while True: - params = { - "filter": filter, - } - if next_token: - params["pageToken"] = next_token - - all_secrets_data = self.api.get(url, params=params) - for secret_info in all_secrets_data.get("secrets") or []: - secret_name = secret_info["name"] - connector_name = secret_info.get("labels", {}).get("connector") - if not connector_name: - self.logger.warning(f"secret {secret_name} doesn't have the label 'connector'") - continue - elif self.connector_name and connector_name != self.connector_name: - self.logger.warning(f"incorrect the label connector '{connector_name}' of secret {secret_name}") - continue - filename = secret_info.get("labels", {}).get("filename") - if filename: - # all secret file names should be finished with ".json" - # but '.' cant be used in google, so we append it - filename = f"{filename}.json" - else: - # the "filename" label is optional. - filename = DEFAULT_SECRET_FILE_WITH_EXT - log_name = f'{secret_name.split("/")[-1]}({connector_name})' - self.logger.info(f"found GSM secret: {log_name} = > {filename}") - - versions_url = f"https://secretmanager.googleapis.com/v1/{secret_name}/versions" - versions_data = self.api.get(versions_url) - enabled_versions = [version["name"] for version in versions_data["versions"] if version["state"] == "ENABLED"] - if len(enabled_versions) > 1: - self.logger.critical(f"{log_name} should have one enabled version at the same time!!!") - if not enabled_versions: - self.logger.warning(f"{log_name} doesn't have enabled versions for {secret_name}") - continue - enabled_version = enabled_versions[0] - secret_url = f"https://secretmanager.googleapis.com/v1/{enabled_version}:access" - secret_data = self.api.get(secret_url) - secret_value = secret_data.get("payload", {}).get("data") - if not secret_value: - self.logger.warning(f"{log_name} has empty value") - continue - secret_value = base64.b64decode(secret_value.encode()).decode("utf-8") - try: - # minimize and validate its JSON value - json_value = json.loads(secret_value) - secret_value = json.dumps(json_value, separators=(",", ":")) - self.mask_secrets_from_action_log(None, json_value) - except JSONDecodeError as err: - self.logger.error(f"{log_name} has non-JSON value!!! Error: {err}") - continue - remote_secret = RemoteSecret(connector_name, filename, secret_value, enabled_version) - secrets.append(remote_secret) - - next_token = all_secrets_data.get("nextPageToken") - if not next_token: - break - - return secrets - - def mask_secrets_from_action_log(self, key, value): - # recursive masking of json based on leaf key - if not value: - return - elif isinstance(value, dict): - for child, item in value.items(): - self.mask_secrets_from_action_log(child, item) - elif isinstance(value, list): - for item in value: - self.mask_secrets_from_action_log(key, item) - else: - if key: - # regular value, check for what to mask - for pattern in self.mask_key_patterns: - if re.search(pattern, key): - self.logger.info(f"Add mask for key: {key}") - for line in str(value).splitlines(): - line = str(line).strip() - # don't output } and such - if len(line) > 1: - if not os.getenv("VERSION") in ["dev", "dagger_ci"]: - # has to be at the beginning of line for Github to notice it - print(f"::add-mask::{line}") - if os.getenv("VERSION") == "dagger_ci": - with open("/tmp/secrets_to_mask.txt", "a") as f: - f.write(f"{line}\n") - break - # see if it's really embedded json and get those values too - try: - json_value = json.loads(value) - self.mask_secrets_from_action_log(None, json_value) - except Exception: - # carry on - pass - - def read_from_gsm(self) -> List[RemoteSecret]: - """Reads all necessary secrets from different sources""" - secrets = self.__load_gsm_secrets() - if not len(secrets): - self.logger.warning(f"not found any secrets of the connector '{self.connector_name}'") - return [] - return secrets - - def write_to_storage(self, secrets: List[RemoteSecret]) -> List[Path]: - """Save target secrets to the airbyte-integrations/connectors|bases/{connector_name}/secrets folder - - Args: - secrets (List[RemoteSecret]): List of remote secret to write locally - - Returns: - List[Path]: List of paths were the secrets were written - """ - written_files = [] - for secret in secrets: - secrets_dir = self.base_folder / secret.directory - secrets_dir.mkdir(parents=True, exist_ok=True) - filepath = secrets_dir / secret.configuration_file_name - with open(filepath, "w") as file: - file.write(secret.value) - written_files.append(filepath) - return written_files - - def _create_new_secret_version(self, new_secret: Secret, old_secret: RemoteSecret) -> RemoteSecret: - """Create a new secret version from a new secret instance. Disable the previous secret version. - - Args: - new_secret (Secret): The new secret instance - old_secret (RemoteSecret): The old secret instance - - Returns: - RemoteSecret: The newly created remote secret instance - """ - secret_url = f"https://secretmanager.googleapis.com/v1/projects/{self.api.project_id}/secrets/{new_secret.name}:addVersion" - body = {"payload": {"data": base64.b64encode(new_secret.value.encode()).decode("utf-8")}} - new_version_response = self.api.post(secret_url, json=body) - self._disable_version(old_secret.enabled_version) - return RemoteSecret.from_secret(new_secret, enabled_version=new_version_response["name"]) - - def _disable_version(self, version_name: str) -> dict: - """Disable a GSM secret version - - Args: - version_name (str): Full name of the version (containing project id and secret name) - - Returns: - dict: API response - """ - disable_version_url = f"https://secretmanager.googleapis.com/v1/{version_name}:disable" - return self.api.post(disable_version_url) - - def _get_updated_secrets(self) -> List[Secret]: - """Find locally updated configurations files and return the most recent instance for each configuration file name. - - Returns: - List[Secret]: List of Secret instances parsed from local updated configuration files - """ - updated_configurations_glob = ( - f"{str(self.base_folder)}/airbyte-integrations/connectors/{self.connector_name}/secrets/updated_configurations/*.json" - ) - updated_configuration_files_versions = {} - for updated_configuration_path in glob(updated_configurations_glob): - updated_configuration_path = Path(updated_configuration_path) - with open(updated_configuration_path, "r") as updated_configuration: - updated_configuration_value = json.load(updated_configuration) - configuration_original_file_name = f"{updated_configuration_path.stem.split('|')[0]}{updated_configuration_path.suffix}" - updated_configuration_files_versions.setdefault(configuration_original_file_name, []) - updated_configuration_files_versions[configuration_original_file_name].append( - (updated_configuration_value, os.path.getctime(str(updated_configuration_path))) - ) - - for updated_configurations in updated_configuration_files_versions.values(): - updated_configurations.sort(key=lambda x: x[1]) - return [ - Secret( - connector_name=self.connector_name, - configuration_file_name=configuration_file_name, - value=json.dumps(versions_by_creation_time[-1][0]), - ) - for configuration_file_name, versions_by_creation_time in updated_configuration_files_versions.items() - ] - - def update_secrets(self, existing_secrets: List[RemoteSecret]) -> List[RemoteSecret]: - """Update existing secrets if an updated version was found locally. - - Args: - existing_secrets (List[RemoteSecret]): List of existing secrets for the current connector on GSM. - - Returns: - List[RemoteSecret]: List of updated secrets as RemoteSecret instances - """ - existing_secrets = {secret.name: secret for secret in existing_secrets} - updated_secrets = {secret.name: secret for secret in self._get_updated_secrets()} - new_remote_secrets = [] - for existing_secret_name in existing_secrets: - if existing_secret_name in updated_secrets and json.loads(updated_secrets[existing_secret_name].value) != json.loads( - existing_secrets[existing_secret_name].value - ): - new_secret = updated_secrets[existing_secret_name] - old_secret = existing_secrets[existing_secret_name] - new_remote_secret = self._create_new_secret_version(new_secret, old_secret) - new_remote_secrets.append(new_remote_secret) - self.logger.info(f"Updated {new_remote_secret.name} with new value") - return new_remote_secrets - - def _get_spec_mask(self) -> List[str]: - response = requests.get(self.SPEC_MASK_URL, allow_redirects=True) - if not response.ok: - self.logger.error(f"Failed to fetch spec mask: {response.content}") - try: - return yaml.safe_load(response.content)["properties"] - except Exception as e: - self.logger.error(f"Failed to parse spec mask: {e}") - return [] diff --git a/airbyte-ci/connectors/ci_credentials/poetry.lock b/airbyte-ci/connectors/ci_credentials/poetry.lock deleted file mode 100644 index 06f2fac41604..000000000000 --- a/airbyte-ci/connectors/ci_credentials/poetry.lock +++ /dev/null @@ -1,507 +0,0 @@ -# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. - -[[package]] -name = "certifi" -version = "2025.1.31" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -groups = ["main", "dev"] -files = [ - {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, - {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, -] - -[[package]] -name = "cffi" -version = "1.17.1" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "platform_python_implementation != \"PyPy\"" -files = [ - {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, - {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, - {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, - {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, - {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, - {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, - {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, - {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, - {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, - {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, - {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, - {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, - {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, - {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, - {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, - {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, -] - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "charset-normalizer" -version = "3.4.1" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -files = [ - {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, - {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, - {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, -] - -[[package]] -name = "click" -version = "8.1.8" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, - {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main", "dev"] -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] -markers = {main = "platform_system == \"Windows\"", dev = "sys_platform == \"win32\""} - -[[package]] -name = "cryptography" -version = "44.0.0" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false -python-versions = "!=3.9.0,!=3.9.1,>=3.7" -groups = ["main"] -files = [ - {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, - {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, - {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, - {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, - {file = "cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd"}, - {file = "cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, - {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, - {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, - {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, - {file = "cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37d76e6863da3774cd9db5b409a9ecfd2c71c981c38788d3fcfaf177f447b731"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:f677e1268c4e23420c3acade68fac427fffcb8d19d7df95ed7ad17cdef8404f4"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f5e7cb1e5e56ca0933b4873c0220a78b773b24d40d186b6738080b73d3d0a756"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:be4ce505894d15d5c5037167ffb7f0ae90b7be6f2a98f9a5c3442395501c32fa"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c"}, - {file = "cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02"}, -] - -[package.dependencies] -cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] -docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] -pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] -sdist = ["build (>=1.0.0)"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] -test-randomorder = ["pytest-randomly"] - -[[package]] -name = "idna" -version = "3.10" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.6" -groups = ["main", "dev"] -files = [ - {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, - {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, -] - -[package.extras] -all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - -[[package]] -name = "packaging" -version = "24.2" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, - {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, -] - -[[package]] -name = "pluggy" -version = "1.5.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "platform_python_implementation != \"PyPy\"" -files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, -] - -[[package]] -name = "pyjwt" -version = "2.8.0" -description = "JSON Web Token implementation in Python" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, - {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, -] - -[package.extras] -crypto = ["cryptography (>=3.4.0)"] -dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] -docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] - -[[package]] -name = "pytest" -version = "8.3.4" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, - {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=1.5,<2" - -[package.extras] -dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "pyyaml" -version = "6.0.2" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, - {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, - {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, - {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, - {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, - {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, - {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, - {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, - {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, - {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, - {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, - {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, - {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, - {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, - {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, - {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, - {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, -] - -[[package]] -name = "requests" -version = "2.32.3" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, - {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "requests-mock" -version = "1.12.1" -description = "Mock out responses from the requests package" -optional = false -python-versions = ">=3.5" -groups = ["dev"] -files = [ - {file = "requests-mock-1.12.1.tar.gz", hash = "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401"}, - {file = "requests_mock-1.12.1-py2.py3-none-any.whl", hash = "sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563"}, -] - -[package.dependencies] -requests = ">=2.22,<3" - -[package.extras] -fixture = ["fixtures"] - -[[package]] -name = "urllib3" -version = "2.3.0" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.9" -groups = ["main", "dev"] -files = [ - {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, - {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[metadata] -lock-version = "2.1" -python-versions = "^3.11" -content-hash = "b9b62c5c060b4e57a4bebfee356c8c2c9f1bef3b9cd75d78fd1dccdf9e2e2212" diff --git a/airbyte-ci/connectors/ci_credentials/pyproject.toml b/airbyte-ci/connectors/ci_credentials/pyproject.toml deleted file mode 100644 index d7d85b6974cf..000000000000 --- a/airbyte-ci/connectors/ci_credentials/pyproject.toml +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -[tool.poetry] -name = "ci_credentials" -version = "1.2.1" -description = "CLI tooling to read and manage GSM secrets" -authors = ["Airbyte "] -readme = "README.md" -packages = [{ include = "ci_credentials" }] - -[tool.poetry.dependencies] -python = "^3.11" -requests = "^2.31" -cryptography = ">=42.0" -click = "^8.1.3" -pyyaml = "^6.0" -pyjwt = "2.8.0" - -[tool.poetry.group.dev.dependencies] -requests-mock = "^1.10.0" -pytest = "^8" - -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" - -[tool.poetry.scripts] -ci_credentials = "ci_credentials.main:ci_credentials" - -[tool.poe.tasks] -test = "pytest tests --config-file=./pyproject.toml" - -[tool.airbyte_ci] -python_versions = ["3.11"] -optional_poetry_groups = ["dev"] -poe_tasks = ["test"] diff --git a/airbyte-ci/connectors/ci_credentials/tests/__init__.py b/airbyte-ci/connectors/ci_credentials/tests/__init__.py deleted file mode 100644 index f70ecfc3a89e..000000000000 --- a/airbyte-ci/connectors/ci_credentials/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. diff --git a/airbyte-ci/connectors/ci_credentials/tests/test_models.py b/airbyte-ci/connectors/ci_credentials/tests/test_models.py deleted file mode 100644 index dd3b749b53d2..000000000000 --- a/airbyte-ci/connectors/ci_credentials/tests/test_models.py +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import pytest -from ci_credentials.models import Secret - - -@pytest.mark.parametrize( - "connector_name,filename,expected_name, expected_directory", - ( - ("source-default", "config.json", "SECRET_SOURCE-DEFAULT__CREDS", "airbyte-integrations/connectors/source-default/secrets"), - ( - "source-custom-filename-1", - "config_custom.json", - "SECRET_SOURCE-CUSTOM-FILENAME-1_CUSTOM__CREDS", - "airbyte-integrations/connectors/source-custom-filename-1/secrets", - ), - ( - "source-custom-filename-2", - "auth.json", - "SECRET_SOURCE-CUSTOM-FILENAME-2_AUTH__CREDS", - "airbyte-integrations/connectors/source-custom-filename-2/secrets", - ), - ( - "source-custom-filename-3", - "config_auth-test---___---config.json", - "SECRET_SOURCE-CUSTOM-FILENAME-3_AUTH-TEST__CREDS", - "airbyte-integrations/connectors/source-custom-filename-3/secrets", - ), - ( - "source-custom-filename-4", - "_____config_test---config.json", - "SECRET_SOURCE-CUSTOM-FILENAME-4_TEST__CREDS", - "airbyte-integrations/connectors/source-custom-filename-4/secrets", - ), - ( - "base-normalization", - "_____config_test---config.json", - "SECRET_BASE-NORMALIZATION_TEST__CREDS", - "airbyte-integrations/bases/base-normalization/secrets", - ), - ), -) -def test_secret_instantiation(connector_name, filename, expected_name, expected_directory): - secret = Secret(connector_name, filename, "secret_value") - assert secret.name == expected_name - assert secret.directory == expected_directory diff --git a/airbyte-ci/connectors/ci_credentials/tests/test_secrets_manager.py b/airbyte-ci/connectors/ci_credentials/tests/test_secrets_manager.py deleted file mode 100644 index 87c698e5ee6b..000000000000 --- a/airbyte-ci/connectors/ci_credentials/tests/test_secrets_manager.py +++ /dev/null @@ -1,209 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import base64 -import json -import re -from unittest.mock import patch - -import pytest -import requests_mock -from ci_credentials import SecretsManager -from ci_credentials.models import RemoteSecret, Secret - - -@pytest.fixture -def matchers(): - return { - "secrets": re.compile("https://secretmanager.googleapis.com/v1/projects/.+/secrets"), - "versions": re.compile("https://secretmanager.googleapis.com/v1/.+/versions"), - "addVersion": re.compile("https://secretmanager.googleapis.com/v1/.+:addVersion"), - "access": re.compile("https://secretmanager.googleapis.com/v1/.+/1:access"), - "disable": re.compile("https://secretmanager.googleapis.com/v1/.+:disable"), - "spec_secret_mask": re.compile("https://connectors.airbyte.com/files/registries/v0/specs_secrets_mask.yaml"), - } - - -@pytest.mark.parametrize( - "connector_name,gsm_secrets,expected_secrets", - ( - ( - "source-gsm-only", - { - "config": {"test_key": "test_value"}, - "config_oauth": {"test_key_1": "test_key_2"}, - }, - [ - RemoteSecret( - "source-gsm-only", - "config.json", - '{"test_key":"test_value"}', - "projects//secrets/SECRET_SOURCE-GSM-ONLY_0_CREDS/versions/1", - ), - RemoteSecret( - "source-gsm-only", - "config_oauth.json", - '{"test_key_1":"test_key_2"}', - "projects//secrets/SECRET_SOURCE-GSM-ONLY_1_CREDS/versions/1", - ), - ], - ), - ), - ids=[ - "gsm_only", - ], -) -@patch("ci_credentials.google_api.GoogleApi.get_access_token", lambda *args: ("fake_token", None)) -@patch("ci_credentials.google_api.GoogleApi.project_id", "fake_id") -def test_read(matchers, connector_name, gsm_secrets, expected_secrets): - secrets_list = { - "secrets": [ - { - "name": f"projects//secrets/SECRET_{connector_name.upper()}_{i}_CREDS", - "labels": { - "filename": k, - "connector": connector_name, - }, - } - for i, k in enumerate(gsm_secrets) - ] - } - - versions_response_list = [ - { - "json": { - "versions": [ - { - "name": f"projects//secrets/SECRET_{connector_name.upper()}_{i}_CREDS/versions/1", - "state": "ENABLED", - } - ] - } - } - for i in range(len(gsm_secrets)) - ] - - secrets_response_list = [ - {"json": {"payload": {"data": base64.b64encode(json.dumps(v).encode()).decode("utf-8")}}} for v in gsm_secrets.values() - ] - - manager = SecretsManager(connector_name=connector_name, gsm_credentials={}) - with requests_mock.Mocker() as m: - m.get(matchers["secrets"], json=secrets_list) - m.post(matchers["secrets"], json={"name": ""}) - m.get(matchers["versions"], versions_response_list) - m.get(matchers["access"], secrets_response_list) - m.get(matchers["spec_secret_mask"], json={"spec_secret_mask": "test"}) - - secrets = manager.read_from_gsm() - assert secrets == expected_secrets - - -@pytest.mark.parametrize( - "connector_name,secrets,expected_files", - ( - ( - "source-test", - [Secret("source-test", "test_config.json", "test_value")], - ["airbyte-integrations/connectors/source-test/secrets/test_config.json"], - ), - ( - "source-test2", - [Secret("source-test2", "test.json", "test_value"), Secret("source-test2", "auth.json", "test_auth")], - [ - "airbyte-integrations/connectors/source-test2/secrets/test.json", - "airbyte-integrations/connectors/source-test2/secrets/auth.json", - ], - ), - ( - "base-normalization", - [Secret("base-normalization", "test.json", "test_value"), Secret("base-normalization", "auth.json", "test_auth")], - [ - "airbyte-integrations/bases/base-normalization/secrets/test.json", - "airbyte-integrations/bases/base-normalization/secrets/auth.json", - ], - ), - ( - "source-no-secret", - [], - [], - ), - ), -) -def test_write(tmp_path, connector_name, secrets, expected_files): - manager = SecretsManager(connector_name=connector_name, gsm_credentials={}) - manager.base_folder = tmp_path - written_files = manager.write_to_storage(secrets) - for expected_file in expected_files: - target_file = tmp_path / expected_file - assert target_file.exists() - assert target_file in written_files - has = False - for secret in secrets: - if target_file.name == secret.configuration_file_name: - with open(target_file, "r") as f: - assert f.read() == secret.value - has = True - break - assert has, f"incorrect file data: {target_file}" - - -@pytest.mark.parametrize( - "connector_name,dict_json_value,expected_secret", - ( - ("source-default", '{"org_id": 111}', "::add-mask::111"), - ("source-default", '{"org": 111}', ""), - ), -) -def test_validate_mask_values(connector_name, dict_json_value, expected_secret, capsys): - manager = SecretsManager(connector_name=connector_name, gsm_credentials={}) - json_value = json.loads(dict_json_value) - manager.mask_secrets_from_action_log(None, json_value) - assert expected_secret in capsys.readouterr().out - - -@patch("ci_credentials.google_api.GoogleApi.get_access_token", lambda *args: ("fake_token", None)) -@patch("ci_credentials.google_api.GoogleApi.project_id", "fake_id") -@pytest.mark.parametrize( - "old_secret_value, updated_configurations", - [ - (json.dumps({"key": "value"}), [json.dumps({"key": "new_value_1"}), json.dumps({"key": "new_value_2"})]), - (json.dumps({"key": "value"}), [json.dumps({"key": "value"})]), - ], -) -def test_update_secrets(tmp_path, matchers, old_secret_value, updated_configurations): - existing_secret = RemoteSecret("source-test", "config.json", old_secret_value, "previous_version") - existing_secrets = [existing_secret] - - manager = SecretsManager(connector_name="source-test", gsm_credentials={}) - manager.base_folder = tmp_path - updated_configuration_directory = tmp_path / "airbyte-integrations/connectors/source-test/secrets/updated_configurations" - updated_configuration_directory.mkdir(parents=True) - - for i, updated_configuration in enumerate(updated_configurations): - stem, ext = existing_secret.configuration_file_name.split(".") - updated_configuration_file_name = f"{stem}|{i}.{ext}" - updated_configuration_path = updated_configuration_directory / updated_configuration_file_name - with open(updated_configuration_path, "w") as f: - f.write(updated_configuration) - - with requests_mock.Mocker() as m: - add_version_adapter = m.post(matchers["addVersion"], json={"name": "new_version"}) - disable_version_adapter = m.post(matchers["disable"], json={}) - updated_secrets = manager.update_secrets(existing_secrets) - - if old_secret_value != updated_configurations[-1]: - # We confirm the new version was created from the latest updated_configuration value - for secret in updated_secrets: - assert secret.connector_name == "source-test" - assert secret.configuration_file_name == "config.json" - assert secret.value == updated_configurations[-1] - assert secret.enabled_version == "new_version" - expected_add_version_payload = {"payload": {"data": base64.b64encode(updated_configurations[-1].encode()).decode("utf-8")}} - assert add_version_adapter.last_request.json() == expected_add_version_payload - assert disable_version_adapter.called_once - else: - assert not updated_secrets - assert not add_version_adapter.called - assert not disable_version_adapter.called diff --git a/airbyte-ci/connectors/connector_ops/README.md b/airbyte-ci/connectors/connector_ops/README.md deleted file mode 100644 index b8d2e0fd20de..000000000000 --- a/airbyte-ci/connectors/connector_ops/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# connector_ops - -A collection of utilities for working with Airbyte connectors. - -# Setup - -## Installation - -`connector_ops` tools use [Poetry](https://github.com/python-poetry/poetry) to manage dependencies, -and targets Python 3.11 and higher. - -Assuming you're in Airbyte repo root: - -```bash -cd airbyte-ci/connectors/connector_ops -poetry install -``` - -## Usage - -Connector OPS package provides useful `Connector` class and helper methods. It's used in several Airbyte CI packages. - -## Contributing to `connector_ops` - -### Running tests - -To run tests locally: - -```bash -poetry run pytest -``` - -## Changelog -- 0.10.2: Update Python version requirement from 3.10 to 3.11. -- 0.10.1: Update to `ci_credentials` 1.2.0, which drops `common_utils`. -- 0.10.0: Add `documentation_file_name` property to `Connector` class. -- 0.9.0: Add components path attribute for manifest-only connectors. -- 0.8.1: Gradle dependency discovery logic supports the Bulk CDK. -- 0.8.0: Add a `sbom_url` property to `Connector` -- 0.7.0: Added required reviewers for manifest-only connector changes/additions. -- 0.6.1: Simplified gradle dependency discovery logic. -- 0.6.0: Added manifest-only build. -- 0.5.0: Added `cloud_usage` property to `Connector` class. -- 0.4.0: Removed acceptance test configuration and allowed hosts checks as they're not used. diff --git a/airbyte-ci/connectors/connector_ops/connector_ops/__init__.py b/airbyte-ci/connectors/connector_ops/connector_ops/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/connector_ops/connector_ops/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/connector_ops/connector_ops/utils.py b/airbyte-ci/connectors/connector_ops/connector_ops/utils.py deleted file mode 100644 index 32e03ebdbcf0..000000000000 --- a/airbyte-ci/connectors/connector_ops/connector_ops/utils.py +++ /dev/null @@ -1,793 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import functools -import json -import logging -import os -import re -from dataclasses import dataclass -from enum import Enum -from glob import glob -from pathlib import Path -from typing import List, Optional, Set, Tuple, Union - -import git -import requests -import yaml -from ci_credentials import SecretsManager -from pydash.collections import find -from pydash.objects import get -from rich.console import Console -from simpleeval import simple_eval - - -console = Console() - -DIFFED_BRANCH = os.environ.get("DIFFED_BRANCH", "origin/master") -OSS_CATALOG_URL = "https://connectors.airbyte.com/files/registries/v0/oss_registry.json" -CLOUD_CATALOG_URL = "https://connectors.airbyte.com/files/registries/v0/cloud_registry.json" -BASE_AIRBYTE_DOCS_URL = "https://docs.airbyte.com" -CONNECTOR_PATH_PREFIX = "airbyte-integrations/connectors" -SOURCE_CONNECTOR_PATH_PREFIX = CONNECTOR_PATH_PREFIX + "/source-" -DESTINATION_CONNECTOR_PATH_PREFIX = CONNECTOR_PATH_PREFIX + "/destination-" - -THIRD_PARTY_GLOB = "third-party" -THIRD_PARTY_CONNECTOR_PATH_PREFIX = CONNECTOR_PATH_PREFIX + f"/{THIRD_PARTY_GLOB}/" -SCAFFOLD_CONNECTOR_GLOB = "-scaffold-" - - -ACCEPTANCE_TEST_CONFIG_FILE_NAME = "acceptance-test-config.yml" -METADATA_FILE_NAME = "metadata.yaml" -AIRBYTE_DOCKER_REPO = "airbyte" -AIRBYTE_REPO_DIRECTORY_NAME = "airbyte" -GRADLE_PROJECT_RE_PATTERN = r"project\((['\"])(.+?)\1\)" -TEST_GRADLE_DEPENDENCIES = [ - "testImplementation", - "testCompileOnly", - "integrationTestJavaImplementation", - "performanceTestJavaImplementation", - "testFixturesCompileOnly", - "testFixturesImplementation", -] - - -def download_catalog(catalog_url): - response = requests.get(catalog_url) - response.raise_for_status() - return response.json() - - -OSS_CATALOG = download_catalog(OSS_CATALOG_URL) -MANIFEST_FILE_NAME = "manifest.yaml" -COMPONENTS_FILE_NAME = "components.py" -DOCKERFILE_FILE_NAME = "Dockerfile" -PYPROJECT_FILE_NAME = "pyproject.toml" -ICON_FILE_NAME = "icon.svg" -POETRY_LOCK_FILE_NAME = "poetry.lock" - -STRATEGIC_CONNECTOR_THRESHOLDS = { - "sl": 200, - "ql": 400, -} - -ALLOWED_HOST_THRESHOLD = { - "ql": 300, -} - - -class ConnectorInvalidNameError(Exception): - pass - - -class ConnectorVersionNotFound(Exception): - pass - - -def get_connector_name_from_path(path): - return path.split("/")[2] - - -def get_changed_metadata(diff_regex: Optional[str] = None) -> Set[str]: - """Retrieve the set of connectors for which the metadata file was changed in the current branch (compared to master). - - Args: - diff_regex (str): Find the edited files that contain the following regex in their change. - - Returns: - Set[Connector]: Set of connectors that were changed - """ - return get_changed_file(METADATA_FILE_NAME, diff_regex) - - -def get_changed_file(file_name: str, diff_regex: Optional[str] = None) -> Set[str]: - """Retrieve the set of connectors for which the given file was changed in the current branch (compared to master). - - Args: - diff_regex (str): Find the edited files that contain the following regex in their change. - - Returns: - Set[Connector]: Set of connectors that were changed - """ - airbyte_repo = git.Repo(search_parent_directories=True) - - if diff_regex is None: - diff_command_args = ("--name-only", DIFFED_BRANCH) - else: - diff_command_args = ("--name-only", f"-G{diff_regex}", DIFFED_BRANCH) - - changed_acceptance_test_config_paths = { - file_path - for file_path in airbyte_repo.git.diff(*diff_command_args).split("\n") - if file_path.startswith(SOURCE_CONNECTOR_PATH_PREFIX) and file_path.endswith(file_name) - } - return {Connector(get_connector_name_from_path(changed_file)) for changed_file in changed_acceptance_test_config_paths} - - -def has_local_cdk_ref(build_file: Path) -> bool: - """Return true if the build file uses the local CDK. - - Args: - build_file (Path): Path to the build.gradle/build.gradle.kts file of the project. - - Returns: - bool: True if using local CDK. - """ - contents = "\n".join( - [ - # Return contents without inline code comments - line.split("//")[0] - for line in build_file.read_text().split("\n") - ] - ) - contents = contents.replace(" ", "") - return "useLocalCdk=true" in contents - - -def get_gradle_dependencies_block(build_file: Path) -> str: - """Get the dependencies block of a Gradle file. - - Args: - build_file (Path): Path to the build.gradle/build.gradle.kts file of the project. - - Returns: - str: The dependencies block of the Gradle file. - """ - contents = build_file.read_text().split("\n") - dependency_block = [] - in_dependencies_block = False - for line in contents: - if line.strip().startswith("dependencies"): - in_dependencies_block = True - continue - if in_dependencies_block: - if line.startswith("}"): - in_dependencies_block = False - break - else: - dependency_block.append(line) - dependencies_block = "\n".join(dependency_block) - return dependencies_block - - -def parse_gradle_dependencies(build_file: Path) -> Tuple[List[Path], List[Path]]: - """Parse the dependencies block of a Gradle file and return the list of project dependencies and test dependencies. - - Args: - build_file (Path): _description_ - - Returns: - Tuple[List[Tuple[str, Path]], List[Tuple[str, Path]]]: _description_ - """ - - dependencies_block = get_gradle_dependencies_block(build_file) - - project_dependencies: List[Path] = [] - test_dependencies: List[Path] = [] - - # Find all matches for test dependencies and regular dependencies - matches = re.findall( - r"(compileOnly|testCompileOnly|testFixturesCompileOnly|testFixturesImplementation|testImplementation|integrationTestJavaImplementation|performanceTestJavaImplementation|implementation|api).*?project\(['\"](.*?)['\"]\)", - dependencies_block, - ) - if matches: - # Iterate through each match - for match in matches: - dependency_type, project_path = match - path_parts = project_path.split(":") - path = Path(*path_parts) - - if dependency_type in TEST_GRADLE_DEPENDENCIES: - test_dependencies.append(path) - else: - project_dependencies.append(path) - - # Dedupe dependencies: - project_dependencies = list(set(project_dependencies)) - test_dependencies = list(set(test_dependencies)) - - return project_dependencies, test_dependencies - - -def get_all_gradle_dependencies( - build_file: Path, with_test_dependencies: bool = True, found_dependencies: Optional[List[Path]] = None -) -> List[Path]: - """Recursively retrieve all transitive dependencies of a Gradle project. - - Args: - build_file (Path): Path to the build.gradle/build.gradle.kts file of the project. - found_dependencies (List[Path]): List of dependencies that have already been found. Defaults to None. - - Returns: - List[Path]: All dependencies of the project. - """ - if found_dependencies is None: - found_dependencies = [] - project_dependencies, test_dependencies = parse_gradle_dependencies(build_file) - all_dependencies = project_dependencies + test_dependencies if with_test_dependencies else project_dependencies - valid_build_files = ["build.gradle", "build.gradle.kts"] - for dependency_path in all_dependencies: - for build_file in valid_build_files: - if dependency_path not in found_dependencies and Path(dependency_path / build_file).exists(): - found_dependencies.append(dependency_path) - get_all_gradle_dependencies(dependency_path / build_file, with_test_dependencies, found_dependencies) - - return found_dependencies - - -class ConnectorLanguage(str, Enum): - PYTHON = "python" - JAVA = "java" - LOW_CODE = "low-code" - MANIFEST_ONLY = "manifest-only" - - -class ConnectorLanguageError(Exception): - pass - - -@dataclass(frozen=True) -class Connector: - """Utility class to gather metadata about a connector.""" - - # Path to the connector directory relative to the CONNECTOR_PATH_PREFIX - # e.g source-google-sheets or third-party/farosai/airbyte-pagerduty-source - relative_connector_path: str - - def _get_type_and_name_from_technical_name(self) -> Tuple[str, str]: - if "-" not in self.technical_name: - raise ConnectorInvalidNameError(f"Connector type and name could not be inferred from {self.technical_name}") - _type = self.technical_name.split("-")[0] - name = self.technical_name[len(_type) + 1 :] - return _type, name - - @property - def technical_name(self) -> str: - """ - Return the technical name of the connector from the given relative_connector_path - e.g. source-google-sheets -> source-google-sheets or third-party/farosai/airbyte-pagerduty-source -> airbyte-pagerduty-source - """ - return self.relative_connector_path.split("/")[-1] - - @property - def name(self): - return self._get_type_and_name_from_technical_name()[1] - - @property - def connector_type(self) -> str: - return self.metadata["connectorType"] if self.metadata else None - - @property - def is_third_party(self) -> bool: - return THIRD_PARTY_GLOB in self.relative_connector_path - - @property - def has_airbyte_docs(self) -> bool: - return ( - self.metadata - and self.metadata.get("documentationUrl") is not None - and BASE_AIRBYTE_DOCS_URL in str(self.metadata.get("documentationUrl")) - ) - - @property - def local_connector_documentation_directory(self) -> Path: - return Path(f"./docs/integrations/{self.connector_type}s") - - @property - def relative_documentation_path_str(self) -> str: - documentation_url = self.metadata["documentationUrl"] - relative_documentation_path = documentation_url.replace(BASE_AIRBYTE_DOCS_URL, "") - - # strip leading and trailing slashes - relative_documentation_path = relative_documentation_path.strip("/") - - return f"./docs/{relative_documentation_path}" - - @property - def documentation_file_name(self) -> str: - return self.metadata.get("documentationUrl").split("/")[-1] + ".md" - - @property - def documentation_file_path(self) -> Optional[Path]: - return Path(f"{self.relative_documentation_path_str}.md") if self.has_airbyte_docs else None - - @property - def inapp_documentation_file_path(self) -> Path: - if not self.has_airbyte_docs: - return None - - return Path(f"{self.relative_documentation_path_str}.inapp.md") - - @property - def migration_guide_file_name(self) -> str: - return f"{self.name}-migrations.md" - - @property - def migration_guide_file_path(self) -> Path: - return self.local_connector_documentation_directory / self.migration_guide_file_name - - @property - def icon_path(self) -> Path: - file_path = self.code_directory / ICON_FILE_NAME - return file_path - - @property - def code_directory(self) -> Path: - return Path(f"./{CONNECTOR_PATH_PREFIX}/{self.relative_connector_path}") - - @property - def python_source_dir_path(self) -> Path: - return self.code_directory / self.technical_name.replace("-", "_") - - @property - def _manifest_only_path(self) -> Path: - return self.code_directory / MANIFEST_FILE_NAME - - @property - def _manifest_low_code_path(self) -> Path: - return self.python_source_dir_path / MANIFEST_FILE_NAME - - @property - def manifest_path(self) -> Path: - if self._manifest_only_path.is_file(): - return self._manifest_only_path - - return self._manifest_low_code_path - - @property - def manifest_only_components_path(self) -> Path: - """Return the path to the components.py file of a manifest-only connector.""" - return self.code_directory / COMPONENTS_FILE_NAME - - @property - def has_dockerfile(self) -> bool: - return self.dockerfile_file_path.is_file() - - @property - def dockerfile_file_path(self) -> Path: - return self.code_directory / DOCKERFILE_FILE_NAME - - @property - def pyproject_file_path(self) -> Path: - return self.code_directory / PYPROJECT_FILE_NAME - - @property - def metadata_file_path(self) -> Path: - return self.code_directory / METADATA_FILE_NAME - - @property - def metadata(self) -> Optional[dict]: - file_path = self.metadata_file_path - if not file_path.is_file(): - return None - return yaml.safe_load((self.code_directory / METADATA_FILE_NAME).read_text())["data"] - - @property - def connector_spec_file_content(self) -> Optional[dict]: - """ - The spec source of truth is the actual output of the spec command, as connector can mutate their spec. - But this is the best effort approach at statically fetching a spec without running the command on the connector. - Which is "good enough" in some cases. - """ - yaml_spec = Path(self.python_source_dir_path / "spec.yaml") - json_spec = Path(self.python_source_dir_path / "spec.json") - - if yaml_spec.exists(): - return yaml.safe_load(yaml_spec.read_text()) - elif json_spec.exists(): - with open(json_spec) as f: - return json.load(f) - elif self.manifest_path.exists(): - return yaml.safe_load(self.manifest_path.read_text())["spec"] - - return None - - @property - def language(self) -> ConnectorLanguage: - if Path(self.code_directory / "manifest.yaml").is_file(): - return ConnectorLanguage.MANIFEST_ONLY - if Path(self.code_directory / self.technical_name.replace("-", "_") / "manifest.yaml").is_file(): - return ConnectorLanguage.LOW_CODE - if Path(self.code_directory / "setup.py").is_file() or Path(self.code_directory / "pyproject.toml").is_file(): - return ConnectorLanguage.PYTHON - if Path(self.code_directory / "src" / "main" / "java").exists() or Path(self.code_directory / "src" / "main" / "kotlin").exists(): - return ConnectorLanguage.JAVA - return None - - @property - def version(self) -> Optional[str]: - if self.metadata is None: - return self.version_in_dockerfile_label - return self.metadata["dockerImageTag"] - - @property - def version_in_dockerfile_label(self) -> Optional[str]: - if not self.has_dockerfile: - return None - with open(self.code_directory / "Dockerfile") as f: - for line in f: - if "io.airbyte.version" in line: - return line.split("=")[1].strip() - raise ConnectorVersionNotFound( - """ - Could not find the connector version from its Dockerfile. - The io.airbyte.version tag is missing. - """ - ) - - @property - def name_from_metadata(self) -> Optional[str]: - return self.metadata.get("name") if self.metadata else None - - @property - def support_level(self) -> Optional[str]: - return self.metadata.get("supportLevel") if self.metadata else None - - def metadata_query_match(self, query_string: str) -> bool: - """Evaluate a query string against the connector metadata. - - Based on the simpleeval library: - https://github.com/danthedeckie/simpleeval - - Examples - -------- - >>> connector.metadata_query_match("'s3' in data.name") - True - - >>> connector.metadata_query_match("data.supportLevel == 'certified'") - False - - >>> connector.metadata_query_match("data.ab_internal.ql >= 100") - True - - Args: - query_string (str): The query string to evaluate. - - Returns: - bool: True if the query string matches the connector metadata, False otherwise. - """ - try: - matches = simple_eval(query_string, names={"data": self.metadata}) - return bool(matches) - except Exception as e: - # Skip on error as we not all fields are present in all connectors. - logging.debug(f"Failed to evaluate query string {query_string} for connector {self.technical_name}, error: {e}") - return False - - @property - def ab_internal_sl(self) -> int: - """Airbyte Internal Field. - - More info can be found here: https://www.notion.so/Internal-Metadata-Fields-32b02037e7b244b7934214019d0b7cc9 - - Returns: - int: The value - """ - default_value = 100 - sl_value = get(self.metadata, "ab_internal.sl") - - if sl_value is None: - logging.warning( - f"Connector {self.technical_name} does not have a `ab_internal.sl` defined in metadata.yaml. Defaulting to {default_value}" - ) - return default_value - - return sl_value - - @property - def ab_internal_ql(self) -> int: - """Airbyte Internal Field. - - More info can be found here: https://www.notion.so/Internal-Metadata-Fields-32b02037e7b244b7934214019d0b7cc9 - - Returns: - int: The value - """ - default_value = 100 - ql_value = get(self.metadata, "ab_internal.ql") - - if ql_value is None: - logging.warning( - f"Connector {self.technical_name} does not have a `ab_internal.ql` defined in metadata.yaml. Defaulting to {default_value}" - ) - return default_value - - return ql_value - - @property - def is_strategic_connector(self) -> bool: - """Check if a connector qualifies as a strategic connector. - - Returns: - bool: True if the connector is a high value connector, False otherwise. - """ - if self.ab_internal_sl >= STRATEGIC_CONNECTOR_THRESHOLDS["sl"]: - return True - - if self.ab_internal_ql >= STRATEGIC_CONNECTOR_THRESHOLDS["ql"]: - return True - - return False - - @property - def requires_high_test_strictness_level(self) -> bool: - """Check if a connector requires high strictness CAT tests. - - Returns: - bool: True if the connector requires high test strictness level, False otherwise. - """ - return self.ab_internal_ql >= STRATEGIC_CONNECTOR_THRESHOLDS["ql"] - - @property - def requires_allowed_hosts_check(self) -> bool: - """Check if a connector requires allowed hosts. - - Returns: - bool: True if the connector requires allowed hosts, False otherwise. - """ - return self.ab_internal_ql >= ALLOWED_HOST_THRESHOLD["ql"] - - @property - def allowed_hosts(self) -> Optional[List[str]]: - return self.metadata.get("allowedHosts") if self.metadata else None - - @property - def suggested_streams(self) -> Optional[List[str]]: - return self.metadata.get("suggestedStreams") if self.metadata else None - - @property - def acceptance_test_config_path(self) -> Path: - return self.code_directory / ACCEPTANCE_TEST_CONFIG_FILE_NAME - - @property - def acceptance_test_config(self) -> Optional[dict]: - try: - with open(self.acceptance_test_config_path) as acceptance_test_config_file: - return yaml.safe_load(acceptance_test_config_file) - except FileNotFoundError: - logging.warning(f"No {ACCEPTANCE_TEST_CONFIG_FILE_NAME} file found for {self.technical_name}") - return None - - @property - def supports_normalization(self) -> bool: - return self.metadata and self.metadata.get("normalizationConfig") is not None - - @property - def normalization_repository(self) -> Optional[str]: - if self.supports_normalization: - return f"{self.metadata['normalizationConfig']['normalizationRepository']}" - - @property - def normalization_tag(self) -> Optional[str]: - if self.supports_normalization: - return f"{self.metadata['normalizationConfig']['normalizationTag']}" - - @property - def is_using_poetry(self) -> bool: - return Path(self.code_directory / "pyproject.toml").exists() - - @property - def registry_primary_key_field(self) -> str: - """ - The primary key field of the connector in the registry. - - example: - - source -> sourceDefinitionId - - destination -> destinationDefinitionId - """ - return f"{self.connector_type}DefinitionId" - - @property - def is_enabled_in_any_registry(self) -> bool: - """Check if the connector is enabled in the registry. - - Example: - - {registries: null} -> false - - {registries: {oss: {enabled: false }}} -> false - - {registries: {oss: {enabled: true }}} -> true - - {registries: {cloud: {enabled: true }}} -> true - - Returns: - bool: True if the connector is enabled, False otherwise. - """ - registries = self.metadata.get("registryOverrides") - if not registries: - return False - - for registry in registries.values(): - if registry.get("enabled"): - return True - - return False - - @property - def is_released(self) -> bool: - """Pull the the OSS registry and check if it the current definition ID and docker image tag are in the registry. - If there is a match it means the connector is released. - We use the OSS registry as the source of truth for released connectors as the cloud registry can be a subset of the OSS registry. - - Returns: - bool: True if the connector is released, False otherwise. - """ - metadata = self.metadata - registry = download_catalog(OSS_CATALOG_URL) - for connector in registry[f"{self.connector_type}s"]: - if ( - connector[self.registry_primary_key_field] == metadata["definitionId"] - and connector["dockerImageTag"] == metadata["dockerImageTag"] - ): - return True - return False - - @property - def cloud_usage(self) -> Optional[str]: - """Pull the cloud registry, check if the connector is in the registry and return the usage metrics. - - Returns: - Optional[str]: The usage metrics of the connector, could be one of ["low", "medium", "high"] or None if the connector is not in the registry. - """ - metadata = self.metadata - definition_id = metadata.get("definitionId") - cloud_registry = download_catalog(CLOUD_CATALOG_URL) - - all_connectors_of_type = cloud_registry[f"{self.connector_type}s"] - connector_entry = find(all_connectors_of_type, {self.registry_primary_key_field: definition_id}) - if not connector_entry: - return None - - return get(connector_entry, "generated.metrics.cloud.usage") - - @property - def sbom_url(self) -> Optional[str]: - """ - Fetches SBOM URL from the connector definition in the OSS registry, if it exists, None otherwise. - """ - metadata = self.metadata - definition_id = metadata.get("definitionId") - # We use the OSS registry as the source of truth for released connectors as the cloud registry can be a subset of the OSS registry. - oss_registry = download_catalog(OSS_CATALOG_URL) - - all_connectors_of_type = oss_registry[f"{self.connector_type}s"] - connector_entry = find(all_connectors_of_type, {self.registry_primary_key_field: definition_id}) - if not connector_entry: - return None - - return get(connector_entry, "generated.sbomUrl") - - @property - def image_address(self) -> str: - return f'{self.metadata["dockerRepository"]}:{self.metadata["dockerImageTag"]}' - - @property - def cdk_name(self) -> str | None: - try: - return [tag.split(":")[-1] for tag in self.metadata["tags"] if tag.startswith("cdk:")][0] - except IndexError: - return None - - @property - def base_image_address(self) -> str | None: - return self.metadata.get("connectorBuildOptions", {}).get("baseImage") - - @property - def uses_base_image(self) -> bool: - return self.base_image_address is not None - - @property - def base_image_version(self) -> str | None: - if not self.uses_base_image: - return None - return self.base_image_address.split(":")[1].split("@")[0] - - def get_secret_manager(self, gsm_credentials: str): - return SecretsManager(connector_name=self.technical_name, gsm_credentials=gsm_credentials) - - def __repr__(self) -> str: - return self.technical_name - - @functools.lru_cache(maxsize=2) - def get_local_dependency_paths(self, with_test_dependencies: bool = True) -> Set[Path]: - dependencies_paths = [] - build_script = "build.gradle" - if Path(self.code_directory / "build.gradle.kts").exists(): - build_script = "build.gradle.kts" - - if self.language == ConnectorLanguage.JAVA: - dependencies_paths += [Path("./airbyte-cdk/java/airbyte-cdk"), Path("./airbyte-cdk/bulk")] - dependencies_paths += get_all_gradle_dependencies( - self.code_directory / build_script, with_test_dependencies=with_test_dependencies - ) - return sorted(list(set(dependencies_paths))) - - -def get_changed_connectors( - modified_files: Optional[Set[Union[str, Path]]] = None, source: bool = True, destination: bool = True, third_party: bool = True -) -> Set[Connector]: - """Retrieve a set of Connectors that were changed in the current branch (compared to master).""" - if modified_files is None: - airbyte_repo = git.Repo(search_parent_directories=True) - modified_files = airbyte_repo.git.diff("--name-only", DIFFED_BRANCH).split("\n") - - prefix_to_check = [] - if source: - prefix_to_check.append(SOURCE_CONNECTOR_PATH_PREFIX) - if destination: - prefix_to_check.append(DESTINATION_CONNECTOR_PATH_PREFIX) - if third_party: - prefix_to_check.append(THIRD_PARTY_CONNECTOR_PATH_PREFIX) - - changed_source_connector_files = { - file_path - for file_path in modified_files - if any(file_path.startswith(prefix) for prefix in prefix_to_check) and SCAFFOLD_CONNECTOR_GLOB not in file_path - } - return {Connector(get_connector_name_from_path(changed_file)) for changed_file in changed_source_connector_files} - - -def _get_relative_connector_folder_name_from_metadata_path(metadata_file_path: str) -> str: - """Get the relative connector folder name from the metadata file path. - - Args: - metadata_file_path (Path): Path to the metadata file. - - Returns: - str: The relative connector folder name. - """ - # remove CONNECTOR_PATH_PREFIX and anything before - metadata_file_path = metadata_file_path.split(CONNECTOR_PATH_PREFIX)[-1] - - # remove metadata.yaml - metadata_file_path = metadata_file_path.replace(METADATA_FILE_NAME, "") - - # remove leading and trailing slashes - metadata_file_path = metadata_file_path.strip("/") - return metadata_file_path - - -def get_all_connectors_in_repo() -> Set[Connector]: - """Retrieve a set of all Connectors in the repo. - We globe the connectors folder for metadata.yaml files and construct Connectors from the directory name. - - Returns: - A set of Connectors. - """ - repo = git.Repo(search_parent_directories=True) - repo_path = repo.working_tree_dir - - return { - Connector(_get_relative_connector_folder_name_from_metadata_path(metadata_file)) - for metadata_file in glob(f"{repo_path}/{CONNECTOR_PATH_PREFIX}/**/metadata.yaml", recursive=True) - if SCAFFOLD_CONNECTOR_GLOB not in metadata_file - } - - -class ConnectorTypeEnum(str, Enum): - source = "source" - destination = "destination" - - -class SupportLevelEnum(str, Enum): - certified = "certified" - community = "community" - archived = "archived" diff --git a/airbyte-ci/connectors/connector_ops/poetry.lock b/airbyte-ci/connectors/connector_ops/poetry.lock deleted file mode 100644 index 3cd49bb7a480..000000000000 --- a/airbyte-ci/connectors/connector_ops/poetry.lock +++ /dev/null @@ -1,1454 +0,0 @@ -# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. - -[[package]] -name = "cachetools" -version = "5.5.1" -description = "Extensible memoizing collections and decorators" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "cachetools-5.5.1-py3-none-any.whl", hash = "sha256:b76651fdc3b24ead3c648bbdeeb940c1b04d365b38b4af66788f9ec4a81d42bb"}, - {file = "cachetools-5.5.1.tar.gz", hash = "sha256:70f238fbba50383ef62e55c6aff6d9673175fe59f7c6782c7a0b9e38f4a9df95"}, -] - -[[package]] -name = "certifi" -version = "2025.1.31" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, - {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, -] - -[[package]] -name = "cffi" -version = "1.17.1" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, - {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, - {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, - {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, - {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, - {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, - {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, - {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, - {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, - {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, - {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, - {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, - {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, - {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, - {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, - {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, -] - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "charset-normalizer" -version = "3.4.1" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, - {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, - {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, -] - -[[package]] -name = "ci-credentials" -version = "1.2.0" -description = "CLI tooling to read and manage GSM secrets" -optional = false -python-versions = "^3.11" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [] -develop = false - -[package.dependencies] -click = "^8.1.3" -cryptography = ">=42.0" -pyjwt = "2.8.0" -pyyaml = "^6.0" -requests = "^2.31" - -[package.source] -type = "directory" -url = "../ci_credentials" - -[[package]] -name = "click" -version = "8.1.8" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, - {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main", "dev"] -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] -markers = {main = "(python_version >= \"3.12\" or python_version == \"3.11\") and platform_system == \"Windows\"", dev = "(python_version >= \"3.12\" or python_version == \"3.11\") and sys_platform == \"win32\""} - -[[package]] -name = "cryptography" -version = "44.0.0" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false -python-versions = "!=3.9.0,!=3.9.1,>=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, - {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, - {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, - {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, - {file = "cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd"}, - {file = "cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, - {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, - {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, - {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, - {file = "cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37d76e6863da3774cd9db5b409a9ecfd2c71c981c38788d3fcfaf177f447b731"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:f677e1268c4e23420c3acade68fac427fffcb8d19d7df95ed7ad17cdef8404f4"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f5e7cb1e5e56ca0933b4873c0220a78b773b24d40d186b6738080b73d3d0a756"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:be4ce505894d15d5c5037167ffb7f0ae90b7be6f2a98f9a5c3442395501c32fa"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c"}, - {file = "cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02"}, -] - -[package.dependencies] -cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] -docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] -pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] -sdist = ["build (>=1.0.0)"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] -test-randomorder = ["pytest-randomly"] - -[[package]] -name = "deprecated" -version = "1.2.18" -description = "Python @deprecated decorator to deprecate old python classes, functions or methods." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "Deprecated-1.2.18-py2.py3-none-any.whl", hash = "sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec"}, - {file = "deprecated-1.2.18.tar.gz", hash = "sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d"}, -] - -[package.dependencies] -wrapt = ">=1.10,<2" - -[package.extras] -dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "setuptools", "tox"] - -[[package]] -name = "freezegun" -version = "1.5.1" -description = "Let your Python tests travel through time" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "freezegun-1.5.1-py3-none-any.whl", hash = "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1"}, - {file = "freezegun-1.5.1.tar.gz", hash = "sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9"}, -] - -[package.dependencies] -python-dateutil = ">=2.7" - -[[package]] -name = "gitdb" -version = "4.0.12" -description = "Git Object Database" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf"}, - {file = "gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571"}, -] - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[[package]] -name = "gitpython" -version = "3.1.44" -description = "GitPython is a Python library used to interact with Git repositories" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110"}, - {file = "gitpython-3.1.44.tar.gz", hash = "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269"}, -] - -[package.dependencies] -gitdb = ">=4.0.1,<5" - -[package.extras] -doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] -test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions"] - -[[package]] -name = "google-api-core" -version = "2.24.1" -description = "Google API client core library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "google_api_core-2.24.1-py3-none-any.whl", hash = "sha256:bc78d608f5a5bf853b80bd70a795f703294de656c096c0968320830a4bc280f1"}, - {file = "google_api_core-2.24.1.tar.gz", hash = "sha256:f8b36f5456ab0dd99a1b693a40a31d1e7757beea380ad1b38faaf8941eae9d8a"}, -] - -[package.dependencies] -google-auth = ">=2.14.1,<3.0.dev0" -googleapis-common-protos = ">=1.56.2,<2.0.dev0" -proto-plus = [ - {version = ">=1.25.0,<2.0.0dev", markers = "python_version >= \"3.13\""}, - {version = ">=1.22.3,<2.0.0dev", markers = "python_version < \"3.13\""}, -] -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" -requests = ">=2.18.0,<3.0.0.dev0" - -[package.extras] -async-rest = ["google-auth[aiohttp] (>=2.35.0,<3.0.dev0)"] -grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status (>=1.33.2,<2.0.dev0)", "grpcio-status (>=1.49.1,<2.0.dev0)"] -grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] -grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] - -[[package]] -name = "google-auth" -version = "2.38.0" -description = "Google Authentication Library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "google_auth-2.38.0-py2.py3-none-any.whl", hash = "sha256:e7dae6694313f434a2727bf2906f27ad259bae090d7aa896590d86feec3d9d4a"}, - {file = "google_auth-2.38.0.tar.gz", hash = "sha256:8285113607d3b80a3f1543b75962447ba8a09fe85783432a784fdeef6ac094c4"}, -] - -[package.dependencies] -cachetools = ">=2.0.0,<6.0" -pyasn1-modules = ">=0.2.1" -rsa = ">=3.1.4,<5" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] -enterprise-cert = ["cryptography", "pyopenssl"] -pyjwt = ["cryptography (>=38.0.3)", "pyjwt (>=2.0)"] -pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] -reauth = ["pyu2f (>=0.1.5)"] -requests = ["requests (>=2.20.0,<3.0.0.dev0)"] - -[[package]] -name = "google-cloud-core" -version = "2.4.1" -description = "Google Cloud API client core library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "google-cloud-core-2.4.1.tar.gz", hash = "sha256:9b7749272a812bde58fff28868d0c5e2f585b82f37e09a1f6ed2d4d10f134073"}, - {file = "google_cloud_core-2.4.1-py2.py3-none-any.whl", hash = "sha256:a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61"}, -] - -[package.dependencies] -google-api-core = ">=1.31.6,<2.0.dev0 || >2.3.0,<3.0.0dev" -google-auth = ">=1.25.0,<3.0dev" - -[package.extras] -grpc = ["grpcio (>=1.38.0,<2.0dev)", "grpcio-status (>=1.38.0,<2.0.dev0)"] - -[[package]] -name = "google-cloud-storage" -version = "2.19.0" -description = "Google Cloud Storage API client library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "google_cloud_storage-2.19.0-py2.py3-none-any.whl", hash = "sha256:aeb971b5c29cf8ab98445082cbfe7b161a1f48ed275822f59ed3f1524ea54fba"}, - {file = "google_cloud_storage-2.19.0.tar.gz", hash = "sha256:cd05e9e7191ba6cb68934d8eb76054d9be4562aa89dbc4236feee4d7d51342b2"}, -] - -[package.dependencies] -google-api-core = ">=2.15.0,<3.0.0dev" -google-auth = ">=2.26.1,<3.0dev" -google-cloud-core = ">=2.3.0,<3.0dev" -google-crc32c = ">=1.0,<2.0dev" -google-resumable-media = ">=2.7.2" -requests = ">=2.18.0,<3.0.0dev" - -[package.extras] -protobuf = ["protobuf (<6.0.0dev)"] -tracing = ["opentelemetry-api (>=1.1.0)"] - -[[package]] -name = "google-crc32c" -version = "1.6.0" -description = "A python wrapper of the C library 'Google CRC32C'" -optional = false -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "google_crc32c-1.6.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:5bcc90b34df28a4b38653c36bb5ada35671ad105c99cfe915fb5bed7ad6924aa"}, - {file = "google_crc32c-1.6.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:d9e9913f7bd69e093b81da4535ce27af842e7bf371cde42d1ae9e9bd382dc0e9"}, - {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a184243544811e4a50d345838a883733461e67578959ac59964e43cca2c791e7"}, - {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:236c87a46cdf06384f614e9092b82c05f81bd34b80248021f729396a78e55d7e"}, - {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebab974b1687509e5c973b5c4b8b146683e101e102e17a86bd196ecaa4d099fc"}, - {file = "google_crc32c-1.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:50cf2a96da226dcbff8671233ecf37bf6e95de98b2a2ebadbfdf455e6d05df42"}, - {file = "google_crc32c-1.6.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:f7a1fc29803712f80879b0806cb83ab24ce62fc8daf0569f2204a0cfd7f68ed4"}, - {file = "google_crc32c-1.6.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:40b05ab32a5067525670880eb5d169529089a26fe35dce8891127aeddc1950e8"}, - {file = "google_crc32c-1.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e4b426c3702f3cd23b933436487eb34e01e00327fac20c9aebb68ccf34117d"}, - {file = "google_crc32c-1.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51c4f54dd8c6dfeb58d1df5e4f7f97df8abf17a36626a217f169893d1d7f3e9f"}, - {file = "google_crc32c-1.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:bb8b3c75bd157010459b15222c3fd30577042a7060e29d42dabce449c087f2b3"}, - {file = "google_crc32c-1.6.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:ed767bf4ba90104c1216b68111613f0d5926fb3780660ea1198fc469af410e9d"}, - {file = "google_crc32c-1.6.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:62f6d4a29fea082ac4a3c9be5e415218255cf11684ac6ef5488eea0c9132689b"}, - {file = "google_crc32c-1.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c87d98c7c4a69066fd31701c4e10d178a648c2cac3452e62c6b24dc51f9fcc00"}, - {file = "google_crc32c-1.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd5e7d2445d1a958c266bfa5d04c39932dc54093fa391736dbfdb0f1929c1fb3"}, - {file = "google_crc32c-1.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:7aec8e88a3583515f9e0957fe4f5f6d8d4997e36d0f61624e70469771584c760"}, - {file = "google_crc32c-1.6.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:e2806553238cd076f0a55bddab37a532b53580e699ed8e5606d0de1f856b5205"}, - {file = "google_crc32c-1.6.0-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:bb0966e1c50d0ef5bc743312cc730b533491d60585a9a08f897274e57c3f70e0"}, - {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:386122eeaaa76951a8196310432c5b0ef3b53590ef4c317ec7588ec554fec5d2"}, - {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2952396dc604544ea7476b33fe87faedc24d666fb0c2d5ac971a2b9576ab871"}, - {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35834855408429cecf495cac67ccbab802de269e948e27478b1e47dfb6465e57"}, - {file = "google_crc32c-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:d8797406499f28b5ef791f339594b0b5fdedf54e203b5066675c406ba69d705c"}, - {file = "google_crc32c-1.6.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48abd62ca76a2cbe034542ed1b6aee851b6f28aaca4e6551b5599b6f3ef175cc"}, - {file = "google_crc32c-1.6.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18e311c64008f1f1379158158bb3f0c8d72635b9eb4f9545f8cf990c5668e59d"}, - {file = "google_crc32c-1.6.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05e2d8c9a2f853ff116db9706b4a27350587f341eda835f46db3c0a8c8ce2f24"}, - {file = "google_crc32c-1.6.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ca8145b060679ec9176e6de4f89b07363d6805bd4760631ef254905503598d"}, - {file = "google_crc32c-1.6.0.tar.gz", hash = "sha256:6eceb6ad197656a1ff49ebfbbfa870678c75be4344feb35ac1edf694309413dc"}, -] - -[package.extras] -testing = ["pytest"] - -[[package]] -name = "google-resumable-media" -version = "2.7.2" -description = "Utilities for Google Media Downloads and Resumable Uploads" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "google_resumable_media-2.7.2-py2.py3-none-any.whl", hash = "sha256:3ce7551e9fe6d99e9a126101d2536612bb73486721951e9562fee0f90c6ababa"}, - {file = "google_resumable_media-2.7.2.tar.gz", hash = "sha256:5280aed4629f2b60b847b0d42f9857fd4935c11af266744df33d8074cae92fe0"}, -] - -[package.dependencies] -google-crc32c = ">=1.0,<2.0dev" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)", "google-auth (>=1.22.0,<2.0dev)"] -requests = ["requests (>=2.18.0,<3.0.0dev)"] - -[[package]] -name = "googleapis-common-protos" -version = "1.66.0" -description = "Common protobufs used in Google APIs" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "googleapis_common_protos-1.66.0-py2.py3-none-any.whl", hash = "sha256:d7abcd75fabb2e0ec9f74466401f6c119a0b498e27370e9be4c94cb7e382b8ed"}, - {file = "googleapis_common_protos-1.66.0.tar.gz", hash = "sha256:c3e7b33d15fdca5374cc0a7346dd92ffa847425cc4ea941d970f13680052ec8c"}, -] - -[package.dependencies] -protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" - -[package.extras] -grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] - -[[package]] -name = "idna" -version = "3.10" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.6" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, - {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, -] - -[package.extras] -all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - -[[package]] -name = "markdown-it-py" -version = "3.0.0" -description = "Python port of markdown-it. Markdown parsing, done right!" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, - {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, -] - -[package.dependencies] -mdurl = ">=0.1,<1.0" - -[package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark"] -code-style = ["pre-commit (>=3.0,<4.0)"] -compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] -linkify = ["linkify-it-py (>=1,<3)"] -plugins = ["mdit-py-plugins"] -profiling = ["gprof2dot"] -rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] - -[[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, -] - -[[package]] -name = "numpy" -version = "2.2.2" -description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.10" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "numpy-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7079129b64cb78bdc8d611d1fd7e8002c0a2565da6a47c4df8062349fee90e3e"}, - {file = "numpy-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ec6c689c61df613b783aeb21f945c4cbe6c51c28cb70aae8430577ab39f163e"}, - {file = "numpy-2.2.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:40c7ff5da22cd391944a28c6a9c638a5eef77fcf71d6e3a79e1d9d9e82752715"}, - {file = "numpy-2.2.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:995f9e8181723852ca458e22de5d9b7d3ba4da3f11cc1cb113f093b271d7965a"}, - {file = "numpy-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b78ea78450fd96a498f50ee096f69c75379af5138f7881a51355ab0e11286c97"}, - {file = "numpy-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fbe72d347fbc59f94124125e73fc4976a06927ebc503ec5afbfb35f193cd957"}, - {file = "numpy-2.2.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8e6da5cffbbe571f93588f562ed130ea63ee206d12851b60819512dd3e1ba50d"}, - {file = "numpy-2.2.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:09d6a2032faf25e8d0cadde7fd6145118ac55d2740132c1d845f98721b5ebcfd"}, - {file = "numpy-2.2.2-cp310-cp310-win32.whl", hash = "sha256:159ff6ee4c4a36a23fe01b7c3d07bd8c14cc433d9720f977fcd52c13c0098160"}, - {file = "numpy-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:64bd6e1762cd7f0986a740fee4dff927b9ec2c5e4d9a28d056eb17d332158014"}, - {file = "numpy-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:642199e98af1bd2b6aeb8ecf726972d238c9877b0f6e8221ee5ab945ec8a2189"}, - {file = "numpy-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6d9fc9d812c81e6168b6d405bf00b8d6739a7f72ef22a9214c4241e0dc70b323"}, - {file = "numpy-2.2.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:c7d1fd447e33ee20c1f33f2c8e6634211124a9aabde3c617687d8b739aa69eac"}, - {file = "numpy-2.2.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:451e854cfae0febe723077bd0cf0a4302a5d84ff25f0bfece8f29206c7bed02e"}, - {file = "numpy-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd249bc894af67cbd8bad2c22e7cbcd46cf87ddfca1f1289d1e7e54868cc785c"}, - {file = "numpy-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02935e2c3c0c6cbe9c7955a8efa8908dd4221d7755644c59d1bba28b94fd334f"}, - {file = "numpy-2.2.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a972cec723e0563aa0823ee2ab1df0cb196ed0778f173b381c871a03719d4826"}, - {file = "numpy-2.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d6d6a0910c3b4368d89dde073e630882cdb266755565155bc33520283b2d9df8"}, - {file = "numpy-2.2.2-cp311-cp311-win32.whl", hash = "sha256:860fd59990c37c3ef913c3ae390b3929d005243acca1a86facb0773e2d8d9e50"}, - {file = "numpy-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:da1eeb460ecce8d5b8608826595c777728cdf28ce7b5a5a8c8ac8d949beadcf2"}, - {file = "numpy-2.2.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ac9bea18d6d58a995fac1b2cb4488e17eceeac413af014b1dd26170b766d8467"}, - {file = "numpy-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23ae9f0c2d889b7b2d88a3791f6c09e2ef827c2446f1c4a3e3e76328ee4afd9a"}, - {file = "numpy-2.2.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3074634ea4d6df66be04f6728ee1d173cfded75d002c75fac79503a880bf3825"}, - {file = "numpy-2.2.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:8ec0636d3f7d68520afc6ac2dc4b8341ddb725039de042faf0e311599f54eb37"}, - {file = "numpy-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ffbb1acd69fdf8e89dd60ef6182ca90a743620957afb7066385a7bbe88dc748"}, - {file = "numpy-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0349b025e15ea9d05c3d63f9657707a4e1d471128a3b1d876c095f328f8ff7f0"}, - {file = "numpy-2.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:463247edcee4a5537841d5350bc87fe8e92d7dd0e8c71c995d2c6eecb8208278"}, - {file = "numpy-2.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9dd47ff0cb2a656ad69c38da850df3454da88ee9a6fde0ba79acceee0e79daba"}, - {file = "numpy-2.2.2-cp312-cp312-win32.whl", hash = "sha256:4525b88c11906d5ab1b0ec1f290996c0020dd318af8b49acaa46f198b1ffc283"}, - {file = "numpy-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:5acea83b801e98541619af398cc0109ff48016955cc0818f478ee9ef1c5c3dcb"}, - {file = "numpy-2.2.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b208cfd4f5fe34e1535c08983a1a6803fdbc7a1e86cf13dd0c61de0b51a0aadc"}, - {file = "numpy-2.2.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d0bbe7dd86dca64854f4b6ce2ea5c60b51e36dfd597300057cf473d3615f2369"}, - {file = "numpy-2.2.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:22ea3bb552ade325530e72a0c557cdf2dea8914d3a5e1fecf58fa5dbcc6f43cd"}, - {file = "numpy-2.2.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:128c41c085cab8a85dc29e66ed88c05613dccf6bc28b3866cd16050a2f5448be"}, - {file = "numpy-2.2.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:250c16b277e3b809ac20d1f590716597481061b514223c7badb7a0f9993c7f84"}, - {file = "numpy-2.2.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0c8854b09bc4de7b041148d8550d3bd712b5c21ff6a8ed308085f190235d7ff"}, - {file = "numpy-2.2.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b6fb9c32a91ec32a689ec6410def76443e3c750e7cfc3fb2206b985ffb2b85f0"}, - {file = "numpy-2.2.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:57b4012e04cc12b78590a334907e01b3a85efb2107df2b8733ff1ed05fce71de"}, - {file = "numpy-2.2.2-cp313-cp313-win32.whl", hash = "sha256:4dbd80e453bd34bd003b16bd802fac70ad76bd463f81f0c518d1245b1c55e3d9"}, - {file = "numpy-2.2.2-cp313-cp313-win_amd64.whl", hash = "sha256:5a8c863ceacae696aff37d1fd636121f1a512117652e5dfb86031c8d84836369"}, - {file = "numpy-2.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b3482cb7b3325faa5f6bc179649406058253d91ceda359c104dac0ad320e1391"}, - {file = "numpy-2.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9491100aba630910489c1d0158034e1c9a6546f0b1340f716d522dc103788e39"}, - {file = "numpy-2.2.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:41184c416143defa34cc8eb9d070b0a5ba4f13a0fa96a709e20584638254b317"}, - {file = "numpy-2.2.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:7dca87ca328f5ea7dafc907c5ec100d187911f94825f8700caac0b3f4c384b49"}, - {file = "numpy-2.2.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bc61b307655d1a7f9f4b043628b9f2b721e80839914ede634e3d485913e1fb2"}, - {file = "numpy-2.2.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fad446ad0bc886855ddf5909cbf8cb5d0faa637aaa6277fb4b19ade134ab3c7"}, - {file = "numpy-2.2.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:149d1113ac15005652e8d0d3f6fd599360e1a708a4f98e43c9c77834a28238cb"}, - {file = "numpy-2.2.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:106397dbbb1896f99e044efc90360d098b3335060375c26aa89c0d8a97c5f648"}, - {file = "numpy-2.2.2-cp313-cp313t-win32.whl", hash = "sha256:0eec19f8af947a61e968d5429f0bd92fec46d92b0008d0a6685b40d6adf8a4f4"}, - {file = "numpy-2.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:97b974d3ba0fb4612b77ed35d7627490e8e3dff56ab41454d9e8b23448940576"}, - {file = "numpy-2.2.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b0531f0b0e07643eb089df4c509d30d72c9ef40defa53e41363eca8a8cc61495"}, - {file = "numpy-2.2.2-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:e9e82dcb3f2ebbc8cb5ce1102d5f1c5ed236bf8a11730fb45ba82e2841ec21df"}, - {file = "numpy-2.2.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0d4142eb40ca6f94539e4db929410f2a46052a0fe7a2c1c59f6179c39938d2a"}, - {file = "numpy-2.2.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:356ca982c188acbfa6af0d694284d8cf20e95b1c3d0aefa8929376fea9146f60"}, - {file = "numpy-2.2.2.tar.gz", hash = "sha256:ed6906f61834d687738d25988ae117683705636936cc605be0bb208b23df4d8f"}, -] - -[[package]] -name = "packaging" -version = "24.2" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, - {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, -] - -[[package]] -name = "pandas" -version = "2.2.3" -description = "Powerful data structures for data analysis, time series, and statistics" -optional = false -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5"}, - {file = "pandas-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348"}, - {file = "pandas-2.2.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d9c45366def9a3dd85a6454c0e7908f2b3b8e9c138f5dc38fed7ce720d8453ed"}, - {file = "pandas-2.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57"}, - {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b8661b0238a69d7aafe156b7fa86c44b881387509653fdf857bebc5e4008ad42"}, - {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f"}, - {file = "pandas-2.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645"}, - {file = "pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039"}, - {file = "pandas-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd"}, - {file = "pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698"}, - {file = "pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc"}, - {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3"}, - {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32"}, - {file = "pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5"}, - {file = "pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9"}, - {file = "pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4"}, - {file = "pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3"}, - {file = "pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319"}, - {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8"}, - {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a"}, - {file = "pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13"}, - {file = "pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015"}, - {file = "pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28"}, - {file = "pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0"}, - {file = "pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24"}, - {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659"}, - {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb"}, - {file = "pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d"}, - {file = "pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468"}, - {file = "pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18"}, - {file = "pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2"}, - {file = "pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4"}, - {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d"}, - {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a"}, - {file = "pandas-2.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc6b93f9b966093cb0fd62ff1a7e4c09e6d546ad7c1de191767baffc57628f39"}, - {file = "pandas-2.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5dbca4c1acd72e8eeef4753eeca07de9b1db4f398669d5994086f788a5d7cc30"}, - {file = "pandas-2.2.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8cd6d7cc958a3910f934ea8dbdf17b2364827bb4dafc38ce6eef6bb3d65ff09c"}, - {file = "pandas-2.2.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99df71520d25fade9db7c1076ac94eb994f4d2673ef2aa2e86ee039b6746d20c"}, - {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31d0ced62d4ea3e231a9f228366919a5ea0b07440d9d4dac345376fd8e1477ea"}, - {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7eee9e7cea6adf3e3d24e304ac6b8300646e2a5d1cd3a3c2abed9101b0846761"}, - {file = "pandas-2.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e"}, - {file = "pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667"}, -] - -[package.dependencies] -numpy = [ - {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, - {version = ">=1.23.2", markers = "python_version == \"3.11\""}, -] -python-dateutil = ">=2.8.2" -pytz = ">=2020.1" -tzdata = ">=2022.7" - -[package.extras] -all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] -aws = ["s3fs (>=2022.11.0)"] -clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] -compression = ["zstandard (>=0.19.0)"] -computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] -consortium-standard = ["dataframe-api-compat (>=0.1.7)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] -feather = ["pyarrow (>=10.0.1)"] -fss = ["fsspec (>=2022.11.0)"] -gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] -hdf5 = ["tables (>=3.8.0)"] -html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] -mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] -output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] -parquet = ["pyarrow (>=10.0.1)"] -performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] -plot = ["matplotlib (>=3.6.3)"] -postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] -pyarrow = ["pyarrow (>=10.0.1)"] -spss = ["pyreadstat (>=1.2.0)"] -sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] -test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] -xml = ["lxml (>=4.9.2)"] - -[[package]] -name = "pluggy" -version = "1.5.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "proto-plus" -version = "1.26.0" -description = "Beautiful, Pythonic protocol buffers" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "proto_plus-1.26.0-py3-none-any.whl", hash = "sha256:bf2dfaa3da281fc3187d12d224c707cb57214fb2c22ba854eb0c105a3fb2d4d7"}, - {file = "proto_plus-1.26.0.tar.gz", hash = "sha256:6e93d5f5ca267b54300880fff156b6a3386b3fa3f43b1da62e680fc0c586ef22"}, -] - -[package.dependencies] -protobuf = ">=3.19.0,<6.0.0dev" - -[package.extras] -testing = ["google-api-core (>=1.31.5)"] - -[[package]] -name = "protobuf" -version = "5.29.3" -description = "" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "protobuf-5.29.3-cp310-abi3-win32.whl", hash = "sha256:3ea51771449e1035f26069c4c7fd51fba990d07bc55ba80701c78f886bf9c888"}, - {file = "protobuf-5.29.3-cp310-abi3-win_amd64.whl", hash = "sha256:a4fa6f80816a9a0678429e84973f2f98cbc218cca434abe8db2ad0bffc98503a"}, - {file = "protobuf-5.29.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a8434404bbf139aa9e1300dbf989667a83d42ddda9153d8ab76e0d5dcaca484e"}, - {file = "protobuf-5.29.3-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:daaf63f70f25e8689c072cfad4334ca0ac1d1e05a92fc15c54eb9cf23c3efd84"}, - {file = "protobuf-5.29.3-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:c027e08a08be10b67c06bf2370b99c811c466398c357e615ca88c91c07f0910f"}, - {file = "protobuf-5.29.3-cp38-cp38-win32.whl", hash = "sha256:84a57163a0ccef3f96e4b6a20516cedcf5bb3a95a657131c5c3ac62200d23252"}, - {file = "protobuf-5.29.3-cp38-cp38-win_amd64.whl", hash = "sha256:b89c115d877892a512f79a8114564fb435943b59067615894c3b13cd3e1fa107"}, - {file = "protobuf-5.29.3-cp39-cp39-win32.whl", hash = "sha256:0eb32bfa5219fc8d4111803e9a690658aa2e6366384fd0851064b963b6d1f2a7"}, - {file = "protobuf-5.29.3-cp39-cp39-win_amd64.whl", hash = "sha256:6ce8cc3389a20693bfde6c6562e03474c40851b44975c9b2bf6df7d8c4f864da"}, - {file = "protobuf-5.29.3-py3-none-any.whl", hash = "sha256:0a18ed4a24198528f2333802eb075e59dea9d679ab7a6c5efb017a59004d849f"}, - {file = "protobuf-5.29.3.tar.gz", hash = "sha256:5da0f41edaf117bde316404bad1a486cb4ededf8e4a54891296f648e8e076620"}, -] - -[[package]] -name = "pyasn1" -version = "0.6.1" -description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"}, - {file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"}, -] - -[[package]] -name = "pyasn1-modules" -version = "0.4.1" -description = "A collection of ASN.1-based protocols modules" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd"}, - {file = "pyasn1_modules-0.4.1.tar.gz", hash = "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c"}, -] - -[package.dependencies] -pyasn1 = ">=0.4.6,<0.7.0" - -[[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, -] - -[[package]] -name = "pydantic" -version = "1.10.21" -description = "Data validation and settings management using python type hints" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "pydantic-1.10.21-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:245e486e0fec53ec2366df9cf1cba36e0bbf066af7cd9c974bbbd9ba10e1e586"}, - {file = "pydantic-1.10.21-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6c54f8d4c151c1de784c5b93dfbb872067e3414619e10e21e695f7bb84d1d1fd"}, - {file = "pydantic-1.10.21-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b64708009cfabd9c2211295144ff455ec7ceb4c4fb45a07a804309598f36187"}, - {file = "pydantic-1.10.21-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a148410fa0e971ba333358d11a6dea7b48e063de127c2b09ece9d1c1137dde4"}, - {file = "pydantic-1.10.21-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:36ceadef055af06e7756eb4b871cdc9e5a27bdc06a45c820cd94b443de019bbf"}, - {file = "pydantic-1.10.21-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0501e1d12df6ab1211b8cad52d2f7b2cd81f8e8e776d39aa5e71e2998d0379f"}, - {file = "pydantic-1.10.21-cp310-cp310-win_amd64.whl", hash = "sha256:c261127c275d7bce50b26b26c7d8427dcb5c4803e840e913f8d9df3f99dca55f"}, - {file = "pydantic-1.10.21-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8b6350b68566bb6b164fb06a3772e878887f3c857c46c0c534788081cb48adf4"}, - {file = "pydantic-1.10.21-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:935b19fdcde236f4fbf691959fa5c3e2b6951fff132964e869e57c70f2ad1ba3"}, - {file = "pydantic-1.10.21-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b6a04efdcd25486b27f24c1648d5adc1633ad8b4506d0e96e5367f075ed2e0b"}, - {file = "pydantic-1.10.21-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1ba253eb5af8d89864073e6ce8e6c8dec5f49920cff61f38f5c3383e38b1c9f"}, - {file = "pydantic-1.10.21-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:57f0101e6c97b411f287a0b7cf5ebc4e5d3b18254bf926f45a11615d29475793"}, - {file = "pydantic-1.10.21-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90e85834f0370d737c77a386ce505c21b06bfe7086c1c568b70e15a568d9670d"}, - {file = "pydantic-1.10.21-cp311-cp311-win_amd64.whl", hash = "sha256:6a497bc66b3374b7d105763d1d3de76d949287bf28969bff4656206ab8a53aa9"}, - {file = "pydantic-1.10.21-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2ed4a5f13cf160d64aa331ab9017af81f3481cd9fd0e49f1d707b57fe1b9f3ae"}, - {file = "pydantic-1.10.21-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3b7693bb6ed3fbe250e222f9415abb73111bb09b73ab90d2d4d53f6390e0ccc1"}, - {file = "pydantic-1.10.21-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185d5f1dff1fead51766da9b2de4f3dc3b8fca39e59383c273f34a6ae254e3e2"}, - {file = "pydantic-1.10.21-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38e6d35cf7cd1727822c79e324fa0677e1a08c88a34f56695101f5ad4d5e20e5"}, - {file = "pydantic-1.10.21-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:1d7c332685eafacb64a1a7645b409a166eb7537f23142d26895746f628a3149b"}, - {file = "pydantic-1.10.21-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c9b782db6f993a36092480eeaab8ba0609f786041b01f39c7c52252bda6d85f"}, - {file = "pydantic-1.10.21-cp312-cp312-win_amd64.whl", hash = "sha256:7ce64d23d4e71d9698492479505674c5c5b92cda02b07c91dfc13633b2eef805"}, - {file = "pydantic-1.10.21-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0067935d35044950be781933ab91b9a708eaff124bf860fa2f70aeb1c4be7212"}, - {file = "pydantic-1.10.21-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5e8148c2ce4894ce7e5a4925d9d3fdce429fb0e821b5a8783573f3611933a251"}, - {file = "pydantic-1.10.21-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4973232c98b9b44c78b1233693e5e1938add5af18042f031737e1214455f9b8"}, - {file = "pydantic-1.10.21-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:662bf5ce3c9b1cef32a32a2f4debe00d2f4839fefbebe1d6956e681122a9c839"}, - {file = "pydantic-1.10.21-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:98737c3ab5a2f8a85f2326eebcd214510f898881a290a7939a45ec294743c875"}, - {file = "pydantic-1.10.21-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0bb58bbe65a43483d49f66b6c8474424d551a3fbe8a7796c42da314bac712738"}, - {file = "pydantic-1.10.21-cp313-cp313-win_amd64.whl", hash = "sha256:e622314542fb48542c09c7bd1ac51d71c5632dd3c92dc82ede6da233f55f4848"}, - {file = "pydantic-1.10.21-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d356aa5b18ef5a24d8081f5c5beb67c0a2a6ff2a953ee38d65a2aa96526b274f"}, - {file = "pydantic-1.10.21-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08caa8c0468172d27c669abfe9e7d96a8b1655ec0833753e117061febaaadef5"}, - {file = "pydantic-1.10.21-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c677aa39ec737fec932feb68e4a2abe142682f2885558402602cd9746a1c92e8"}, - {file = "pydantic-1.10.21-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:79577cc045d3442c4e845df53df9f9202546e2ba54954c057d253fc17cd16cb1"}, - {file = "pydantic-1.10.21-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:b6b73ab347284719f818acb14f7cd80696c6fdf1bd34feee1955d7a72d2e64ce"}, - {file = "pydantic-1.10.21-cp37-cp37m-win_amd64.whl", hash = "sha256:46cffa24891b06269e12f7e1ec50b73f0c9ab4ce71c2caa4ccf1fb36845e1ff7"}, - {file = "pydantic-1.10.21-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:298d6f765e3c9825dfa78f24c1efd29af91c3ab1b763e1fd26ae4d9e1749e5c8"}, - {file = "pydantic-1.10.21-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f2f4a2305f15eff68f874766d982114ac89468f1c2c0b97640e719cf1a078374"}, - {file = "pydantic-1.10.21-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35b263b60c519354afb3a60107d20470dd5250b3ce54c08753f6975c406d949b"}, - {file = "pydantic-1.10.21-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e23a97a6c2f2db88995496db9387cd1727acdacc85835ba8619dce826c0b11a6"}, - {file = "pydantic-1.10.21-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:3c96fed246ccc1acb2df032ff642459e4ae18b315ecbab4d95c95cfa292e8517"}, - {file = "pydantic-1.10.21-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:b92893ebefc0151474f682e7debb6ab38552ce56a90e39a8834734c81f37c8a9"}, - {file = "pydantic-1.10.21-cp38-cp38-win_amd64.whl", hash = "sha256:b8460bc256bf0de821839aea6794bb38a4c0fbd48f949ea51093f6edce0be459"}, - {file = "pydantic-1.10.21-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5d387940f0f1a0adb3c44481aa379122d06df8486cc8f652a7b3b0caf08435f7"}, - {file = "pydantic-1.10.21-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:266ecfc384861d7b0b9c214788ddff75a2ea123aa756bcca6b2a1175edeca0fe"}, - {file = "pydantic-1.10.21-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61da798c05a06a362a2f8c5e3ff0341743e2818d0f530eaac0d6898f1b187f1f"}, - {file = "pydantic-1.10.21-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a621742da75ce272d64ea57bd7651ee2a115fa67c0f11d66d9dcfc18c2f1b106"}, - {file = "pydantic-1.10.21-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9e3e4000cd54ef455694b8be9111ea20f66a686fc155feda1ecacf2322b115da"}, - {file = "pydantic-1.10.21-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f198c8206640f4c0ef5a76b779241efb1380a300d88b1bce9bfe95a6362e674d"}, - {file = "pydantic-1.10.21-cp39-cp39-win_amd64.whl", hash = "sha256:e7f0cda108b36a30c8fc882e4fc5b7eec8ef584aa43aa43694c6a7b274fb2b56"}, - {file = "pydantic-1.10.21-py3-none-any.whl", hash = "sha256:db70c920cba9d05c69ad4a9e7f8e9e83011abb2c6490e561de9ae24aee44925c"}, - {file = "pydantic-1.10.21.tar.gz", hash = "sha256:64b48e2b609a6c22178a56c408ee1215a7206077ecb8a193e2fda31858b2362a"}, -] - -[package.dependencies] -typing-extensions = ">=4.2.0" - -[package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] - -[[package]] -name = "pydash" -version = "6.0.2" -description = "The kitchen sink of Python utility libraries for doing \"stuff\" in a functional way. Based on the Lo-Dash Javascript library." -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "pydash-6.0.2-py3-none-any.whl", hash = "sha256:6d3ce5cbbc8ca3533c12782ac201c2ec756d1e1703ec3efc88f2b95d1ed2bb31"}, - {file = "pydash-6.0.2.tar.gz", hash = "sha256:35caa588e01d293713655e0870544d25128cd414c5e19477a0d63adc2b2ca03e"}, -] - -[package.extras] -dev = ["Sphinx", "black", "build", "coverage", "docformatter", "flake8", "flake8-black", "flake8-bugbear", "flake8-isort", "importlib-metadata (<5)", "invoke", "isort", "pylint", "pytest", "pytest-cov", "sphinx-rtd-theme", "tox", "twine", "wheel"] - -[[package]] -name = "pygithub" -version = "2.5.0" -description = "Use the full Github API v3" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "PyGithub-2.5.0-py3-none-any.whl", hash = "sha256:b0b635999a658ab8e08720bdd3318893ff20e2275f6446fcf35bf3f44f2c0fd2"}, - {file = "pygithub-2.5.0.tar.gz", hash = "sha256:e1613ac508a9be710920d26eb18b1905ebd9926aa49398e88151c1b526aad3cf"}, -] - -[package.dependencies] -Deprecated = "*" -pyjwt = {version = ">=2.4.0", extras = ["crypto"]} -pynacl = ">=1.4.0" -requests = ">=2.14.0" -typing-extensions = ">=4.0.0" -urllib3 = ">=1.26.0" - -[[package]] -name = "pygments" -version = "2.19.1" -description = "Pygments is a syntax highlighting package written in Python." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, - {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, -] - -[package.extras] -windows-terminal = ["colorama (>=0.4.6)"] - -[[package]] -name = "pyjwt" -version = "2.8.0" -description = "JSON Web Token implementation in Python" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, - {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, -] - -[package.dependencies] -cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"crypto\""} - -[package.extras] -crypto = ["cryptography (>=3.4.0)"] -dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] -docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] - -[[package]] -name = "pynacl" -version = "1.5.0" -description = "Python binding to the Networking and Cryptography (NaCl) library" -optional = false -python-versions = ">=3.6" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, - {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, -] - -[package.dependencies] -cffi = ">=1.4.1" - -[package.extras] -docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] -tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] - -[[package]] -name = "pytest" -version = "8.3.4" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, - {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=1.5,<2" - -[package.extras] -dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "pytest-mock" -version = "3.14.0" -description = "Thin-wrapper around the mock package for easier use with pytest" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, - {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, -] - -[package.dependencies] -pytest = ">=6.2.5" - -[package.extras] -dev = ["pre-commit", "pytest-asyncio", "tox"] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main", "dev"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, - {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "pytz" -version = "2025.1" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "pytz-2025.1-py2.py3-none-any.whl", hash = "sha256:89dd22dca55b46eac6eda23b2d72721bf1bdfef212645d81513ef5d03038de57"}, - {file = "pytz-2025.1.tar.gz", hash = "sha256:c2db42be2a2518b28e65f9207c4d05e6ff547d1efa4086469ef855e4ab70178e"}, -] - -[[package]] -name = "pyyaml" -version = "6.0.2" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, - {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, - {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, - {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, - {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, - {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, - {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, - {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, - {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, - {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, - {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, - {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, - {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, - {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, - {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, - {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, - {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, -] - -[[package]] -name = "requests" -version = "2.32.3" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, - {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "rich" -version = "13.9.4" -description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -optional = false -python-versions = ">=3.8.0" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"}, - {file = "rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098"}, -] - -[package.dependencies] -markdown-it-py = ">=2.2.0" -pygments = ">=2.13.0,<3.0.0" - -[package.extras] -jupyter = ["ipywidgets (>=7.5.1,<9)"] - -[[package]] -name = "rsa" -version = "4.9" -description = "Pure-Python RSA implementation" -optional = false -python-versions = ">=3.6,<4" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, - {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, -] - -[package.dependencies] -pyasn1 = ">=0.1.3" - -[[package]] -name = "semver" -version = "3.0.4" -description = "Python helper for Semantic Versioning (https://semver.org)" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "semver-3.0.4-py3-none-any.whl", hash = "sha256:9c824d87ba7f7ab4a1890799cec8596f15c1241cb473404ea1cb0c55e4b04746"}, - {file = "semver-3.0.4.tar.gz", hash = "sha256:afc7d8c584a5ed0a11033af086e8af226a9c0b206f313e0301f8dd7b6b589602"}, -] - -[[package]] -name = "simpleeval" -version = "0.9.13" -description = "A simple, safe single expression evaluator library." -optional = false -python-versions = "*" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "simpleeval-0.9.13-py2.py3-none-any.whl", hash = "sha256:22a2701a5006e4188d125d34accf2405c2c37c93f6b346f2484b6422415ae54a"}, - {file = "simpleeval-0.9.13.tar.gz", hash = "sha256:4a30f9cc01825fe4c719c785e3762623e350c4840d5e6855c2a8496baaa65fac"}, -] - -[[package]] -name = "six" -version = "1.17.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main", "dev"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, - {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, -] - -[[package]] -name = "smmap" -version = "5.0.2" -description = "A pure Python implementation of a sliding window memory map manager" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e"}, - {file = "smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5"}, -] - -[[package]] -name = "typing-extensions" -version = "4.12.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, -] - -[[package]] -name = "tzdata" -version = "2025.1" -description = "Provider of IANA time zone data" -optional = false -python-versions = ">=2" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639"}, - {file = "tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694"}, -] - -[[package]] -name = "urllib3" -version = "2.3.0" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, - {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "wrapt" -version = "1.17.2" -description = "Module for decorators, wrappers and monkey patching." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version >= \"3.12\" or python_version == \"3.11\"" -files = [ - {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, - {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, - {file = "wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7"}, - {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c"}, - {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72"}, - {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061"}, - {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2"}, - {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c"}, - {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62"}, - {file = "wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563"}, - {file = "wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f"}, - {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58"}, - {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda"}, - {file = "wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438"}, - {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a"}, - {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000"}, - {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6"}, - {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b"}, - {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662"}, - {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72"}, - {file = "wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317"}, - {file = "wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3"}, - {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925"}, - {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392"}, - {file = "wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40"}, - {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d"}, - {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b"}, - {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98"}, - {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82"}, - {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae"}, - {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9"}, - {file = "wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9"}, - {file = "wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991"}, - {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125"}, - {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998"}, - {file = "wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5"}, - {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8"}, - {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6"}, - {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc"}, - {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2"}, - {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b"}, - {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504"}, - {file = "wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a"}, - {file = "wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845"}, - {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192"}, - {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b"}, - {file = "wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0"}, - {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306"}, - {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb"}, - {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681"}, - {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6"}, - {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6"}, - {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f"}, - {file = "wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555"}, - {file = "wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c"}, - {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9"}, - {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119"}, - {file = "wrapt-1.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6"}, - {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9"}, - {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a"}, - {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2"}, - {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a"}, - {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04"}, - {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f"}, - {file = "wrapt-1.17.2-cp38-cp38-win32.whl", hash = "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7"}, - {file = "wrapt-1.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3"}, - {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a"}, - {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061"}, - {file = "wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82"}, - {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9"}, - {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f"}, - {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b"}, - {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f"}, - {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8"}, - {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9"}, - {file = "wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb"}, - {file = "wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb"}, - {file = "wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8"}, - {file = "wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3"}, -] - -[metadata] -lock-version = "2.1" -python-versions = "^3.11" -content-hash = "2e5cf16ae5611f4e60137746863e018c5670a42829f024c9d7384e9d5e144581" diff --git a/airbyte-ci/connectors/connector_ops/pyproject.toml b/airbyte-ci/connectors/connector_ops/pyproject.toml deleted file mode 100644 index 108cbed0cbb4..000000000000 --- a/airbyte-ci/connectors/connector_ops/pyproject.toml +++ /dev/null @@ -1,38 +0,0 @@ -[build-system] -requires = ["poetry-core>=1.1.0"] -build-backend = "poetry.core.masonry.api" - -[tool.poetry] -name = "connector_ops" -version = "0.10.1" -description = "Packaged maintained by the connector operations team to perform CI for connectors" -authors = ["Airbyte "] - -[tool.poetry.dependencies] -python = "^3.11" -click = "^8.1.3" -requests = "^2.31" -PyYAML = "^6.0" -GitPython = "^3.1.29" -pydantic = "^1.9" -PyGithub = "^2" -rich = "^13.0.0" -pydash = "^6.0.2" -google-cloud-storage = "^2.8.0" -ci-credentials = {path = "../ci_credentials"} -pandas = "^2.0.3" -simpleeval = "^0.9.13" -semver = "^3.0.2" - -[tool.poetry.group.dev.dependencies] -pytest = "^8" -pytest-mock = "^3.10.0" -freezegun = "^1.1.0" - -[tool.poe.tasks] -test = "pytest tests" - -[tool.airbyte_ci] -python_versions = ["3.11"] -optional_poetry_groups = ["dev"] -poe_tasks = ["test"] diff --git a/airbyte-ci/connectors/connector_ops/pytest.ini b/airbyte-ci/connectors/connector_ops/pytest.ini deleted file mode 100644 index 6df308df74d5..000000000000 --- a/airbyte-ci/connectors/connector_ops/pytest.ini +++ /dev/null @@ -1,4 +0,0 @@ -[pytest] -markers = - slow: marks tests as slow (deselect with '-m "not slow"') - serial diff --git a/airbyte-ci/connectors/connector_ops/tests/conftest.py b/airbyte-ci/connectors/connector_ops/tests/conftest.py deleted file mode 100644 index 78aad3d1c104..000000000000 --- a/airbyte-ci/connectors/connector_ops/tests/conftest.py +++ /dev/null @@ -1,65 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - - -import os -from datetime import datetime - -import pandas as pd -import pytest - - -@pytest.fixture(scope="module") -def adoption_metrics_per_connector_version(): - return pd.DataFrame( - [ - { - "connector_definition_id": "dfd88b22-b603-4c3d-aad7-3701784586b1", - "connector_version": "2.0.0", - "number_of_connections": 0, - "number_of_users": 0, - "succeeded_syncs_count": 0, - "failed_syncs_count": 0, - "total_syncs_count": 0, - "sync_success_rate": 0.0, - } - ] - ) - - -@pytest.fixture -def dummy_qa_report() -> pd.DataFrame: - return pd.DataFrame( - [ - { - "connector_type": "source", - "connector_name": "test", - "connector_technical_name": "source-test", - "connector_definition_id": "foobar", - "connector_version": "0.0.0", - "support_level": "community", - "is_on_cloud": False, - "is_appropriate_for_cloud_use": True, - "latest_build_is_successful": True, - "documentation_is_available": False, - "number_of_connections": 0, - "number_of_users": 0, - "sync_success_rate": 0.99, - "total_syncs_count": 0, - "failed_syncs_count": 0, - "succeeded_syncs_count": 0, - "is_eligible_for_promotion_to_cloud": True, - "report_generation_datetime": datetime.utcnow(), - } - ] - ) - - -@pytest.fixture(autouse=True) -def set_working_dir_to_repo_root(monkeypatch): - """Set working directory to the root of the repository. - - HACK: This is a workaround for the fact that these tests are not run from the root of the repository. - """ - monkeypatch.chdir(os.path.join(os.path.dirname(__file__), "..", "..", "..", "..")) diff --git a/airbyte-ci/connectors/connector_ops/tests/test_migration_files/bad-header.md b/airbyte-ci/connectors/connector_ops/tests/test_migration_files/bad-header.md deleted file mode 100644 index 2d430959e1c6..000000000000 --- a/airbyte-ci/connectors/connector_ops/tests/test_migration_files/bad-header.md +++ /dev/null @@ -1,9 +0,0 @@ -# Foobar Migration Guide - -## 2.0.0 - -This is something else - -## 1.0.0 - -This is something diff --git a/airbyte-ci/connectors/connector_ops/tests/test_migration_files/bad-title.md b/airbyte-ci/connectors/connector_ops/tests/test_migration_files/bad-title.md deleted file mode 100644 index 10fd8674485a..000000000000 --- a/airbyte-ci/connectors/connector_ops/tests/test_migration_files/bad-title.md +++ /dev/null @@ -1,9 +0,0 @@ -# source-foobar Migration Guide - -## Upgrading to 2.0.0 - -This is something else - -## Upgrading to 1.0.0 - -This is something diff --git a/airbyte-ci/connectors/connector_ops/tests/test_migration_files/extra-header.md b/airbyte-ci/connectors/connector_ops/tests/test_migration_files/extra-header.md deleted file mode 100644 index 02a23ff5bd19..000000000000 --- a/airbyte-ci/connectors/connector_ops/tests/test_migration_files/extra-header.md +++ /dev/null @@ -1,13 +0,0 @@ -# Foobar Migration Guide - -## Upgrading to 2.0.0 - -This is something else - -## Upgrading to 1.0.0 - -This is something - -## Upgrading to 1.0.0 - -This is extra diff --git a/airbyte-ci/connectors/connector_ops/tests/test_migration_files/missing-entry.md b/airbyte-ci/connectors/connector_ops/tests/test_migration_files/missing-entry.md deleted file mode 100644 index cf642efdc263..000000000000 --- a/airbyte-ci/connectors/connector_ops/tests/test_migration_files/missing-entry.md +++ /dev/null @@ -1,5 +0,0 @@ -# Foobar Migration Guide - -## Upgrading to 1.0.0 - -This is something diff --git a/airbyte-ci/connectors/connector_ops/tests/test_migration_files/out-of-order.md b/airbyte-ci/connectors/connector_ops/tests/test_migration_files/out-of-order.md deleted file mode 100644 index dc2caf839c41..000000000000 --- a/airbyte-ci/connectors/connector_ops/tests/test_migration_files/out-of-order.md +++ /dev/null @@ -1,9 +0,0 @@ -# Foobar Migration Guide - -## Upgrading to 1.0.0 - -This is something - -## Upgrading to 2.0.0 - -This is something else diff --git a/airbyte-ci/connectors/connector_ops/tests/test_utils.py b/airbyte-ci/connectors/connector_ops/tests/test_utils.py deleted file mode 100644 index a58acdb17f14..000000000000 --- a/airbyte-ci/connectors/connector_ops/tests/test_utils.py +++ /dev/null @@ -1,184 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from contextlib import nullcontext as does_not_raise -from pathlib import Path - -import pytest -import semver -from connector_ops import utils - - -class TestConnector: - @pytest.mark.parametrize( - "technical_name, expected_type, expected_name, expected_error", - [ - ("source-faker", "source", "faker", does_not_raise()), - ("source-facebook-marketing", "source", "facebook-marketing", does_not_raise()), - ("destination-postgres", "destination", "postgres", does_not_raise()), - ("foo", None, None, pytest.raises(utils.ConnectorInvalidNameError)), - ], - ) - def test__get_type_and_name_from_technical_name(self, technical_name, expected_type, expected_name, expected_error): - connector = utils.Connector(technical_name) - with expected_error: - assert connector._get_type_and_name_from_technical_name() == (expected_type, expected_name) - assert connector.name == expected_name - assert connector.connector_type == expected_type - - @pytest.mark.parametrize( - "connector, exists", - [ - (utils.Connector("source-faker"), True), - (utils.Connector("source-doesnotexist"), False), - ], - ) - def test_init(self, connector, exists, mocker, tmp_path): - assert str(connector) == connector.technical_name - assert connector.code_directory == Path(f"./airbyte-integrations/connectors/{connector.technical_name}") - assert connector.acceptance_test_config_path == connector.code_directory / utils.ACCEPTANCE_TEST_CONFIG_FILE_NAME - - if exists: - assert connector.connector_type, connector.name == connector._get_type_and_name_from_technical_name() - assert connector.documentation_file_path == Path(f"./docs/integrations/{connector.connector_type}s/{connector.name}.md") - assert isinstance(connector.metadata, dict) - assert isinstance(connector.support_level, str) - assert isinstance(connector.acceptance_test_config, dict) - assert connector.icon_path == Path(f"./airbyte-integrations/connectors/{connector.technical_name}/icon.svg") - assert semver.Version.parse(connector.version) - else: - assert connector.metadata is None - assert connector.support_level is None - assert connector.acceptance_test_config is None - assert connector.icon_path == Path(f"./airbyte-integrations/connectors/{connector.technical_name}/icon.svg") - assert connector.version is None - with pytest.raises(utils.ConnectorVersionNotFound): - Path(tmp_path / "Dockerfile").touch() - mocker.patch.object(utils.Connector, "code_directory", tmp_path) - utils.Connector(connector.technical_name).version - - def test_metadata_query_match(self, mocker): - connector = utils.Connector("source-faker") - mocker.patch.object(utils.Connector, "metadata", {"dockerRepository": "airbyte/source-faker", "ab_internal": {"ql": 100}}) - assert connector.metadata_query_match("data.dockerRepository == 'airbyte/source-faker'") - assert connector.metadata_query_match("'source' in data.dockerRepository") - assert not connector.metadata_query_match("data.dockerRepository == 'airbyte/source-faker2'") - assert not connector.metadata_query_match("'destination' in data.dockerRepository") - assert connector.metadata_query_match("data.ab_internal.ql == 100") - assert connector.metadata_query_match("data.ab_internal.ql >= 100") - assert connector.metadata_query_match("data.ab_internal.ql > 1") - assert not connector.metadata_query_match("data.ab_internal.ql == 101") - assert not connector.metadata_query_match("data.ab_internal.ql >= 101") - assert not connector.metadata_query_match("data.ab_internal.ql > 101") - assert not connector.metadata_query_match("data.ab_internal == whatever") - - @pytest.fixture - def connector_without_dockerfile(self, mocker, tmp_path): - mocker.patch.object(utils.Connector, "code_directory", tmp_path) - connector = utils.Connector("source-faker") - return connector - - def test_has_dockerfile_without_dockerfile(self, connector_without_dockerfile): - assert not connector_without_dockerfile.has_dockerfile - - @pytest.fixture - def connector_with_dockerfile(self, mocker, tmp_path): - mocker.patch.object(utils.Connector, "code_directory", tmp_path) - connector = utils.Connector("source-faker") - tmp_path.joinpath("Dockerfile").touch() - return connector - - def test_has_dockerfile_with_dockerfile(self, connector_with_dockerfile): - assert connector_with_dockerfile.has_dockerfile - - -@pytest.fixture() -def gradle_file_with_dependencies(tmpdir) -> tuple[Path, list[Path], list[Path]]: - test_gradle_file = Path(tmpdir) / "build.gradle" - test_gradle_file.write_text( - """ - plugins { - id 'java' - } - - dependencies { - implementation project(':path:to:dependency1') - implementation project(':path:to:dependency2') - testImplementation project(':path:to:test:dependency') - integrationTestJavaImplementation project(':path:to:test:dependency1') - performanceTestJavaImplementation project(':path:to:test:dependency2') - } - """ - ) - expected_dependencies = [Path("path/to/dependency1"), Path("path/to/dependency2")] - expected_test_dependencies = [Path("path/to/test/dependency"), Path("path/to/test/dependency1"), Path("path/to/test/dependency2")] - - return test_gradle_file, expected_dependencies, expected_test_dependencies - - -@pytest.fixture() -def gradle_file_with_local_cdk_dependencies(tmpdir) -> tuple[Path, list[Path], list[Path]]: - test_gradle_file = Path(tmpdir) / "build.gradle" - test_gradle_file.write_text( - """ - plugins { - id 'java' - id 'airbyte-java-connector' - } - - airbyteJavaConnector { - cdkVersionRequired = '0.1.0' - features = ['db-destinations'] - useLocalCdk = true - } - - airbyteJavaConnector.addCdkDependencies() - - dependencies { - implementation project(':path:to:dependency1') - implementation project(':path:to:dependency2') - testImplementation project(':path:to:test:dependency') - integrationTestJavaImplementation project(':path:to:test:dependency1') - performanceTestJavaImplementation project(':path:to:test:dependency2') - } - """ - ) - expected_dependencies = [ - Path("path/to/dependency1"), - Path("path/to/dependency2"), - ] - expected_test_dependencies = [ - Path("path/to/test/dependency"), - Path("path/to/test/dependency1"), - Path("path/to/test/dependency2"), - ] - return test_gradle_file, expected_dependencies, expected_test_dependencies - - -def test_parse_dependencies(gradle_file_with_dependencies): - gradle_file, expected_regular_dependencies, expected_test_dependencies = gradle_file_with_dependencies - regular_dependencies, test_dependencies = utils.parse_gradle_dependencies(gradle_file) - assert len(regular_dependencies) == len(expected_regular_dependencies) - assert all([regular_dependency in expected_regular_dependencies for regular_dependency in regular_dependencies]) - assert len(test_dependencies) == len(expected_test_dependencies) - assert all([test_dependency in expected_test_dependencies for test_dependency in test_dependencies]) - - -def test_parse_dependencies_with_cdk(gradle_file_with_local_cdk_dependencies): - gradle_file, expected_regular_dependencies, expected_test_dependencies = gradle_file_with_local_cdk_dependencies - regular_dependencies, test_dependencies = utils.parse_gradle_dependencies(gradle_file) - assert len(regular_dependencies) == len(expected_regular_dependencies) - assert all([regular_dependency in expected_regular_dependencies for regular_dependency in regular_dependencies]) - assert len(test_dependencies) == len(expected_test_dependencies) - assert all([test_dependency in expected_test_dependencies for test_dependency in test_dependencies]) - - -def test_get_all_connectors_in_repo(): - all_connectors = utils.get_all_connectors_in_repo() - assert len(all_connectors) > 0 - for connector in all_connectors: - assert isinstance(connector, utils.Connector) - assert connector.metadata is not None - if connector.has_airbyte_docs and connector.is_enabled_in_any_registry: - assert connector.documentation_file_path.exists() diff --git a/airbyte-ci/connectors/connectors_insights/README.md b/airbyte-ci/connectors/connectors_insights/README.md deleted file mode 100644 index 6d38228949f8..000000000000 --- a/airbyte-ci/connectors/connectors_insights/README.md +++ /dev/null @@ -1,97 +0,0 @@ -# Connectors Insights - -Connectors Insights is a Python project designed to generate various insights from analysis of our connectors code. This project utilizes Poetry for dependency management and packaging. - -## Artifacts Produced -The project generates the following artifacts: - -- `insights.json`: Contains general insights and metadata about the connectors. -- `sbom.json`: Contains the Software Bill Of Material. Produced by [Syft](https://github.com/anchore/syft). - -## Installation -To install the project and its dependencies, ensure you have Poetry installed, then run: -```sh -poetry install -``` - -## Usage -The Connectors Insights project provides a command-line interface (CLI) to generate the artifacts. Below is the command to run the CLI: - -```sh -# From airbyte root directory -connectors-insights generate --output-directory --gcs-uri=gs:/// --connector-directory airbyte-integrations/connectors/ --concurrency 2 --rewrite -``` - -### CLI Options - -- `generate`: The command to generate the artifacts. - -- `-o, --output-dir`: Specifies the local directory where the generated artifacts will be saved. In this example, artifacts are saved to `/Users/augustin/Desktop/insights`. - -- `-g, --gcs-uri`: The Google Cloud Storage (GCS) URI prefix where the artifacts will be uploaded. In the form: `gs:///`. - -- `-d, --connector-directory`: The directory containing the connectors. This option points to the location of the connectors to be analyzed, here it is `airbyte-integrations/connectors/`. - -- `-c, --concurrency`: Sets the level of concurrency for the generation process. In this example, it is set to `2`. - -- `--rewrite`: If provided, this flag indicates that existing artifacts should be rewritten if they already exist. - -## Example -To generate the artifacts and save them both locally and to GCS, you can use the following command: - -```sh -connectors-insights generate --output-directory --gcs-uri=gs:/// --connector-directory airbyte-integrations/connectors/ --concurrency 2 --rewrite -``` - -This command will generate `insights.json` and `sbom.json` files, saving them to the specified local directory and uploading them to the specified GCS URI if `--gcs-uri` is passed. - -### Examples of generated artifacts -* [`insights.json`](https://storage.googleapis.com/prod-airbyte-cloud-connector-metadata-service/connector_insights/source-faker/latest/insights.json) -* [`sbom.json`](https://storage.googleapis.com/prod-airbyte-cloud-connector-metadata-service/connector_insights/source-faker/latest/sbom.json) - - -## Orchestration - -This CLI is currently running nightly in GitHub Actions. The workflow can be found in `.github/workflows/connector_insights.yml`. - -## Changelog - -### 0.3.7 -Update Python version requirement from 3.10 to 3.11. - -### 0.3.5 -Fix permissions issue when installing `pylint` in connector container. - -### 0.3.4 -Update `dagger` to `0.13.3`. - -### 0.3.3 -Use SBOM from the connector registry (SPDX format) instead of generating SBOM in the connector insights. - -### 0.3.2 -Bugfix: Ignore CI on master report if it's not accessible. - -### 0.3.1 -Skip manifest inferred insights when the connector does not have a `manifest.yaml` file. - -### 0.3.0 -Adding `manifest_uses_parameters`, `manifest_uses_custom_components`, and `manifest_custom_components_classes` insights. - -### 0.2.4 -Do not generate insights for `*-scaffold-*` and `*-strict-encrypt` connectors. - -### 0.2.3 -Share `.docker/config.json` with `syft` to benefit from increased DockerHub rate limit. - -### 0.2.2 -- Write the sbom output to a file and not to stdout to avoid issues with large outputs. - -### 0.2.1 -- Implement a high-level error handling to not fail the entire process if a connector fails to generate insights. - -### 0.2.0 -- Detect deprecated class and module use in connectors. -- Fix missing CDK version for connectors not declaring a CDK name in their metadata. - -### 0.1.0 -- Initial release diff --git a/airbyte-ci/connectors/connectors_insights/poetry.lock b/airbyte-ci/connectors/connectors_insights/poetry.lock deleted file mode 100644 index 0587981e3fa3..000000000000 --- a/airbyte-ci/connectors/connectors_insights/poetry.lock +++ /dev/null @@ -1,2379 +0,0 @@ -# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. - -[[package]] -name = "anyio" -version = "4.8.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"}, - {file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"}, -] - -[package.dependencies] -idna = ">=2.8" -sniffio = ">=1.1" -typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} - -[package.extras] -doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"] -trio = ["trio (>=0.26.1)"] - -[[package]] -name = "asyncclick" -version = "8.1.8" -description = "Composable command line interface toolkit," -optional = false -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "asyncclick-8.1.8-py3-none-any.whl", hash = "sha256:eb1ccb44bc767f8f0695d592c7806fdf5bd575605b4ee246ffd5fadbcfdbd7c6"}, - {file = "asyncclick-8.1.8.0-py3-none-any.whl", hash = "sha256:be146a2d8075d4fe372ff4e877f23c8b5af269d16705c1948123b9415f6fd678"}, - {file = "asyncclick-8.1.8.tar.gz", hash = "sha256:0f0eb0f280e04919d67cf71b9fcdfb4db2d9ff7203669c40284485c149578e4c"}, -] - -[package.dependencies] -anyio = ">=4.0,<5.0" -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "asyncer" -version = "0.0.7" -description = "Asyncer, async and await, focused on developer experience." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "asyncer-0.0.7-py3-none-any.whl", hash = "sha256:f0d579d4f67c4ead52ede3a45c854f462cae569058a8a6a68a4ebccac1c335d8"}, - {file = "asyncer-0.0.7.tar.gz", hash = "sha256:d5e563fb0f56eb87b97257984703658a4f5bbdb52ff851b3e8ed864cc200b1d2"}, -] - -[package.dependencies] -anyio = ">=3.4.0,<5.0" - -[[package]] -name = "attrs" -version = "25.1.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a"}, - {file = "attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e"}, -] - -[package.extras] -benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] - -[[package]] -name = "backoff" -version = "2.2.1" -description = "Function decoration for backoff and retry" -optional = false -python-versions = ">=3.7,<4.0" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, - {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, -] - -[[package]] -name = "beartype" -version = "0.19.0" -description = "Unbearably fast near-real-time hybrid runtime-static type-checking in pure Python." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "beartype-0.19.0-py3-none-any.whl", hash = "sha256:33b2694eda0daf052eb2aff623ed9a8a586703bbf0a90bbc475a83bbf427f699"}, - {file = "beartype-0.19.0.tar.gz", hash = "sha256:de42dfc1ba5c3710fde6c3002e3bd2cad236ed4d2aabe876345ab0b4234a6573"}, -] - -[package.extras] -dev = ["autoapi (>=0.9.0)", "coverage (>=5.5)", "equinox", "jax[cpu]", "jaxtyping", "mypy (>=0.800)", "numba", "numpy", "pandera", "pydata-sphinx-theme (<=0.7.2)", "pygments", "pyright (>=1.1.370)", "pytest (>=4.0.0)", "sphinx", "sphinx (>=4.2.0,<6.0.0)", "sphinxext-opengraph (>=0.7.5)", "tox (>=3.20.1)", "typing-extensions (>=3.10.0.0)"] -doc-rtd = ["autoapi (>=0.9.0)", "pydata-sphinx-theme (<=0.7.2)", "sphinx (>=4.2.0,<6.0.0)", "sphinxext-opengraph (>=0.7.5)"] -test = ["coverage (>=5.5)", "equinox", "jax[cpu]", "jaxtyping", "mypy (>=0.800)", "numba", "numpy", "pandera", "pygments", "pyright (>=1.1.370)", "pytest (>=4.0.0)", "sphinx", "tox (>=3.20.1)", "typing-extensions (>=3.10.0.0)"] -test-tox = ["equinox", "jax[cpu]", "jaxtyping", "mypy (>=0.800)", "numba", "numpy", "pandera", "pygments", "pyright (>=1.1.370)", "pytest (>=4.0.0)", "sphinx", "typing-extensions (>=3.10.0.0)"] -test-tox-coverage = ["coverage (>=5.5)"] - -[[package]] -name = "beautifulsoup4" -version = "4.12.3" -description = "Screen-scraping library" -optional = false -python-versions = ">=3.6.0" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, - {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, -] - -[package.dependencies] -soupsieve = ">1.2" - -[package.extras] -cchardet = ["cchardet"] -chardet = ["chardet"] -charset-normalizer = ["charset-normalizer"] -html5lib = ["html5lib"] -lxml = ["lxml"] - -[[package]] -name = "cachetools" -version = "5.5.1" -description = "Extensible memoizing collections and decorators" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "cachetools-5.5.1-py3-none-any.whl", hash = "sha256:b76651fdc3b24ead3c648bbdeeb940c1b04d365b38b4af66788f9ec4a81d42bb"}, - {file = "cachetools-5.5.1.tar.gz", hash = "sha256:70f238fbba50383ef62e55c6aff6d9673175fe59f7c6782c7a0b9e38f4a9df95"}, -] - -[[package]] -name = "cattrs" -version = "24.1.2" -description = "Composable complex class support for attrs and dataclasses." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "cattrs-24.1.2-py3-none-any.whl", hash = "sha256:67c7495b760168d931a10233f979b28dc04daf853b30752246f4f8471c6d68d0"}, - {file = "cattrs-24.1.2.tar.gz", hash = "sha256:8028cfe1ff5382df59dd36474a86e02d817b06eaf8af84555441bac915d2ef85"}, -] - -[package.dependencies] -attrs = ">=23.1.0" - -[package.extras] -bson = ["pymongo (>=4.4.0)"] -cbor2 = ["cbor2 (>=5.4.6)"] -msgpack = ["msgpack (>=1.0.5)"] -msgspec = ["msgspec (>=0.18.5)"] -orjson = ["orjson (>=3.9.2)"] -pyyaml = ["pyyaml (>=6.0)"] -tomlkit = ["tomlkit (>=0.11.8)"] -ujson = ["ujson (>=5.7.0)"] - -[[package]] -name = "certifi" -version = "2025.1.31" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, - {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, -] - -[[package]] -name = "cffi" -version = "1.17.1" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, - {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, - {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, - {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, - {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, - {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, - {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, - {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, - {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, - {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, - {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, - {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, - {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, - {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, - {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, - {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, -] - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "charset-normalizer" -version = "3.4.1" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, - {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, - {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, -] - -[[package]] -name = "ci-credentials" -version = "1.2.0" -description = "CLI tooling to read and manage GSM secrets" -optional = false -python-versions = "^3.11" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [] -develop = false - -[package.dependencies] -click = "^8.1.3" -cryptography = ">=42.0" -pyjwt = "2.8.0" -pyyaml = "^6.0" -requests = "^2.31" - -[package.source] -type = "directory" -url = "../ci_credentials" - -[[package]] -name = "click" -version = "8.1.8" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, - {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main"] -markers = "(python_version == \"3.11\" or python_version >= \"3.12\") and platform_system == \"Windows\"" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "connector-ops" -version = "0.10.0" -description = "Packaged maintained by the connector operations team to perform CI for connectors" -optional = false -python-versions = "^3.11" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [] -develop = false - -[package.dependencies] -ci-credentials = {path = "../ci_credentials"} -click = "^8.1.3" -GitPython = "^3.1.29" -google-cloud-storage = "^2.8.0" -pandas = "^2.0.3" -pydantic = "^1.9" -pydash = "^6.0.2" -PyGithub = "^2" -PyYAML = "^6.0" -requests = "^2.31" -rich = "^13.0.0" -semver = "^3.0.2" -simpleeval = "^0.9.13" - -[package.source] -type = "directory" -url = "../connector_ops" - -[[package]] -name = "cryptography" -version = "44.0.0" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false -python-versions = "!=3.9.0,!=3.9.1,>=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, - {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, - {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, - {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, - {file = "cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd"}, - {file = "cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, - {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, - {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, - {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, - {file = "cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37d76e6863da3774cd9db5b409a9ecfd2c71c981c38788d3fcfaf177f447b731"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:f677e1268c4e23420c3acade68fac427fffcb8d19d7df95ed7ad17cdef8404f4"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f5e7cb1e5e56ca0933b4873c0220a78b773b24d40d186b6738080b73d3d0a756"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:be4ce505894d15d5c5037167ffb7f0ae90b7be6f2a98f9a5c3442395501c32fa"}, - {file = "cryptography-44.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c"}, - {file = "cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02"}, -] - -[package.dependencies] -cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] -docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] -pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] -sdist = ["build (>=1.0.0)"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] -test-randomorder = ["pytest-randomly"] - -[[package]] -name = "dagger-io" -version = "0.13.3" -description = "A client package for running Dagger pipelines in Python." -optional = false -python-versions = ">=3.10" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "dagger_io-0.13.3-py3-none-any.whl", hash = "sha256:c3be14bd2c77ad265f944612123ef6f7653cf0365ffee0c70bf2a2662dc9783d"}, - {file = "dagger_io-0.13.3.tar.gz", hash = "sha256:fb9f602b8493f6e5f66afba4c6f51485dccb7c4795fbde7d92e188c69e8961b7"}, -] - -[package.dependencies] -anyio = ">=3.6.2" -beartype = ">=0.18.2" -cattrs = ">=22.2.0" -gql = {version = ">=3.5.0", extras = ["httpx"]} -opentelemetry-exporter-otlp-proto-grpc = ">=1.23.0" -opentelemetry-sdk = ">=1.23.0" -platformdirs = ">=2.6.2" -rich = ">=10.11.0" -typing-extensions = ">=4.8.0" - -[[package]] -name = "deprecated" -version = "1.2.18" -description = "Python @deprecated decorator to deprecate old python classes, functions or methods." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "Deprecated-1.2.18-py2.py3-none-any.whl", hash = "sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec"}, - {file = "deprecated-1.2.18.tar.gz", hash = "sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d"}, -] - -[package.dependencies] -wrapt = ">=1.10,<2" - -[package.extras] -dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "setuptools", "tox"] - -[[package]] -name = "gitdb" -version = "4.0.12" -description = "Git Object Database" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf"}, - {file = "gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571"}, -] - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[[package]] -name = "gitpython" -version = "3.1.44" -description = "GitPython is a Python library used to interact with Git repositories" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110"}, - {file = "gitpython-3.1.44.tar.gz", hash = "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269"}, -] - -[package.dependencies] -gitdb = ">=4.0.1,<5" - -[package.extras] -doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] -test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions"] - -[[package]] -name = "google-api-core" -version = "2.24.1" -description = "Google API client core library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "google_api_core-2.24.1-py3-none-any.whl", hash = "sha256:bc78d608f5a5bf853b80bd70a795f703294de656c096c0968320830a4bc280f1"}, - {file = "google_api_core-2.24.1.tar.gz", hash = "sha256:f8b36f5456ab0dd99a1b693a40a31d1e7757beea380ad1b38faaf8941eae9d8a"}, -] - -[package.dependencies] -google-auth = ">=2.14.1,<3.0.dev0" -googleapis-common-protos = ">=1.56.2,<2.0.dev0" -proto-plus = [ - {version = ">=1.22.3,<2.0.0dev", markers = "python_version < \"3.13\""}, - {version = ">=1.25.0,<2.0.0dev", markers = "python_version >= \"3.13\""}, -] -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" -requests = ">=2.18.0,<3.0.0.dev0" - -[package.extras] -async-rest = ["google-auth[aiohttp] (>=2.35.0,<3.0.dev0)"] -grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status (>=1.33.2,<2.0.dev0)", "grpcio-status (>=1.49.1,<2.0.dev0)"] -grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] -grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] - -[[package]] -name = "google-auth" -version = "2.38.0" -description = "Google Authentication Library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "google_auth-2.38.0-py2.py3-none-any.whl", hash = "sha256:e7dae6694313f434a2727bf2906f27ad259bae090d7aa896590d86feec3d9d4a"}, - {file = "google_auth-2.38.0.tar.gz", hash = "sha256:8285113607d3b80a3f1543b75962447ba8a09fe85783432a784fdeef6ac094c4"}, -] - -[package.dependencies] -cachetools = ">=2.0.0,<6.0" -pyasn1-modules = ">=0.2.1" -rsa = ">=3.1.4,<5" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] -enterprise-cert = ["cryptography", "pyopenssl"] -pyjwt = ["cryptography (>=38.0.3)", "pyjwt (>=2.0)"] -pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] -reauth = ["pyu2f (>=0.1.5)"] -requests = ["requests (>=2.20.0,<3.0.0.dev0)"] - -[[package]] -name = "google-cloud-core" -version = "2.4.1" -description = "Google Cloud API client core library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "google-cloud-core-2.4.1.tar.gz", hash = "sha256:9b7749272a812bde58fff28868d0c5e2f585b82f37e09a1f6ed2d4d10f134073"}, - {file = "google_cloud_core-2.4.1-py2.py3-none-any.whl", hash = "sha256:a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61"}, -] - -[package.dependencies] -google-api-core = ">=1.31.6,<2.0.dev0 || >2.3.0,<3.0.0dev" -google-auth = ">=1.25.0,<3.0dev" - -[package.extras] -grpc = ["grpcio (>=1.38.0,<2.0dev)", "grpcio-status (>=1.38.0,<2.0.dev0)"] - -[[package]] -name = "google-cloud-storage" -version = "2.19.0" -description = "Google Cloud Storage API client library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "google_cloud_storage-2.19.0-py2.py3-none-any.whl", hash = "sha256:aeb971b5c29cf8ab98445082cbfe7b161a1f48ed275822f59ed3f1524ea54fba"}, - {file = "google_cloud_storage-2.19.0.tar.gz", hash = "sha256:cd05e9e7191ba6cb68934d8eb76054d9be4562aa89dbc4236feee4d7d51342b2"}, -] - -[package.dependencies] -google-api-core = ">=2.15.0,<3.0.0dev" -google-auth = ">=2.26.1,<3.0dev" -google-cloud-core = ">=2.3.0,<3.0dev" -google-crc32c = ">=1.0,<2.0dev" -google-resumable-media = ">=2.7.2" -requests = ">=2.18.0,<3.0.0dev" - -[package.extras] -protobuf = ["protobuf (<6.0.0dev)"] -tracing = ["opentelemetry-api (>=1.1.0)"] - -[[package]] -name = "google-crc32c" -version = "1.6.0" -description = "A python wrapper of the C library 'Google CRC32C'" -optional = false -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "google_crc32c-1.6.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:5bcc90b34df28a4b38653c36bb5ada35671ad105c99cfe915fb5bed7ad6924aa"}, - {file = "google_crc32c-1.6.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:d9e9913f7bd69e093b81da4535ce27af842e7bf371cde42d1ae9e9bd382dc0e9"}, - {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a184243544811e4a50d345838a883733461e67578959ac59964e43cca2c791e7"}, - {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:236c87a46cdf06384f614e9092b82c05f81bd34b80248021f729396a78e55d7e"}, - {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebab974b1687509e5c973b5c4b8b146683e101e102e17a86bd196ecaa4d099fc"}, - {file = "google_crc32c-1.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:50cf2a96da226dcbff8671233ecf37bf6e95de98b2a2ebadbfdf455e6d05df42"}, - {file = "google_crc32c-1.6.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:f7a1fc29803712f80879b0806cb83ab24ce62fc8daf0569f2204a0cfd7f68ed4"}, - {file = "google_crc32c-1.6.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:40b05ab32a5067525670880eb5d169529089a26fe35dce8891127aeddc1950e8"}, - {file = "google_crc32c-1.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e4b426c3702f3cd23b933436487eb34e01e00327fac20c9aebb68ccf34117d"}, - {file = "google_crc32c-1.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51c4f54dd8c6dfeb58d1df5e4f7f97df8abf17a36626a217f169893d1d7f3e9f"}, - {file = "google_crc32c-1.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:bb8b3c75bd157010459b15222c3fd30577042a7060e29d42dabce449c087f2b3"}, - {file = "google_crc32c-1.6.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:ed767bf4ba90104c1216b68111613f0d5926fb3780660ea1198fc469af410e9d"}, - {file = "google_crc32c-1.6.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:62f6d4a29fea082ac4a3c9be5e415218255cf11684ac6ef5488eea0c9132689b"}, - {file = "google_crc32c-1.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c87d98c7c4a69066fd31701c4e10d178a648c2cac3452e62c6b24dc51f9fcc00"}, - {file = "google_crc32c-1.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd5e7d2445d1a958c266bfa5d04c39932dc54093fa391736dbfdb0f1929c1fb3"}, - {file = "google_crc32c-1.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:7aec8e88a3583515f9e0957fe4f5f6d8d4997e36d0f61624e70469771584c760"}, - {file = "google_crc32c-1.6.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:e2806553238cd076f0a55bddab37a532b53580e699ed8e5606d0de1f856b5205"}, - {file = "google_crc32c-1.6.0-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:bb0966e1c50d0ef5bc743312cc730b533491d60585a9a08f897274e57c3f70e0"}, - {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:386122eeaaa76951a8196310432c5b0ef3b53590ef4c317ec7588ec554fec5d2"}, - {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2952396dc604544ea7476b33fe87faedc24d666fb0c2d5ac971a2b9576ab871"}, - {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35834855408429cecf495cac67ccbab802de269e948e27478b1e47dfb6465e57"}, - {file = "google_crc32c-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:d8797406499f28b5ef791f339594b0b5fdedf54e203b5066675c406ba69d705c"}, - {file = "google_crc32c-1.6.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48abd62ca76a2cbe034542ed1b6aee851b6f28aaca4e6551b5599b6f3ef175cc"}, - {file = "google_crc32c-1.6.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18e311c64008f1f1379158158bb3f0c8d72635b9eb4f9545f8cf990c5668e59d"}, - {file = "google_crc32c-1.6.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05e2d8c9a2f853ff116db9706b4a27350587f341eda835f46db3c0a8c8ce2f24"}, - {file = "google_crc32c-1.6.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ca8145b060679ec9176e6de4f89b07363d6805bd4760631ef254905503598d"}, - {file = "google_crc32c-1.6.0.tar.gz", hash = "sha256:6eceb6ad197656a1ff49ebfbbfa870678c75be4344feb35ac1edf694309413dc"}, -] - -[package.extras] -testing = ["pytest"] - -[[package]] -name = "google-resumable-media" -version = "2.7.2" -description = "Utilities for Google Media Downloads and Resumable Uploads" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "google_resumable_media-2.7.2-py2.py3-none-any.whl", hash = "sha256:3ce7551e9fe6d99e9a126101d2536612bb73486721951e9562fee0f90c6ababa"}, - {file = "google_resumable_media-2.7.2.tar.gz", hash = "sha256:5280aed4629f2b60b847b0d42f9857fd4935c11af266744df33d8074cae92fe0"}, -] - -[package.dependencies] -google-crc32c = ">=1.0,<2.0dev" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)", "google-auth (>=1.22.0,<2.0dev)"] -requests = ["requests (>=2.18.0,<3.0.0dev)"] - -[[package]] -name = "googleapis-common-protos" -version = "1.66.0" -description = "Common protobufs used in Google APIs" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "googleapis_common_protos-1.66.0-py2.py3-none-any.whl", hash = "sha256:d7abcd75fabb2e0ec9f74466401f6c119a0b498e27370e9be4c94cb7e382b8ed"}, - {file = "googleapis_common_protos-1.66.0.tar.gz", hash = "sha256:c3e7b33d15fdca5374cc0a7346dd92ffa847425cc4ea941d970f13680052ec8c"}, -] - -[package.dependencies] -protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" - -[package.extras] -grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] - -[[package]] -name = "gql" -version = "3.5.0" -description = "GraphQL client for Python" -optional = false -python-versions = "*" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "gql-3.5.0-py2.py3-none-any.whl", hash = "sha256:70dda5694a5b194a8441f077aa5fb70cc94e4ec08016117523f013680901ecb7"}, - {file = "gql-3.5.0.tar.gz", hash = "sha256:ccb9c5db543682b28f577069950488218ed65d4ac70bb03b6929aaadaf636de9"}, -] - -[package.dependencies] -anyio = ">=3.0,<5" -backoff = ">=1.11.1,<3.0" -graphql-core = ">=3.2,<3.3" -httpx = {version = ">=0.23.1,<1", optional = true, markers = "extra == \"httpx\""} -yarl = ">=1.6,<2.0" - -[package.extras] -aiohttp = ["aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)"] -all = ["aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "websockets (>=10,<12)"] -botocore = ["botocore (>=1.21,<2)"] -dev = ["aiofiles", "aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)", "black (==22.3.0)", "botocore (>=1.21,<2)", "check-manifest (>=0.42,<1)", "flake8 (==3.8.1)", "httpx (>=0.23.1,<1)", "isort (==4.3.21)", "mock (==4.0.2)", "mypy (==0.910)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "sphinx (>=5.3.0,<6)", "sphinx-argparse (==0.2.5)", "sphinx-rtd-theme (>=0.4,<1)", "types-aiofiles", "types-mock", "types-requests", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] -httpx = ["httpx (>=0.23.1,<1)"] -requests = ["requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)"] -test = ["aiofiles", "aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] -test-no-transport = ["aiofiles", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "vcrpy (==4.4.0)"] -websockets = ["websockets (>=10,<12)"] - -[[package]] -name = "graphql-core" -version = "3.2.6" -description = "GraphQL implementation for Python, a port of GraphQL.js, the JavaScript reference implementation for GraphQL." -optional = false -python-versions = "<4,>=3.6" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "graphql_core-3.2.6-py3-none-any.whl", hash = "sha256:78b016718c161a6fb20a7d97bbf107f331cd1afe53e45566c59f776ed7f0b45f"}, - {file = "graphql_core-3.2.6.tar.gz", hash = "sha256:c08eec22f9e40f0bd61d805907e3b3b1b9a320bc606e23dc145eebca07c8fbab"}, -] - -[[package]] -name = "grpcio" -version = "1.70.0" -description = "HTTP/2-based RPC framework" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "grpcio-1.70.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:95469d1977429f45fe7df441f586521361e235982a0b39e33841549143ae2851"}, - {file = "grpcio-1.70.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:ed9718f17fbdb472e33b869c77a16d0b55e166b100ec57b016dc7de9c8d236bf"}, - {file = "grpcio-1.70.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:374d014f29f9dfdb40510b041792e0e2828a1389281eb590df066e1cc2b404e5"}, - {file = "grpcio-1.70.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2af68a6f5c8f78d56c145161544ad0febbd7479524a59c16b3e25053f39c87f"}, - {file = "grpcio-1.70.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce7df14b2dcd1102a2ec32f621cc9fab6695effef516efbc6b063ad749867295"}, - {file = "grpcio-1.70.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c78b339869f4dbf89881e0b6fbf376313e4f845a42840a7bdf42ee6caed4b11f"}, - {file = "grpcio-1.70.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:58ad9ba575b39edef71f4798fdb5c7b6d02ad36d47949cd381d4392a5c9cbcd3"}, - {file = "grpcio-1.70.0-cp310-cp310-win32.whl", hash = "sha256:2b0d02e4b25a5c1f9b6c7745d4fa06efc9fd6a611af0fb38d3ba956786b95199"}, - {file = "grpcio-1.70.0-cp310-cp310-win_amd64.whl", hash = "sha256:0de706c0a5bb9d841e353f6343a9defc9fc35ec61d6eb6111802f3aa9fef29e1"}, - {file = "grpcio-1.70.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:17325b0be0c068f35770f944124e8839ea3185d6d54862800fc28cc2ffad205a"}, - {file = "grpcio-1.70.0-cp311-cp311-macosx_10_14_universal2.whl", hash = "sha256:dbe41ad140df911e796d4463168e33ef80a24f5d21ef4d1e310553fcd2c4a386"}, - {file = "grpcio-1.70.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:5ea67c72101d687d44d9c56068328da39c9ccba634cabb336075fae2eab0d04b"}, - {file = "grpcio-1.70.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb5277db254ab7586769e490b7b22f4ddab3876c490da0a1a9d7c695ccf0bf77"}, - {file = "grpcio-1.70.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7831a0fc1beeeb7759f737f5acd9fdcda520e955049512d68fda03d91186eea"}, - {file = "grpcio-1.70.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:27cc75e22c5dba1fbaf5a66c778e36ca9b8ce850bf58a9db887754593080d839"}, - {file = "grpcio-1.70.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d63764963412e22f0491d0d32833d71087288f4e24cbcddbae82476bfa1d81fd"}, - {file = "grpcio-1.70.0-cp311-cp311-win32.whl", hash = "sha256:bb491125103c800ec209d84c9b51f1c60ea456038e4734688004f377cfacc113"}, - {file = "grpcio-1.70.0-cp311-cp311-win_amd64.whl", hash = "sha256:d24035d49e026353eb042bf7b058fb831db3e06d52bee75c5f2f3ab453e71aca"}, - {file = "grpcio-1.70.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:ef4c14508299b1406c32bdbb9fb7b47612ab979b04cf2b27686ea31882387cff"}, - {file = "grpcio-1.70.0-cp312-cp312-macosx_10_14_universal2.whl", hash = "sha256:aa47688a65643afd8b166928a1da6247d3f46a2784d301e48ca1cc394d2ffb40"}, - {file = "grpcio-1.70.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:880bfb43b1bb8905701b926274eafce5c70a105bc6b99e25f62e98ad59cb278e"}, - {file = "grpcio-1.70.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e654c4b17d07eab259d392e12b149c3a134ec52b11ecdc6a515b39aceeec898"}, - {file = "grpcio-1.70.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2394e3381071045a706ee2eeb6e08962dd87e8999b90ac15c55f56fa5a8c9597"}, - {file = "grpcio-1.70.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:b3c76701428d2df01964bc6479422f20e62fcbc0a37d82ebd58050b86926ef8c"}, - {file = "grpcio-1.70.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ac073fe1c4cd856ebcf49e9ed6240f4f84d7a4e6ee95baa5d66ea05d3dd0df7f"}, - {file = "grpcio-1.70.0-cp312-cp312-win32.whl", hash = "sha256:cd24d2d9d380fbbee7a5ac86afe9787813f285e684b0271599f95a51bce33528"}, - {file = "grpcio-1.70.0-cp312-cp312-win_amd64.whl", hash = "sha256:0495c86a55a04a874c7627fd33e5beaee771917d92c0e6d9d797628ac40e7655"}, - {file = "grpcio-1.70.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:aa573896aeb7d7ce10b1fa425ba263e8dddd83d71530d1322fd3a16f31257b4a"}, - {file = "grpcio-1.70.0-cp313-cp313-macosx_10_14_universal2.whl", hash = "sha256:d405b005018fd516c9ac529f4b4122342f60ec1cee181788249372524e6db429"}, - {file = "grpcio-1.70.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:f32090238b720eb585248654db8e3afc87b48d26ac423c8dde8334a232ff53c9"}, - {file = "grpcio-1.70.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfa089a734f24ee5f6880c83d043e4f46bf812fcea5181dcb3a572db1e79e01c"}, - {file = "grpcio-1.70.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f19375f0300b96c0117aca118d400e76fede6db6e91f3c34b7b035822e06c35f"}, - {file = "grpcio-1.70.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:7c73c42102e4a5ec76608d9b60227d917cea46dff4d11d372f64cbeb56d259d0"}, - {file = "grpcio-1.70.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:0a5c78d5198a1f0aa60006cd6eb1c912b4a1520b6a3968e677dbcba215fabb40"}, - {file = "grpcio-1.70.0-cp313-cp313-win32.whl", hash = "sha256:fe9dbd916df3b60e865258a8c72ac98f3ac9e2a9542dcb72b7a34d236242a5ce"}, - {file = "grpcio-1.70.0-cp313-cp313-win_amd64.whl", hash = "sha256:4119fed8abb7ff6c32e3d2255301e59c316c22d31ab812b3fbcbaf3d0d87cc68"}, - {file = "grpcio-1.70.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:8058667a755f97407fca257c844018b80004ae8035565ebc2812cc550110718d"}, - {file = "grpcio-1.70.0-cp38-cp38-macosx_10_14_universal2.whl", hash = "sha256:879a61bf52ff8ccacbedf534665bb5478ec8e86ad483e76fe4f729aaef867cab"}, - {file = "grpcio-1.70.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:0ba0a173f4feacf90ee618fbc1a27956bfd21260cd31ced9bc707ef551ff7dc7"}, - {file = "grpcio-1.70.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:558c386ecb0148f4f99b1a65160f9d4b790ed3163e8610d11db47838d452512d"}, - {file = "grpcio-1.70.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:412faabcc787bbc826f51be261ae5fa996b21263de5368a55dc2cf824dc5090e"}, - {file = "grpcio-1.70.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3b0f01f6ed9994d7a0b27eeddea43ceac1b7e6f3f9d86aeec0f0064b8cf50fdb"}, - {file = "grpcio-1.70.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7385b1cb064734005204bc8994eed7dcb801ed6c2eda283f613ad8c6c75cf873"}, - {file = "grpcio-1.70.0-cp38-cp38-win32.whl", hash = "sha256:07269ff4940f6fb6710951116a04cd70284da86d0a4368fd5a3b552744511f5a"}, - {file = "grpcio-1.70.0-cp38-cp38-win_amd64.whl", hash = "sha256:aba19419aef9b254e15011b230a180e26e0f6864c90406fdbc255f01d83bc83c"}, - {file = "grpcio-1.70.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:4f1937f47c77392ccd555728f564a49128b6a197a05a5cd527b796d36f3387d0"}, - {file = "grpcio-1.70.0-cp39-cp39-macosx_10_14_universal2.whl", hash = "sha256:0cd430b9215a15c10b0e7d78f51e8a39d6cf2ea819fd635a7214fae600b1da27"}, - {file = "grpcio-1.70.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:e27585831aa6b57b9250abaf147003e126cd3a6c6ca0c531a01996f31709bed1"}, - {file = "grpcio-1.70.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1af8e15b0f0fe0eac75195992a63df17579553b0c4af9f8362cc7cc99ccddf4"}, - {file = "grpcio-1.70.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbce24409beaee911c574a3d75d12ffb8c3e3dd1b813321b1d7a96bbcac46bf4"}, - {file = "grpcio-1.70.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ff4a8112a79464919bb21c18e956c54add43ec9a4850e3949da54f61c241a4a6"}, - {file = "grpcio-1.70.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5413549fdf0b14046c545e19cfc4eb1e37e9e1ebba0ca390a8d4e9963cab44d2"}, - {file = "grpcio-1.70.0-cp39-cp39-win32.whl", hash = "sha256:b745d2c41b27650095e81dea7091668c040457483c9bdb5d0d9de8f8eb25e59f"}, - {file = "grpcio-1.70.0-cp39-cp39-win_amd64.whl", hash = "sha256:a31d7e3b529c94e930a117b2175b2efd179d96eb3c7a21ccb0289a8ab05b645c"}, - {file = "grpcio-1.70.0.tar.gz", hash = "sha256:8d1584a68d5922330025881e63a6c1b54cc8117291d382e4fa69339b6d914c56"}, -] - -[package.extras] -protobuf = ["grpcio-tools (>=1.70.0)"] - -[[package]] -name = "h11" -version = "0.14.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, -] - -[[package]] -name = "httpcore" -version = "1.0.7" -description = "A minimal low-level HTTP client." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, - {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, -] - -[package.dependencies] -certifi = "*" -h11 = ">=0.13,<0.15" - -[package.extras] -asyncio = ["anyio (>=4.0,<5.0)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<1.0)"] - -[[package]] -name = "httpx" -version = "0.28.1" -description = "The next generation HTTP client." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, - {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, -] - -[package.dependencies] -anyio = "*" -certifi = "*" -httpcore = "==1.*" -idna = "*" - -[package.extras] -brotli = ["brotli", "brotlicffi"] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "idna" -version = "3.10" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.6" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, - {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, -] - -[package.extras] -all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] - -[[package]] -name = "importlib-metadata" -version = "8.5.0" -description = "Read metadata from Python packages" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, - {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, -] - -[package.dependencies] -zipp = ">=3.20" - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=2.2)"] -perf = ["ipython"] -test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] -type = ["pytest-mypy"] - -[[package]] -name = "markdown-it-py" -version = "3.0.0" -description = "Python port of markdown-it. Markdown parsing, done right!" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, - {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, -] - -[package.dependencies] -mdurl = ">=0.1,<1.0" - -[package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark"] -code-style = ["pre-commit (>=3.0,<4.0)"] -compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] -linkify = ["linkify-it-py (>=1,<3)"] -plugins = ["mdit-py-plugins"] -profiling = ["gprof2dot"] -rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] - -[[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, -] - -[[package]] -name = "multidict" -version = "6.1.0" -description = "multidict implementation" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, - {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, - {file = "multidict-6.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7"}, - {file = "multidict-6.1.0-cp310-cp310-win32.whl", hash = "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0"}, - {file = "multidict-6.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d"}, - {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6"}, - {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156"}, - {file = "multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753"}, - {file = "multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80"}, - {file = "multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926"}, - {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa"}, - {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436"}, - {file = "multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3"}, - {file = "multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133"}, - {file = "multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1"}, - {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008"}, - {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f"}, - {file = "multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6"}, - {file = "multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81"}, - {file = "multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774"}, - {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392"}, - {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a"}, - {file = "multidict-6.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd"}, - {file = "multidict-6.1.0-cp38-cp38-win32.whl", hash = "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167"}, - {file = "multidict-6.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef"}, - {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c"}, - {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1"}, - {file = "multidict-6.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43"}, - {file = "multidict-6.1.0-cp39-cp39-win32.whl", hash = "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada"}, - {file = "multidict-6.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a"}, - {file = "multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506"}, - {file = "multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a"}, -] - -[[package]] -name = "mypy" -version = "1.14.1" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb"}, - {file = "mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b"}, - {file = "mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427"}, - {file = "mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f"}, - {file = "mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1"}, - {file = "mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e"}, - {file = "mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89"}, - {file = "mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9"}, - {file = "mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd"}, - {file = "mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7084fb8f1128c76cd9cf68fe5971b37072598e7c31b2f9f95586b65c741a9d31"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f845a00b4f420f693f870eaee5f3e2692fa84cc8514496114649cfa8fd5e2c6"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44bf464499f0e3a2d14d58b54674dee25c031703b2ffc35064bd0df2e0fac319"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c99f27732c0b7dc847adb21c9d47ce57eb48fa33a17bc6d7d5c5e9f9e7ae5bac"}, - {file = "mypy-1.14.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:bce23c7377b43602baa0bd22ea3265c49b9ff0b76eb315d6c34721af4cdf1d9b"}, - {file = "mypy-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:8edc07eeade7ebc771ff9cf6b211b9a7d93687ff892150cb5692e4f4272b0837"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb"}, - {file = "mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60"}, - {file = "mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c"}, - {file = "mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1"}, - {file = "mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6"}, -] - -[package.dependencies] -mypy_extensions = ">=1.0.0" -typing_extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -faster-cache = ["orjson"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -groups = ["dev"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "numpy" -version = "2.2.2" -description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.10" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "numpy-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7079129b64cb78bdc8d611d1fd7e8002c0a2565da6a47c4df8062349fee90e3e"}, - {file = "numpy-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ec6c689c61df613b783aeb21f945c4cbe6c51c28cb70aae8430577ab39f163e"}, - {file = "numpy-2.2.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:40c7ff5da22cd391944a28c6a9c638a5eef77fcf71d6e3a79e1d9d9e82752715"}, - {file = "numpy-2.2.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:995f9e8181723852ca458e22de5d9b7d3ba4da3f11cc1cb113f093b271d7965a"}, - {file = "numpy-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b78ea78450fd96a498f50ee096f69c75379af5138f7881a51355ab0e11286c97"}, - {file = "numpy-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fbe72d347fbc59f94124125e73fc4976a06927ebc503ec5afbfb35f193cd957"}, - {file = "numpy-2.2.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8e6da5cffbbe571f93588f562ed130ea63ee206d12851b60819512dd3e1ba50d"}, - {file = "numpy-2.2.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:09d6a2032faf25e8d0cadde7fd6145118ac55d2740132c1d845f98721b5ebcfd"}, - {file = "numpy-2.2.2-cp310-cp310-win32.whl", hash = "sha256:159ff6ee4c4a36a23fe01b7c3d07bd8c14cc433d9720f977fcd52c13c0098160"}, - {file = "numpy-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:64bd6e1762cd7f0986a740fee4dff927b9ec2c5e4d9a28d056eb17d332158014"}, - {file = "numpy-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:642199e98af1bd2b6aeb8ecf726972d238c9877b0f6e8221ee5ab945ec8a2189"}, - {file = "numpy-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6d9fc9d812c81e6168b6d405bf00b8d6739a7f72ef22a9214c4241e0dc70b323"}, - {file = "numpy-2.2.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:c7d1fd447e33ee20c1f33f2c8e6634211124a9aabde3c617687d8b739aa69eac"}, - {file = "numpy-2.2.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:451e854cfae0febe723077bd0cf0a4302a5d84ff25f0bfece8f29206c7bed02e"}, - {file = "numpy-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd249bc894af67cbd8bad2c22e7cbcd46cf87ddfca1f1289d1e7e54868cc785c"}, - {file = "numpy-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02935e2c3c0c6cbe9c7955a8efa8908dd4221d7755644c59d1bba28b94fd334f"}, - {file = "numpy-2.2.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a972cec723e0563aa0823ee2ab1df0cb196ed0778f173b381c871a03719d4826"}, - {file = "numpy-2.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d6d6a0910c3b4368d89dde073e630882cdb266755565155bc33520283b2d9df8"}, - {file = "numpy-2.2.2-cp311-cp311-win32.whl", hash = "sha256:860fd59990c37c3ef913c3ae390b3929d005243acca1a86facb0773e2d8d9e50"}, - {file = "numpy-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:da1eeb460ecce8d5b8608826595c777728cdf28ce7b5a5a8c8ac8d949beadcf2"}, - {file = "numpy-2.2.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ac9bea18d6d58a995fac1b2cb4488e17eceeac413af014b1dd26170b766d8467"}, - {file = "numpy-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23ae9f0c2d889b7b2d88a3791f6c09e2ef827c2446f1c4a3e3e76328ee4afd9a"}, - {file = "numpy-2.2.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3074634ea4d6df66be04f6728ee1d173cfded75d002c75fac79503a880bf3825"}, - {file = "numpy-2.2.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:8ec0636d3f7d68520afc6ac2dc4b8341ddb725039de042faf0e311599f54eb37"}, - {file = "numpy-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ffbb1acd69fdf8e89dd60ef6182ca90a743620957afb7066385a7bbe88dc748"}, - {file = "numpy-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0349b025e15ea9d05c3d63f9657707a4e1d471128a3b1d876c095f328f8ff7f0"}, - {file = "numpy-2.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:463247edcee4a5537841d5350bc87fe8e92d7dd0e8c71c995d2c6eecb8208278"}, - {file = "numpy-2.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9dd47ff0cb2a656ad69c38da850df3454da88ee9a6fde0ba79acceee0e79daba"}, - {file = "numpy-2.2.2-cp312-cp312-win32.whl", hash = "sha256:4525b88c11906d5ab1b0ec1f290996c0020dd318af8b49acaa46f198b1ffc283"}, - {file = "numpy-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:5acea83b801e98541619af398cc0109ff48016955cc0818f478ee9ef1c5c3dcb"}, - {file = "numpy-2.2.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b208cfd4f5fe34e1535c08983a1a6803fdbc7a1e86cf13dd0c61de0b51a0aadc"}, - {file = "numpy-2.2.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d0bbe7dd86dca64854f4b6ce2ea5c60b51e36dfd597300057cf473d3615f2369"}, - {file = "numpy-2.2.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:22ea3bb552ade325530e72a0c557cdf2dea8914d3a5e1fecf58fa5dbcc6f43cd"}, - {file = "numpy-2.2.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:128c41c085cab8a85dc29e66ed88c05613dccf6bc28b3866cd16050a2f5448be"}, - {file = "numpy-2.2.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:250c16b277e3b809ac20d1f590716597481061b514223c7badb7a0f9993c7f84"}, - {file = "numpy-2.2.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0c8854b09bc4de7b041148d8550d3bd712b5c21ff6a8ed308085f190235d7ff"}, - {file = "numpy-2.2.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b6fb9c32a91ec32a689ec6410def76443e3c750e7cfc3fb2206b985ffb2b85f0"}, - {file = "numpy-2.2.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:57b4012e04cc12b78590a334907e01b3a85efb2107df2b8733ff1ed05fce71de"}, - {file = "numpy-2.2.2-cp313-cp313-win32.whl", hash = "sha256:4dbd80e453bd34bd003b16bd802fac70ad76bd463f81f0c518d1245b1c55e3d9"}, - {file = "numpy-2.2.2-cp313-cp313-win_amd64.whl", hash = "sha256:5a8c863ceacae696aff37d1fd636121f1a512117652e5dfb86031c8d84836369"}, - {file = "numpy-2.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b3482cb7b3325faa5f6bc179649406058253d91ceda359c104dac0ad320e1391"}, - {file = "numpy-2.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9491100aba630910489c1d0158034e1c9a6546f0b1340f716d522dc103788e39"}, - {file = "numpy-2.2.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:41184c416143defa34cc8eb9d070b0a5ba4f13a0fa96a709e20584638254b317"}, - {file = "numpy-2.2.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:7dca87ca328f5ea7dafc907c5ec100d187911f94825f8700caac0b3f4c384b49"}, - {file = "numpy-2.2.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bc61b307655d1a7f9f4b043628b9f2b721e80839914ede634e3d485913e1fb2"}, - {file = "numpy-2.2.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fad446ad0bc886855ddf5909cbf8cb5d0faa637aaa6277fb4b19ade134ab3c7"}, - {file = "numpy-2.2.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:149d1113ac15005652e8d0d3f6fd599360e1a708a4f98e43c9c77834a28238cb"}, - {file = "numpy-2.2.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:106397dbbb1896f99e044efc90360d098b3335060375c26aa89c0d8a97c5f648"}, - {file = "numpy-2.2.2-cp313-cp313t-win32.whl", hash = "sha256:0eec19f8af947a61e968d5429f0bd92fec46d92b0008d0a6685b40d6adf8a4f4"}, - {file = "numpy-2.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:97b974d3ba0fb4612b77ed35d7627490e8e3dff56ab41454d9e8b23448940576"}, - {file = "numpy-2.2.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b0531f0b0e07643eb089df4c509d30d72c9ef40defa53e41363eca8a8cc61495"}, - {file = "numpy-2.2.2-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:e9e82dcb3f2ebbc8cb5ce1102d5f1c5ed236bf8a11730fb45ba82e2841ec21df"}, - {file = "numpy-2.2.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0d4142eb40ca6f94539e4db929410f2a46052a0fe7a2c1c59f6179c39938d2a"}, - {file = "numpy-2.2.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:356ca982c188acbfa6af0d694284d8cf20e95b1c3d0aefa8929376fea9146f60"}, - {file = "numpy-2.2.2.tar.gz", hash = "sha256:ed6906f61834d687738d25988ae117683705636936cc605be0bb208b23df4d8f"}, -] - -[[package]] -name = "opentelemetry-api" -version = "1.29.0" -description = "OpenTelemetry Python API" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "opentelemetry_api-1.29.0-py3-none-any.whl", hash = "sha256:5fcd94c4141cc49c736271f3e1efb777bebe9cc535759c54c936cca4f1b312b8"}, - {file = "opentelemetry_api-1.29.0.tar.gz", hash = "sha256:d04a6cf78aad09614f52964ecb38021e248f5714dc32c2e0d8fd99517b4d69cf"}, -] - -[package.dependencies] -deprecated = ">=1.2.6" -importlib-metadata = ">=6.0,<=8.5.0" - -[[package]] -name = "opentelemetry-exporter-otlp-proto-common" -version = "1.29.0" -description = "OpenTelemetry Protobuf encoding" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "opentelemetry_exporter_otlp_proto_common-1.29.0-py3-none-any.whl", hash = "sha256:a9d7376c06b4da9cf350677bcddb9618ed4b8255c3f6476975f5e38274ecd3aa"}, - {file = "opentelemetry_exporter_otlp_proto_common-1.29.0.tar.gz", hash = "sha256:e7c39b5dbd1b78fe199e40ddfe477e6983cb61aa74ba836df09c3869a3e3e163"}, -] - -[package.dependencies] -opentelemetry-proto = "1.29.0" - -[[package]] -name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.29.0" -description = "OpenTelemetry Collector Protobuf over gRPC Exporter" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "opentelemetry_exporter_otlp_proto_grpc-1.29.0-py3-none-any.whl", hash = "sha256:5a2a3a741a2543ed162676cf3eefc2b4150e6f4f0a193187afb0d0e65039c69c"}, - {file = "opentelemetry_exporter_otlp_proto_grpc-1.29.0.tar.gz", hash = "sha256:3d324d07d64574d72ed178698de3d717f62a059a93b6b7685ee3e303384e73ea"}, -] - -[package.dependencies] -deprecated = ">=1.2.6" -googleapis-common-protos = ">=1.52,<2.0" -grpcio = ">=1.63.2,<2.0.0" -opentelemetry-api = ">=1.15,<2.0" -opentelemetry-exporter-otlp-proto-common = "1.29.0" -opentelemetry-proto = "1.29.0" -opentelemetry-sdk = ">=1.29.0,<1.30.0" - -[[package]] -name = "opentelemetry-proto" -version = "1.29.0" -description = "OpenTelemetry Python Proto" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "opentelemetry_proto-1.29.0-py3-none-any.whl", hash = "sha256:495069c6f5495cbf732501cdcd3b7f60fda2b9d3d4255706ca99b7ca8dec53ff"}, - {file = "opentelemetry_proto-1.29.0.tar.gz", hash = "sha256:3c136aa293782e9b44978c738fff72877a4b78b5d21a64e879898db7b2d93e5d"}, -] - -[package.dependencies] -protobuf = ">=5.0,<6.0" - -[[package]] -name = "opentelemetry-sdk" -version = "1.29.0" -description = "OpenTelemetry Python SDK" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "opentelemetry_sdk-1.29.0-py3-none-any.whl", hash = "sha256:173be3b5d3f8f7d671f20ea37056710217959e774e2749d984355d1f9391a30a"}, - {file = "opentelemetry_sdk-1.29.0.tar.gz", hash = "sha256:b0787ce6aade6ab84315302e72bd7a7f2f014b0fb1b7c3295b88afe014ed0643"}, -] - -[package.dependencies] -opentelemetry-api = "1.29.0" -opentelemetry-semantic-conventions = "0.50b0" -typing-extensions = ">=3.7.4" - -[[package]] -name = "opentelemetry-semantic-conventions" -version = "0.50b0" -description = "OpenTelemetry Semantic Conventions" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "opentelemetry_semantic_conventions-0.50b0-py3-none-any.whl", hash = "sha256:e87efba8fdb67fb38113efea6a349531e75ed7ffc01562f65b802fcecb5e115e"}, - {file = "opentelemetry_semantic_conventions-0.50b0.tar.gz", hash = "sha256:02dc6dbcb62f082de9b877ff19a3f1ffaa3c306300fa53bfac761c4567c83d38"}, -] - -[package.dependencies] -deprecated = ">=1.2.6" -opentelemetry-api = "1.29.0" - -[[package]] -name = "pandas" -version = "2.2.3" -description = "Powerful data structures for data analysis, time series, and statistics" -optional = false -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5"}, - {file = "pandas-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348"}, - {file = "pandas-2.2.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d9c45366def9a3dd85a6454c0e7908f2b3b8e9c138f5dc38fed7ce720d8453ed"}, - {file = "pandas-2.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57"}, - {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b8661b0238a69d7aafe156b7fa86c44b881387509653fdf857bebc5e4008ad42"}, - {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f"}, - {file = "pandas-2.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645"}, - {file = "pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039"}, - {file = "pandas-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd"}, - {file = "pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698"}, - {file = "pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc"}, - {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3"}, - {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32"}, - {file = "pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5"}, - {file = "pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9"}, - {file = "pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4"}, - {file = "pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3"}, - {file = "pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319"}, - {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8"}, - {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a"}, - {file = "pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13"}, - {file = "pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015"}, - {file = "pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28"}, - {file = "pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0"}, - {file = "pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24"}, - {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659"}, - {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb"}, - {file = "pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d"}, - {file = "pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468"}, - {file = "pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18"}, - {file = "pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2"}, - {file = "pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4"}, - {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d"}, - {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a"}, - {file = "pandas-2.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc6b93f9b966093cb0fd62ff1a7e4c09e6d546ad7c1de191767baffc57628f39"}, - {file = "pandas-2.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5dbca4c1acd72e8eeef4753eeca07de9b1db4f398669d5994086f788a5d7cc30"}, - {file = "pandas-2.2.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8cd6d7cc958a3910f934ea8dbdf17b2364827bb4dafc38ce6eef6bb3d65ff09c"}, - {file = "pandas-2.2.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99df71520d25fade9db7c1076ac94eb994f4d2673ef2aa2e86ee039b6746d20c"}, - {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31d0ced62d4ea3e231a9f228366919a5ea0b07440d9d4dac345376fd8e1477ea"}, - {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7eee9e7cea6adf3e3d24e304ac6b8300646e2a5d1cd3a3c2abed9101b0846761"}, - {file = "pandas-2.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e"}, - {file = "pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667"}, -] - -[package.dependencies] -numpy = [ - {version = ">=1.23.2", markers = "python_version == \"3.11\""}, - {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, -] -python-dateutil = ">=2.8.2" -pytz = ">=2020.1" -tzdata = ">=2022.7" - -[package.extras] -all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] -aws = ["s3fs (>=2022.11.0)"] -clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] -compression = ["zstandard (>=0.19.0)"] -computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] -consortium-standard = ["dataframe-api-compat (>=0.1.7)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] -feather = ["pyarrow (>=10.0.1)"] -fss = ["fsspec (>=2022.11.0)"] -gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] -hdf5 = ["tables (>=3.8.0)"] -html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] -mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] -output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] -parquet = ["pyarrow (>=10.0.1)"] -performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] -plot = ["matplotlib (>=3.6.3)"] -postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] -pyarrow = ["pyarrow (>=10.0.1)"] -spss = ["pyreadstat (>=1.2.0)"] -sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] -test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] -xml = ["lxml (>=4.9.2)"] - -[[package]] -name = "platformdirs" -version = "4.3.6" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, - {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.11.2)"] - -[[package]] -name = "propcache" -version = "0.2.1" -description = "Accelerated property cache" -optional = false -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6"}, - {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2"}, - {file = "propcache-0.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6445804cf4ec763dc70de65a3b0d9954e868609e83850a47ca4f0cb64bd79fea"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9479aa06a793c5aeba49ce5c5692ffb51fcd9a7016e017d555d5e2b0045d212"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9631c5e8b5b3a0fda99cb0d29c18133bca1e18aea9effe55adb3da1adef80d3"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3156628250f46a0895f1f36e1d4fbe062a1af8718ec3ebeb746f1d23f0c5dc4d"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b6fb63ae352e13748289f04f37868099e69dba4c2b3e271c46061e82c745634"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:887d9b0a65404929641a9fabb6452b07fe4572b269d901d622d8a34a4e9043b2"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a96dc1fa45bd8c407a0af03b2d5218392729e1822b0c32e62c5bf7eeb5fb3958"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a7e65eb5c003a303b94aa2c3852ef130230ec79e349632d030e9571b87c4698c"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:999779addc413181912e984b942fbcc951be1f5b3663cd80b2687758f434c583"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:19a0f89a7bb9d8048d9c4370c9c543c396e894c76be5525f5e1ad287f1750ddf"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1ac2f5fe02fa75f56e1ad473f1175e11f475606ec9bd0be2e78e4734ad575034"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:574faa3b79e8ebac7cb1d7930f51184ba1ccf69adfdec53a12f319a06030a68b"}, - {file = "propcache-0.2.1-cp310-cp310-win32.whl", hash = "sha256:03ff9d3f665769b2a85e6157ac8b439644f2d7fd17615a82fa55739bc97863f4"}, - {file = "propcache-0.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:2d3af2e79991102678f53e0dbf4c35de99b6b8b58f29a27ca0325816364caaba"}, - {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16"}, - {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717"}, - {file = "propcache-0.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e"}, - {file = "propcache-0.2.1-cp311-cp311-win32.whl", hash = "sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034"}, - {file = "propcache-0.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3"}, - {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a"}, - {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0"}, - {file = "propcache-0.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518"}, - {file = "propcache-0.2.1-cp312-cp312-win32.whl", hash = "sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246"}, - {file = "propcache-0.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1"}, - {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc"}, - {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9"}, - {file = "propcache-0.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30"}, - {file = "propcache-0.2.1-cp313-cp313-win32.whl", hash = "sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6"}, - {file = "propcache-0.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1"}, - {file = "propcache-0.2.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6a9a8c34fb7bb609419a211e59da8887eeca40d300b5ea8e56af98f6fbbb1541"}, - {file = "propcache-0.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae1aa1cd222c6d205853b3013c69cd04515f9d6ab6de4b0603e2e1c33221303e"}, - {file = "propcache-0.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:accb6150ce61c9c4b7738d45550806aa2b71c7668c6942f17b0ac182b6142fd4"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eee736daafa7af6d0a2dc15cc75e05c64f37fc37bafef2e00d77c14171c2097"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7a31fc1e1bd362874863fdeed71aed92d348f5336fd84f2197ba40c59f061bd"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba4cfa1052819d16699e1d55d18c92b6e094d4517c41dd231a8b9f87b6fa681"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f089118d584e859c62b3da0892b88a83d611c2033ac410e929cb6754eec0ed16"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:781e65134efaf88feb447e8c97a51772aa75e48b794352f94cb7ea717dedda0d"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31f5af773530fd3c658b32b6bdc2d0838543de70eb9a2156c03e410f7b0d3aae"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:a7a078f5d37bee6690959c813977da5291b24286e7b962e62a94cec31aa5188b"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cea7daf9fc7ae6687cf1e2c049752f19f146fdc37c2cc376e7d0032cf4f25347"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:8b3489ff1ed1e8315674d0775dc7d2195fb13ca17b3808721b54dbe9fd020faf"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9403db39be1393618dd80c746cb22ccda168efce239c73af13c3763ef56ffc04"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5d97151bc92d2b2578ff7ce779cdb9174337390a535953cbb9452fb65164c587"}, - {file = "propcache-0.2.1-cp39-cp39-win32.whl", hash = "sha256:9caac6b54914bdf41bcc91e7eb9147d331d29235a7c967c150ef5df6464fd1bb"}, - {file = "propcache-0.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:92fc4500fcb33899b05ba73276dfb684a20d31caa567b7cb5252d48f896a91b1"}, - {file = "propcache-0.2.1-py3-none-any.whl", hash = "sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54"}, - {file = "propcache-0.2.1.tar.gz", hash = "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64"}, -] - -[[package]] -name = "proto-plus" -version = "1.26.0" -description = "Beautiful, Pythonic protocol buffers" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "proto_plus-1.26.0-py3-none-any.whl", hash = "sha256:bf2dfaa3da281fc3187d12d224c707cb57214fb2c22ba854eb0c105a3fb2d4d7"}, - {file = "proto_plus-1.26.0.tar.gz", hash = "sha256:6e93d5f5ca267b54300880fff156b6a3386b3fa3f43b1da62e680fc0c586ef22"}, -] - -[package.dependencies] -protobuf = ">=3.19.0,<6.0.0dev" - -[package.extras] -testing = ["google-api-core (>=1.31.5)"] - -[[package]] -name = "protobuf" -version = "5.29.3" -description = "" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "protobuf-5.29.3-cp310-abi3-win32.whl", hash = "sha256:3ea51771449e1035f26069c4c7fd51fba990d07bc55ba80701c78f886bf9c888"}, - {file = "protobuf-5.29.3-cp310-abi3-win_amd64.whl", hash = "sha256:a4fa6f80816a9a0678429e84973f2f98cbc218cca434abe8db2ad0bffc98503a"}, - {file = "protobuf-5.29.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a8434404bbf139aa9e1300dbf989667a83d42ddda9153d8ab76e0d5dcaca484e"}, - {file = "protobuf-5.29.3-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:daaf63f70f25e8689c072cfad4334ca0ac1d1e05a92fc15c54eb9cf23c3efd84"}, - {file = "protobuf-5.29.3-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:c027e08a08be10b67c06bf2370b99c811c466398c357e615ca88c91c07f0910f"}, - {file = "protobuf-5.29.3-cp38-cp38-win32.whl", hash = "sha256:84a57163a0ccef3f96e4b6a20516cedcf5bb3a95a657131c5c3ac62200d23252"}, - {file = "protobuf-5.29.3-cp38-cp38-win_amd64.whl", hash = "sha256:b89c115d877892a512f79a8114564fb435943b59067615894c3b13cd3e1fa107"}, - {file = "protobuf-5.29.3-cp39-cp39-win32.whl", hash = "sha256:0eb32bfa5219fc8d4111803e9a690658aa2e6366384fd0851064b963b6d1f2a7"}, - {file = "protobuf-5.29.3-cp39-cp39-win_amd64.whl", hash = "sha256:6ce8cc3389a20693bfde6c6562e03474c40851b44975c9b2bf6df7d8c4f864da"}, - {file = "protobuf-5.29.3-py3-none-any.whl", hash = "sha256:0a18ed4a24198528f2333802eb075e59dea9d679ab7a6c5efb017a59004d849f"}, - {file = "protobuf-5.29.3.tar.gz", hash = "sha256:5da0f41edaf117bde316404bad1a486cb4ededf8e4a54891296f648e8e076620"}, -] - -[[package]] -name = "pyasn1" -version = "0.6.1" -description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"}, - {file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"}, -] - -[[package]] -name = "pyasn1-modules" -version = "0.4.1" -description = "A collection of ASN.1-based protocols modules" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd"}, - {file = "pyasn1_modules-0.4.1.tar.gz", hash = "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c"}, -] - -[package.dependencies] -pyasn1 = ">=0.4.6,<0.7.0" - -[[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, -] - -[[package]] -name = "pydantic" -version = "1.10.21" -description = "Data validation and settings management using python type hints" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "pydantic-1.10.21-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:245e486e0fec53ec2366df9cf1cba36e0bbf066af7cd9c974bbbd9ba10e1e586"}, - {file = "pydantic-1.10.21-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6c54f8d4c151c1de784c5b93dfbb872067e3414619e10e21e695f7bb84d1d1fd"}, - {file = "pydantic-1.10.21-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b64708009cfabd9c2211295144ff455ec7ceb4c4fb45a07a804309598f36187"}, - {file = "pydantic-1.10.21-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a148410fa0e971ba333358d11a6dea7b48e063de127c2b09ece9d1c1137dde4"}, - {file = "pydantic-1.10.21-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:36ceadef055af06e7756eb4b871cdc9e5a27bdc06a45c820cd94b443de019bbf"}, - {file = "pydantic-1.10.21-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0501e1d12df6ab1211b8cad52d2f7b2cd81f8e8e776d39aa5e71e2998d0379f"}, - {file = "pydantic-1.10.21-cp310-cp310-win_amd64.whl", hash = "sha256:c261127c275d7bce50b26b26c7d8427dcb5c4803e840e913f8d9df3f99dca55f"}, - {file = "pydantic-1.10.21-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8b6350b68566bb6b164fb06a3772e878887f3c857c46c0c534788081cb48adf4"}, - {file = "pydantic-1.10.21-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:935b19fdcde236f4fbf691959fa5c3e2b6951fff132964e869e57c70f2ad1ba3"}, - {file = "pydantic-1.10.21-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b6a04efdcd25486b27f24c1648d5adc1633ad8b4506d0e96e5367f075ed2e0b"}, - {file = "pydantic-1.10.21-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1ba253eb5af8d89864073e6ce8e6c8dec5f49920cff61f38f5c3383e38b1c9f"}, - {file = "pydantic-1.10.21-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:57f0101e6c97b411f287a0b7cf5ebc4e5d3b18254bf926f45a11615d29475793"}, - {file = "pydantic-1.10.21-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90e85834f0370d737c77a386ce505c21b06bfe7086c1c568b70e15a568d9670d"}, - {file = "pydantic-1.10.21-cp311-cp311-win_amd64.whl", hash = "sha256:6a497bc66b3374b7d105763d1d3de76d949287bf28969bff4656206ab8a53aa9"}, - {file = "pydantic-1.10.21-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2ed4a5f13cf160d64aa331ab9017af81f3481cd9fd0e49f1d707b57fe1b9f3ae"}, - {file = "pydantic-1.10.21-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3b7693bb6ed3fbe250e222f9415abb73111bb09b73ab90d2d4d53f6390e0ccc1"}, - {file = "pydantic-1.10.21-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185d5f1dff1fead51766da9b2de4f3dc3b8fca39e59383c273f34a6ae254e3e2"}, - {file = "pydantic-1.10.21-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38e6d35cf7cd1727822c79e324fa0677e1a08c88a34f56695101f5ad4d5e20e5"}, - {file = "pydantic-1.10.21-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:1d7c332685eafacb64a1a7645b409a166eb7537f23142d26895746f628a3149b"}, - {file = "pydantic-1.10.21-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c9b782db6f993a36092480eeaab8ba0609f786041b01f39c7c52252bda6d85f"}, - {file = "pydantic-1.10.21-cp312-cp312-win_amd64.whl", hash = "sha256:7ce64d23d4e71d9698492479505674c5c5b92cda02b07c91dfc13633b2eef805"}, - {file = "pydantic-1.10.21-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0067935d35044950be781933ab91b9a708eaff124bf860fa2f70aeb1c4be7212"}, - {file = "pydantic-1.10.21-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5e8148c2ce4894ce7e5a4925d9d3fdce429fb0e821b5a8783573f3611933a251"}, - {file = "pydantic-1.10.21-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4973232c98b9b44c78b1233693e5e1938add5af18042f031737e1214455f9b8"}, - {file = "pydantic-1.10.21-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:662bf5ce3c9b1cef32a32a2f4debe00d2f4839fefbebe1d6956e681122a9c839"}, - {file = "pydantic-1.10.21-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:98737c3ab5a2f8a85f2326eebcd214510f898881a290a7939a45ec294743c875"}, - {file = "pydantic-1.10.21-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0bb58bbe65a43483d49f66b6c8474424d551a3fbe8a7796c42da314bac712738"}, - {file = "pydantic-1.10.21-cp313-cp313-win_amd64.whl", hash = "sha256:e622314542fb48542c09c7bd1ac51d71c5632dd3c92dc82ede6da233f55f4848"}, - {file = "pydantic-1.10.21-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d356aa5b18ef5a24d8081f5c5beb67c0a2a6ff2a953ee38d65a2aa96526b274f"}, - {file = "pydantic-1.10.21-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08caa8c0468172d27c669abfe9e7d96a8b1655ec0833753e117061febaaadef5"}, - {file = "pydantic-1.10.21-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c677aa39ec737fec932feb68e4a2abe142682f2885558402602cd9746a1c92e8"}, - {file = "pydantic-1.10.21-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:79577cc045d3442c4e845df53df9f9202546e2ba54954c057d253fc17cd16cb1"}, - {file = "pydantic-1.10.21-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:b6b73ab347284719f818acb14f7cd80696c6fdf1bd34feee1955d7a72d2e64ce"}, - {file = "pydantic-1.10.21-cp37-cp37m-win_amd64.whl", hash = "sha256:46cffa24891b06269e12f7e1ec50b73f0c9ab4ce71c2caa4ccf1fb36845e1ff7"}, - {file = "pydantic-1.10.21-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:298d6f765e3c9825dfa78f24c1efd29af91c3ab1b763e1fd26ae4d9e1749e5c8"}, - {file = "pydantic-1.10.21-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f2f4a2305f15eff68f874766d982114ac89468f1c2c0b97640e719cf1a078374"}, - {file = "pydantic-1.10.21-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35b263b60c519354afb3a60107d20470dd5250b3ce54c08753f6975c406d949b"}, - {file = "pydantic-1.10.21-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e23a97a6c2f2db88995496db9387cd1727acdacc85835ba8619dce826c0b11a6"}, - {file = "pydantic-1.10.21-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:3c96fed246ccc1acb2df032ff642459e4ae18b315ecbab4d95c95cfa292e8517"}, - {file = "pydantic-1.10.21-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:b92893ebefc0151474f682e7debb6ab38552ce56a90e39a8834734c81f37c8a9"}, - {file = "pydantic-1.10.21-cp38-cp38-win_amd64.whl", hash = "sha256:b8460bc256bf0de821839aea6794bb38a4c0fbd48f949ea51093f6edce0be459"}, - {file = "pydantic-1.10.21-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5d387940f0f1a0adb3c44481aa379122d06df8486cc8f652a7b3b0caf08435f7"}, - {file = "pydantic-1.10.21-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:266ecfc384861d7b0b9c214788ddff75a2ea123aa756bcca6b2a1175edeca0fe"}, - {file = "pydantic-1.10.21-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61da798c05a06a362a2f8c5e3ff0341743e2818d0f530eaac0d6898f1b187f1f"}, - {file = "pydantic-1.10.21-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a621742da75ce272d64ea57bd7651ee2a115fa67c0f11d66d9dcfc18c2f1b106"}, - {file = "pydantic-1.10.21-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9e3e4000cd54ef455694b8be9111ea20f66a686fc155feda1ecacf2322b115da"}, - {file = "pydantic-1.10.21-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f198c8206640f4c0ef5a76b779241efb1380a300d88b1bce9bfe95a6362e674d"}, - {file = "pydantic-1.10.21-cp39-cp39-win_amd64.whl", hash = "sha256:e7f0cda108b36a30c8fc882e4fc5b7eec8ef584aa43aa43694c6a7b274fb2b56"}, - {file = "pydantic-1.10.21-py3-none-any.whl", hash = "sha256:db70c920cba9d05c69ad4a9e7f8e9e83011abb2c6490e561de9ae24aee44925c"}, - {file = "pydantic-1.10.21.tar.gz", hash = "sha256:64b48e2b609a6c22178a56c408ee1215a7206077ecb8a193e2fda31858b2362a"}, -] - -[package.dependencies] -typing-extensions = ">=4.2.0" - -[package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] - -[[package]] -name = "pydash" -version = "6.0.2" -description = "The kitchen sink of Python utility libraries for doing \"stuff\" in a functional way. Based on the Lo-Dash Javascript library." -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "pydash-6.0.2-py3-none-any.whl", hash = "sha256:6d3ce5cbbc8ca3533c12782ac201c2ec756d1e1703ec3efc88f2b95d1ed2bb31"}, - {file = "pydash-6.0.2.tar.gz", hash = "sha256:35caa588e01d293713655e0870544d25128cd414c5e19477a0d63adc2b2ca03e"}, -] - -[package.extras] -dev = ["Sphinx", "black", "build", "coverage", "docformatter", "flake8", "flake8-black", "flake8-bugbear", "flake8-isort", "importlib-metadata (<5)", "invoke", "isort", "pylint", "pytest", "pytest-cov", "sphinx-rtd-theme", "tox", "twine", "wheel"] - -[[package]] -name = "pygithub" -version = "2.5.0" -description = "Use the full Github API v3" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "PyGithub-2.5.0-py3-none-any.whl", hash = "sha256:b0b635999a658ab8e08720bdd3318893ff20e2275f6446fcf35bf3f44f2c0fd2"}, - {file = "pygithub-2.5.0.tar.gz", hash = "sha256:e1613ac508a9be710920d26eb18b1905ebd9926aa49398e88151c1b526aad3cf"}, -] - -[package.dependencies] -Deprecated = "*" -pyjwt = {version = ">=2.4.0", extras = ["crypto"]} -pynacl = ">=1.4.0" -requests = ">=2.14.0" -typing-extensions = ">=4.0.0" -urllib3 = ">=1.26.0" - -[[package]] -name = "pygments" -version = "2.19.1" -description = "Pygments is a syntax highlighting package written in Python." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, - {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, -] - -[package.extras] -windows-terminal = ["colorama (>=0.4.6)"] - -[[package]] -name = "pyjwt" -version = "2.8.0" -description = "JSON Web Token implementation in Python" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, - {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, -] - -[package.dependencies] -cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"crypto\""} - -[package.extras] -crypto = ["cryptography (>=3.4.0)"] -dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] -docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] - -[[package]] -name = "pynacl" -version = "1.5.0" -description = "Python binding to the Networking and Cryptography (NaCl) library" -optional = false -python-versions = ">=3.6" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, - {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, -] - -[package.dependencies] -cffi = ">=1.4.1" - -[package.extras] -docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] -tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, - {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "pytz" -version = "2025.1" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "pytz-2025.1-py2.py3-none-any.whl", hash = "sha256:89dd22dca55b46eac6eda23b2d72721bf1bdfef212645d81513ef5d03038de57"}, - {file = "pytz-2025.1.tar.gz", hash = "sha256:c2db42be2a2518b28e65f9207c4d05e6ff547d1efa4086469ef855e4ab70178e"}, -] - -[[package]] -name = "pyyaml" -version = "6.0.2" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, - {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, - {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, - {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, - {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, - {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, - {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, - {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, - {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, - {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, - {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, - {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, - {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, - {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, - {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, - {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, - {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, -] - -[[package]] -name = "requests" -version = "2.32.3" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, - {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "rich" -version = "13.9.4" -description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -optional = false -python-versions = ">=3.8.0" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"}, - {file = "rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098"}, -] - -[package.dependencies] -markdown-it-py = ">=2.2.0" -pygments = ">=2.13.0,<3.0.0" - -[package.extras] -jupyter = ["ipywidgets (>=7.5.1,<9)"] - -[[package]] -name = "rsa" -version = "4.9" -description = "Pure-Python RSA implementation" -optional = false -python-versions = ">=3.6,<4" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, - {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, -] - -[package.dependencies] -pyasn1 = ">=0.1.3" - -[[package]] -name = "ruff" -version = "0.4.10" -description = "An extremely fast Python linter and code formatter, written in Rust." -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "ruff-0.4.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5c2c4d0859305ac5a16310eec40e4e9a9dec5dcdfbe92697acd99624e8638dac"}, - {file = "ruff-0.4.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a79489607d1495685cdd911a323a35871abfb7a95d4f98fc6f85e799227ac46e"}, - {file = "ruff-0.4.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1dd1681dfa90a41b8376a61af05cc4dc5ff32c8f14f5fe20dba9ff5deb80cd6"}, - {file = "ruff-0.4.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c75c53bb79d71310dc79fb69eb4902fba804a81f374bc86a9b117a8d077a1784"}, - {file = "ruff-0.4.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18238c80ee3d9100d3535d8eb15a59c4a0753b45cc55f8bf38f38d6a597b9739"}, - {file = "ruff-0.4.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d8f71885bce242da344989cae08e263de29752f094233f932d4f5cfb4ef36a81"}, - {file = "ruff-0.4.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:330421543bd3222cdfec481e8ff3460e8702ed1e58b494cf9d9e4bf90db52b9d"}, - {file = "ruff-0.4.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e9b6fb3a37b772628415b00c4fc892f97954275394ed611056a4b8a2631365e"}, - {file = "ruff-0.4.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f54c481b39a762d48f64d97351048e842861c6662d63ec599f67d515cb417f6"}, - {file = "ruff-0.4.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:67fe086b433b965c22de0b4259ddfe6fa541c95bf418499bedb9ad5fb8d1c631"}, - {file = "ruff-0.4.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:acfaaab59543382085f9eb51f8e87bac26bf96b164839955f244d07125a982ef"}, - {file = "ruff-0.4.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3cea07079962b2941244191569cf3a05541477286f5cafea638cd3aa94b56815"}, - {file = "ruff-0.4.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:338a64ef0748f8c3a80d7f05785930f7965d71ca260904a9321d13be24b79695"}, - {file = "ruff-0.4.10-py3-none-win32.whl", hash = "sha256:ffe3cd2f89cb54561c62e5fa20e8f182c0a444934bf430515a4b422f1ab7b7ca"}, - {file = "ruff-0.4.10-py3-none-win_amd64.whl", hash = "sha256:67f67cef43c55ffc8cc59e8e0b97e9e60b4837c8f21e8ab5ffd5d66e196e25f7"}, - {file = "ruff-0.4.10-py3-none-win_arm64.whl", hash = "sha256:dd1fcee327c20addac7916ca4e2653fbbf2e8388d8a6477ce5b4e986b68ae6c0"}, - {file = "ruff-0.4.10.tar.gz", hash = "sha256:3aa4f2bc388a30d346c56524f7cacca85945ba124945fe489952aadb6b5cd804"}, -] - -[[package]] -name = "semver" -version = "3.0.4" -description = "Python helper for Semantic Versioning (https://semver.org)" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "semver-3.0.4-py3-none-any.whl", hash = "sha256:9c824d87ba7f7ab4a1890799cec8596f15c1241cb473404ea1cb0c55e4b04746"}, - {file = "semver-3.0.4.tar.gz", hash = "sha256:afc7d8c584a5ed0a11033af086e8af226a9c0b206f313e0301f8dd7b6b589602"}, -] - -[[package]] -name = "simpleeval" -version = "0.9.13" -description = "A simple, safe single expression evaluator library." -optional = false -python-versions = "*" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "simpleeval-0.9.13-py2.py3-none-any.whl", hash = "sha256:22a2701a5006e4188d125d34accf2405c2c37c93f6b346f2484b6422415ae54a"}, - {file = "simpleeval-0.9.13.tar.gz", hash = "sha256:4a30f9cc01825fe4c719c785e3762623e350c4840d5e6855c2a8496baaa65fac"}, -] - -[[package]] -name = "six" -version = "1.17.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, - {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, -] - -[[package]] -name = "smmap" -version = "5.0.2" -description = "A pure Python implementation of a sliding window memory map manager" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e"}, - {file = "smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5"}, -] - -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - -[[package]] -name = "soupsieve" -version = "2.6" -description = "A modern CSS selector implementation for Beautiful Soup." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"}, - {file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"}, -] - -[[package]] -name = "types-beautifulsoup4" -version = "4.12.0.20241020" -description = "Typing stubs for beautifulsoup4" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "types-beautifulsoup4-4.12.0.20241020.tar.gz", hash = "sha256:158370d08d0cd448bd11b132a50ff5279237a5d4b5837beba074de152a513059"}, - {file = "types_beautifulsoup4-4.12.0.20241020-py3-none-any.whl", hash = "sha256:c95e66ce15a4f5f0835f7fbc5cd886321ae8294f977c495424eaf4225307fd30"}, -] - -[package.dependencies] -types-html5lib = "*" - -[[package]] -name = "types-html5lib" -version = "1.1.11.20241018" -description = "Typing stubs for html5lib" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "types-html5lib-1.1.11.20241018.tar.gz", hash = "sha256:98042555ff78d9e3a51c77c918b1041acbb7eb6c405408d8a9e150ff5beccafa"}, - {file = "types_html5lib-1.1.11.20241018-py3-none-any.whl", hash = "sha256:3f1e064d9ed2c289001ae6392c84c93833abb0816165c6ff0abfc304a779f403"}, -] - -[[package]] -name = "types-requests" -version = "2.32.0.20241016" -description = "Typing stubs for requests" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "types-requests-2.32.0.20241016.tar.gz", hash = "sha256:0d9cad2f27515d0e3e3da7134a1b6f28fb97129d86b867f24d9c726452634d95"}, - {file = "types_requests-2.32.0.20241016-py3-none-any.whl", hash = "sha256:4195d62d6d3e043a4eaaf08ff8a62184584d2e8684e9d2aa178c7915a7da3747"}, -] - -[package.dependencies] -urllib3 = ">=2" - -[[package]] -name = "typing-extensions" -version = "4.12.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, -] - -[[package]] -name = "tzdata" -version = "2025.1" -description = "Provider of IANA time zone data" -optional = false -python-versions = ">=2" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639"}, - {file = "tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694"}, -] - -[[package]] -name = "urllib3" -version = "2.3.0" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.9" -groups = ["main", "dev"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, - {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "wrapt" -version = "1.17.2" -description = "Module for decorators, wrappers and monkey patching." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, - {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, - {file = "wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7"}, - {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c"}, - {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72"}, - {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061"}, - {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2"}, - {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c"}, - {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62"}, - {file = "wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563"}, - {file = "wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f"}, - {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58"}, - {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda"}, - {file = "wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438"}, - {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a"}, - {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000"}, - {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6"}, - {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b"}, - {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662"}, - {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72"}, - {file = "wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317"}, - {file = "wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3"}, - {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925"}, - {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392"}, - {file = "wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40"}, - {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d"}, - {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b"}, - {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98"}, - {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82"}, - {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae"}, - {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9"}, - {file = "wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9"}, - {file = "wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991"}, - {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125"}, - {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998"}, - {file = "wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5"}, - {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8"}, - {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6"}, - {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc"}, - {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2"}, - {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b"}, - {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504"}, - {file = "wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a"}, - {file = "wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845"}, - {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192"}, - {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b"}, - {file = "wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0"}, - {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306"}, - {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb"}, - {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681"}, - {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6"}, - {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6"}, - {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f"}, - {file = "wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555"}, - {file = "wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c"}, - {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9"}, - {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119"}, - {file = "wrapt-1.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6"}, - {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9"}, - {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a"}, - {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2"}, - {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a"}, - {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04"}, - {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f"}, - {file = "wrapt-1.17.2-cp38-cp38-win32.whl", hash = "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7"}, - {file = "wrapt-1.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3"}, - {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a"}, - {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061"}, - {file = "wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82"}, - {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9"}, - {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f"}, - {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b"}, - {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f"}, - {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8"}, - {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9"}, - {file = "wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb"}, - {file = "wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb"}, - {file = "wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8"}, - {file = "wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3"}, -] - -[[package]] -name = "yarl" -version = "1.18.3" -description = "Yet another URL library" -optional = false -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34"}, - {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7"}, - {file = "yarl-1.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:602d98f2c2d929f8e697ed274fbadc09902c4025c5a9963bf4e9edfc3ab6f7ed"}, - {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c654d5207c78e0bd6d749f6dae1dcbbfde3403ad3a4b11f3c5544d9906969dde"}, - {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5094d9206c64181d0f6e76ebd8fb2f8fe274950a63890ee9e0ebfd58bf9d787b"}, - {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35098b24e0327fc4ebdc8ffe336cee0a87a700c24ffed13161af80124b7dc8e5"}, - {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3236da9272872443f81fedc389bace88408f64f89f75d1bdb2256069a8730ccc"}, - {file = "yarl-1.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2c08cc9b16f4f4bc522771d96734c7901e7ebef70c6c5c35dd0f10845270bcd"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:80316a8bd5109320d38eef8833ccf5f89608c9107d02d2a7f985f98ed6876990"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c1e1cc06da1491e6734f0ea1e6294ce00792193c463350626571c287c9a704db"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fea09ca13323376a2fdfb353a5fa2e59f90cd18d7ca4eaa1fd31f0a8b4f91e62"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e3b9fd71836999aad54084906f8663dffcd2a7fb5cdafd6c37713b2e72be1760"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:757e81cae69244257d125ff31663249b3013b5dc0a8520d73694aed497fb195b"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b1771de9944d875f1b98a745bc547e684b863abf8f8287da8466cf470ef52690"}, - {file = "yarl-1.18.3-cp310-cp310-win32.whl", hash = "sha256:8874027a53e3aea659a6d62751800cf6e63314c160fd607489ba5c2edd753cf6"}, - {file = "yarl-1.18.3-cp310-cp310-win_amd64.whl", hash = "sha256:93b2e109287f93db79210f86deb6b9bbb81ac32fc97236b16f7433db7fc437d8"}, - {file = "yarl-1.18.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069"}, - {file = "yarl-1.18.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193"}, - {file = "yarl-1.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889"}, - {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8"}, - {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca"}, - {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8"}, - {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae"}, - {file = "yarl-1.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a"}, - {file = "yarl-1.18.3-cp311-cp311-win32.whl", hash = "sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1"}, - {file = "yarl-1.18.3-cp311-cp311-win_amd64.whl", hash = "sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5"}, - {file = "yarl-1.18.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50"}, - {file = "yarl-1.18.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576"}, - {file = "yarl-1.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640"}, - {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2"}, - {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75"}, - {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512"}, - {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba"}, - {file = "yarl-1.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285"}, - {file = "yarl-1.18.3-cp312-cp312-win32.whl", hash = "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2"}, - {file = "yarl-1.18.3-cp312-cp312-win_amd64.whl", hash = "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477"}, - {file = "yarl-1.18.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb"}, - {file = "yarl-1.18.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa"}, - {file = "yarl-1.18.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782"}, - {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0"}, - {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482"}, - {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186"}, - {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58"}, - {file = "yarl-1.18.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8"}, - {file = "yarl-1.18.3-cp313-cp313-win32.whl", hash = "sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d"}, - {file = "yarl-1.18.3-cp313-cp313-win_amd64.whl", hash = "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c"}, - {file = "yarl-1.18.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:61e5e68cb65ac8f547f6b5ef933f510134a6bf31bb178be428994b0cb46c2a04"}, - {file = "yarl-1.18.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fe57328fbc1bfd0bd0514470ac692630f3901c0ee39052ae47acd1d90a436719"}, - {file = "yarl-1.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a440a2a624683108a1b454705ecd7afc1c3438a08e890a1513d468671d90a04e"}, - {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09c7907c8548bcd6ab860e5f513e727c53b4a714f459b084f6580b49fa1b9cee"}, - {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4f6450109834af88cb4cc5ecddfc5380ebb9c228695afc11915a0bf82116789"}, - {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9ca04806f3be0ac6d558fffc2fdf8fcef767e0489d2684a21912cc4ed0cd1b8"}, - {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77a6e85b90a7641d2e07184df5557132a337f136250caafc9ccaa4a2a998ca2c"}, - {file = "yarl-1.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6333c5a377c8e2f5fae35e7b8f145c617b02c939d04110c76f29ee3676b5f9a5"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0b3c92fa08759dbf12b3a59579a4096ba9af8dd344d9a813fc7f5070d86bbab1"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4ac515b860c36becb81bb84b667466885096b5fc85596948548b667da3bf9f24"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:045b8482ce9483ada4f3f23b3774f4e1bf4f23a2d5c912ed5170f68efb053318"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:a4bb030cf46a434ec0225bddbebd4b89e6471814ca851abb8696170adb163985"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:54d6921f07555713b9300bee9c50fb46e57e2e639027089b1d795ecd9f7fa910"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1d407181cfa6e70077df3377938c08012d18893f9f20e92f7d2f314a437c30b1"}, - {file = "yarl-1.18.3-cp39-cp39-win32.whl", hash = "sha256:ac36703a585e0929b032fbaab0707b75dc12703766d0b53486eabd5139ebadd5"}, - {file = "yarl-1.18.3-cp39-cp39-win_amd64.whl", hash = "sha256:ba87babd629f8af77f557b61e49e7c7cac36f22f871156b91e10a6e9d4f829e9"}, - {file = "yarl-1.18.3-py3-none-any.whl", hash = "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b"}, - {file = "yarl-1.18.3.tar.gz", hash = "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1"}, -] - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" -propcache = ">=0.2.0" - -[[package]] -name = "zipp" -version = "3.21.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -optional = false -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version == \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, - {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, -] - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] -type = ["pytest-mypy"] - -[metadata] -lock-version = "2.1" -python-versions = "^3.11" -content-hash = "0ff88ea1d411afca3b23762cc84070b3c1ca422225fad5041bfbff0191a39b78" diff --git a/airbyte-ci/connectors/connectors_insights/pyproject.toml b/airbyte-ci/connectors/connectors_insights/pyproject.toml deleted file mode 100644 index be58b4b9d54e..000000000000 --- a/airbyte-ci/connectors/connectors_insights/pyproject.toml +++ /dev/null @@ -1,48 +0,0 @@ -[tool.poetry] -name = "connectors-insights" -version = "0.3.7" -description = "" -authors = ["Airbyte "] -readme = "README.md" -packages = [{ include = "connectors_insights", from = "src" }] - -[tool.poetry.dependencies] -python = "^3.11" -dagger-io = "0.13.3" -click = "^8.1.7" -pydantic = "^1.9" -asyncer = "^0.0.7" -asyncclick = "^8.1.7.2" -connector-ops = { path = "../connector_ops", develop = false } -beautifulsoup4 = "^4.12.3" -requests = "^2.32.3" -google-cloud-storage = "^2.17.0" -ruff = "^0.4.8" - -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" - -[tool.poetry.scripts] -connectors-insights = "connectors_insights.cli:connectors_insights" - -[tool.poetry.group.dev.dependencies] -mypy = "^1.8.0" -types-requests = "^2.32.0.20240602" -types-beautifulsoup4 = "^4.12.0.20240511" - -[tool.ruff] -line-length = 140 - -[tool.ruff.lint] -select = ["F"] - -[tool.poe.tasks] -type_check = "mypy src --disallow-untyped-defs" -lint = "ruff check src --fix" -ci = ["type_check", "lint"] - -[tool.airbyte_ci] -python_versions = ["3.11"] -optional_poetry_groups = ["dev"] -poe_tasks = ["ci"] diff --git a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/__init__.py b/airbyte-ci/connectors/connectors_insights/src/connectors_insights/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/cli.py b/airbyte-ci/connectors/connectors_insights/src/connectors_insights/cli.py deleted file mode 100644 index 1587db395bd9..000000000000 --- a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/cli.py +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -import logging -import sys -from pathlib import Path -from typing import TYPE_CHECKING - -import asyncclick as click -import asyncer -import dagger -from anyio import Semaphore -from connector_ops.utils import Connector # type: ignore - -from connectors_insights.insights import generate_insights_for_connector -from connectors_insights.result_backends import GCSBucket, LocalDir -from connectors_insights.utils import gcs_uri_to_bucket_key, get_all_connectors_in_directory, remove_strict_encrypt_suffix - -if TYPE_CHECKING: - from typing import List - - from connectors_insights.result_backends import ResultBackend - -logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s") -logging.getLogger("urllib3").setLevel(logging.WARNING) -logging.getLogger("httpx").setLevel(logging.WARNING) - - -@click.group -async def connectors_insights() -> None: - pass - - -@connectors_insights.command("generate", help="Generate connector insights the given connectors.") -@click.option( - "-n", - "--name", - "selected_connectors", - multiple=True, - help="The technical name of the connector. e.g. 'source-google-sheets'.", -) -@click.option( - "-d", - "--connector-directory", - "connector_directory", - type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path), - help="The directory containing the connectors, to generate insights for all connectors in this directory.", -) -@click.option( - "-o", - "--output-directory", - "output_directory", - type=click.Path(file_okay=False, path_type=Path, writable=True, dir_okay=True), - help="Path to the directory where the insights will be saved as JSON files.", -) -@click.option( - "-g", - "--gcs-uri", - "gcs_uri", - help="GCS URI to the directory where the insights will be saved as JSON files.", -) -@click.option( - "-c", - "--concurrency", - "concurrency", - type=int, - default=5, - help="The number of connectors to generate insights for concurrently.", -) -@click.option( - "--rewrite", - "rewrite", - type=bool, - is_flag=True, - default=False, - help="Whether to rewrite the report file if it already exists.", -) -async def generate( - selected_connectors: List[str], - connector_directory: Path | None, - output_directory: Path | None, - gcs_uri: str | None, - concurrency: int, - rewrite: bool, -) -> None: - logger = logging.getLogger(__name__) - result_backends: List[ResultBackend] = [] - if output_directory: - result_backends.append(LocalDir(output_directory)) - if gcs_uri: - result_backends.append(GCSBucket(*gcs_uri_to_bucket_key(gcs_uri))) - connectors: List[Connector] = [] - if selected_connectors: - connectors += [Connector(remove_strict_encrypt_suffix(connector)) for connector in selected_connectors] - if connector_directory: - connectors += get_all_connectors_in_directory(connector_directory) - - connectors = sorted(list(connectors), key=lambda connector: connector.technical_name, reverse=True) - - if not connectors: - raise click.UsageError( - "No connectors passed. Please pass at least one connector with --name or a directory containing connectors with --connector-directory." - ) - else: - logger.info(f"Generating insights for {len(connectors)} connectors.") - semaphore = Semaphore(concurrency) - soon_results = [] - async with dagger.Connection(dagger.Config(log_output=sys.stderr)) as dagger_client: - async with asyncer.create_task_group() as connector_task_group: - for connector in connectors: - soon_results.append( - connector_task_group.soonify(generate_insights_for_connector)( - dagger_client, - connector, - semaphore, - rewrite, - result_backends=result_backends, - ) - ) - failing_connector_names = [soon_result.value[1].technical_name for soon_result in soon_results if not soon_result.value[0]] - if failing_connector_names: - raise click.ClickException("Failed to generate insights for the following connectors: " + ", ".join(failing_connector_names)) diff --git a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/hacks.py b/airbyte-ci/connectors/connectors_insights/src/connectors_insights/hacks.py deleted file mode 100644 index d521a1d8b8db..000000000000 --- a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/hacks.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -import json -from typing import TYPE_CHECKING - -import requests -from bs4 import BeautifulSoup -from google.cloud import storage # type: ignore - -if TYPE_CHECKING: - from typing import Dict - - from connector_ops.utils import Connector # type: ignore - - -TEST_SUMMARY_ROOT_URL = "https://connectors.airbyte.com/files/generated_reports/test_summary" - - -def get_ci_json_report(json_report_url: str) -> Dict: - storage_client = storage.Client(project="dataline-integration-testing") - bucket_name = json_report_url.split("/")[3] - blob_name = "/".join(json_report_url.split("/")[4:]) - bucket = storage_client.bucket(bucket_name) - blob = bucket.blob(blob_name) - - return json.loads(blob.download_as_string()) - - -def get_ci_on_master_report(connector: Connector) -> Dict | None: - """This is a hack because we use the HTML report to get the latest CI insights. - We should ideally fetch the json report directly but the URL has timestamp in it so it's not deterministic. - - Args: - connector (Connector): The connector to get the CI insights for. - - Returns: - Dict | None: The CI insights if found, None otherwise. - """ - url = f"{TEST_SUMMARY_ROOT_URL}/{connector.technical_name}/index.html" - - response = requests.get(url) - if response.status_code != 200: - return None - - soup = BeautifulSoup(response.content, "html.parser") - - rows = soup.find_all("tr") - - for row in rows[1:]: # Skipping the header row - columns = row.find_all("td") - if columns: - try: - report_url = columns[3].find("a")["href"] - except (IndexError, KeyError, TypeError): - continue - json_report_url = report_url.replace(".html", ".json") - # The first table entry is the latest report, but sometimes it's not there questionmark - try: - json_report = get_ci_json_report(json_report_url) - if json_report["connector_version"] == connector.version: - return json_report - except Exception as e: - continue - return None - - return None diff --git a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/insights.py b/airbyte-ci/connectors/connectors_insights/src/connectors_insights/insights.py deleted file mode 100644 index 5267c88df8ce..000000000000 --- a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/insights.py +++ /dev/null @@ -1,263 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -import datetime -import itertools -import json -import logging -import re -from typing import TYPE_CHECKING - -import requests - -from connectors_insights.hacks import get_ci_on_master_report -from connectors_insights.models import ConnectorInsights -from connectors_insights.pylint import get_pylint_output -from connectors_insights.result_backends import FileToPersist, ResultBackend - -if TYPE_CHECKING: - from typing import Dict, List, Tuple - - import dagger - from anyio import Semaphore - from connector_ops.utils import Connector # type: ignore - - -def get_manifest_inferred_insights(connector: Connector) -> dict: - if connector.manifest_path is None or not connector.manifest_path.exists(): - return {} - - manifest = connector.manifest_path.read_text() - - schemas_directory = connector.code_directory / connector.technical_name.replace("-", "_") / "schemas" - - return { - "manifest_uses_parameters": manifest.find("$parameters") != -1, - "manifest_uses_custom_components": manifest.find("class_name:") != -1, - "manifest_custom_component_classes": re.findall(r"class_name: (.+)", manifest), - "has_json_schemas": schemas_directory.is_dir() and any(schemas_directory.iterdir()), - } - - -def get_metadata_inferred_insights(connector: Connector) -> Dict: - return { - "connector_technical_name": connector.technical_name, - "connector_version": connector.version, - "connector_image_address": connector.image_address, - "uses_base_image": connector.uses_base_image, - "base_image_address": connector.base_image_address, - "base_image_version": connector.base_image_version, - "connector_language": connector.language, - "cdk_name": connector.cdk_name, - "is_using_poetry": connector.is_using_poetry, - "connector_definition_id": connector.metadata.get("definitionId"), - "connector_type": connector.metadata.get("connectorType"), - "connector_subtype": connector.metadata.get("connectorSubtype"), - "connector_support_level": connector.metadata.get("supportLevel"), - "ab_internal_sl": connector.metadata.get("ab_internal", {}).get("sl"), - "ab_internal_ql": connector.metadata.get("ab_internal", {}).get("ql"), - "is_cloud_enabled": connector.metadata.get("registryOverrides", {}).get("cloud", {}).get("enabled", False), - "is_oss_enabled": connector.metadata.get("registryOverrides", {}).get("oss", {}).get("enabled", False), - } - - -def get_sbom_inferred_insights(raw_sbom: str | None, connector: Connector) -> Dict: - """Parse the SBOM and get dependencies and CDK version from it. - - Args: - raw_sbom (str | None): the SBOM in JSON format. - connector (Connector): the connector to get insights for. - - Returns: - Dict: the inferred insights from the SBOM. - """ - sbom_inferred_insights: Dict[str, List[Dict[str, str]] | None] = { - "cdk_version": None, - "dependencies": [], - } - if not raw_sbom: - return sbom_inferred_insights - sbom = json.loads(raw_sbom) - python_artifacts = {package["name"]: package for package in sbom["packages"] if package["SPDXID"].startswith("SPDXRef-Package-python-")} - sbom_inferred_insights["cdk_version"] = python_artifacts.get("airbyte-cdk", {}).get("versionInfo") - - for package in sbom["packages"]: - package_type = package["SPDXID"].split("-")[2] - try: - dependency = {"type": package_type, "version": package["versionInfo"], "package_name": package["name"]} - except KeyError: - continue - if isinstance(sbom_inferred_insights["dependencies"], list) and dependency not in sbom_inferred_insights["dependencies"]: - sbom_inferred_insights["dependencies"].append(dependency) - return sbom_inferred_insights - - -def get_pylint_inferred_insights(pylint_output: str | None) -> Dict: - """Make insights from the pylint output. - It currently parses the deprecated classes and modules from the pylint output. - """ - if not pylint_output: - return {} - - deprecated_classes_in_use = [] - deprecated_modules_in_use = [] - forbidden_method_names_in_use = [] - deprecated_class_pattern = r"Using deprecated class (\w+) of module ([\w\.]+)" - deprecated_module_pattern = r"Deprecated module '([^']+)'" - forbidden_method_name_pattern = r'Method name "([^"]+)"' - for message in json.loads(pylint_output): - if message["symbol"] == "deprecated-class": - if match := re.search(deprecated_class_pattern, message["message"]): - deprecated_classes_in_use.append(f"{match.group(2)}.{match.group(1)}") - if message["symbol"] == "deprecated-module": - if match := re.search(deprecated_module_pattern, message["message"]): - deprecated_modules_in_use.append(match.group(1)) - if message["symbol"] == "forbidden-method-name": - if match := re.search(forbidden_method_name_pattern, message["message"]): - forbidden_method_names_in_use.append(match.group(1)) - return { - "deprecated_classes_in_use": deprecated_classes_in_use, - "deprecated_modules_in_use": deprecated_modules_in_use, - "forbidden_method_names_in_use": forbidden_method_names_in_use, - } - - -def should_skip_generation( - result_backends: List[ResultBackend] | None, connector: Connector, files_to_persist: List[FileToPersist], rewrite: bool -) -> bool: - """Check if the insights generation should be skipped because they already exist. - Always run if rewrite is True or no result backends are provided. - - Args: - result_backends (List[ResultBackend] | None): The result backends to check if the insights already exist. - connector (Connector): The connector to check if the insights already exist. - files_to_persist (List[FileToPersist]): The files to persist for the connector. - rewrite (bool): Whether to rewrite the insights if they already exist. - - Returns: - bool: True if the insights generation should be skipped, False otherwise. - """ - if rewrite or not result_backends: - return False - - for result_backend, file_to_persist in itertools.product(result_backends, files_to_persist): - if not result_backend.artifact_already_exists(connector, file_to_persist): - return False - return True - - -def fetch_sbom(connector: Connector) -> str | None: - """Fetch the SBOM for the connector if it is released. - SBOM are generated from published Docker images. If the connector is not released it does not have a published Docker image. - - Args: - dagger_client (dagger.Client): The Dagger client to use. - connector (Connector): The connector to fetch the SBOM for. - - Returns: - str | None: The SBOM in JSON format if the connector is released, None otherwise. - """ - if connector.sbom_url: - r = requests.get(connector.sbom_url) - r.raise_for_status() - return r.text - return None - - -def generate_insights(connector: Connector, sbom: str | None, pylint_output: str | None) -> ConnectorInsights: - """Generate insights for the connector. - - Args: - connector (Connector): The connector to generate insights for. - sbom (str | None): The SBOM in JSON format. - - Returns: - ConnectorInsights: The insights for the connector. - """ - ci_on_master_report = get_ci_on_master_report(connector) - return ConnectorInsights( - **{ - **get_metadata_inferred_insights(connector), - **get_manifest_inferred_insights(connector), - **get_pylint_inferred_insights(pylint_output), - **get_sbom_inferred_insights(sbom, connector), - "ci_on_master_report": ci_on_master_report, - "ci_on_master_passes": ci_on_master_report.get("success") if ci_on_master_report else None, - "insight_generation_timestamp": datetime.datetime.utcnow(), - } - ) - - -# TODO: make it async for concurrent uploads -def persist_files( - connector: Connector, - files_to_persist: List[FileToPersist], - result_backends: List[ResultBackend] | None, - rewrite: bool, - logger: logging.Logger, -) -> None: - """Persist the files to the result backends. - - Args: - connector (Connector): The connector to persist the files for. - files_to_persist (List[FileToPersist]): The files to persist for the connector. - result_backends (List[ResultBackend] | None): The result backends to persist the files to. - rewrite (bool): Whether to rewrite the files if they already exist. - logger (logging.Logger): The logger to use. - - Returns: - None - """ - if not result_backends: - logger.warning(f"No result backends provided to persist files for {connector.technical_name}") - return None - for backend, file in itertools.product(result_backends, files_to_persist): - if file.file_content: - if not rewrite and backend.artifact_already_exists(connector, file): - logger.info(f"Skipping writing {file.file_name} for {connector.technical_name} because it already exists.") - continue - backend.write(connector, file) - else: - logger.warning(f"No content provided for {file.file_name} for {connector.technical_name}") - - -async def generate_insights_for_connector( - dagger_client: dagger.Client, - connector: Connector, - semaphore: Semaphore, - rewrite: bool = False, - result_backends: List[ResultBackend] | None = None, -) -> Tuple[bool, Connector]: - """Aggregate insights for a connector and write them to the result backends. - - Args: - dagger_client (dagger.Client): the dagger client. - connector (Connector): the connector to generate insights for. - semaphore (Semaphore): the semaphore to limit the number of concurrent insights generation. - rewrite (bool): whether to rewrite the insights if they already exist. - result_backend (List[ResultBackend] | None): the result backends to write the insights to. - Returns: - Tuple[bool, Connector]: a tuple of whether the insights were generated and the connector. - """ - logger = logging.getLogger(__name__) - insights_file = FileToPersist("insights.json") - files_to_persist = [insights_file] - - async with semaphore: - if should_skip_generation(result_backends, connector, files_to_persist, rewrite): - logger.info(f"Skipping insights generation for {connector.technical_name} because it is already generated.") - return True, connector - - logger.info(f"Generating insights for {connector.technical_name}") - result_backends = result_backends or [] - try: - pylint_output = await get_pylint_output(dagger_client, connector) - raw_sbom = fetch_sbom(connector) - insights = generate_insights(connector, raw_sbom, pylint_output) - insights_file.set_file_content(insights.json()) - persist_files(connector, files_to_persist, result_backends, rewrite, logger) - logger.info(f"Finished generating insights for {connector.technical_name}") - return True, connector - except Exception as e: - logger.error(f"Failed to generate insights for {connector.technical_name}: {e}") - return False, connector diff --git a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/models.py b/airbyte-ci/connectors/connectors_insights/src/connectors_insights/models.py deleted file mode 100644 index 570982251856..000000000000 --- a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/models.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -import json -from datetime import datetime - -from connector_ops.utils import ConnectorLanguage # type: ignore -from pydantic import BaseModel, StrictBool -from pydantic.json import pydantic_encoder - - -class ConnectorInsights(BaseModel): - insight_generation_timestamp: datetime - connector_definition_id: str - connector_type: str - connector_subtype: str | None - connector_technical_name: str - connector_version: str - connector_image_address: str - connector_support_level: str | None - ab_internal_sl: int | None - ab_internal_ql: int | None - cdk_name: str | None - cdk_version: str | None - connector_language: ConnectorLanguage | None - ci_on_master_report: dict | None - ci_on_master_passes: StrictBool | None - uses_base_image: StrictBool - base_image_address: str | None - base_image_version: str | None - is_using_poetry: StrictBool - dependencies: list[dict] - is_cloud_enabled: StrictBool - is_oss_enabled: StrictBool - deprecated_classes_in_use: list[str] | None - deprecated_modules_in_use: list[str] | None - forbidden_method_names_in_use: list[str] | None - manifest_uses_parameters: StrictBool | None - manifest_uses_custom_components: StrictBool | None - manifest_custom_component_classes: list[str] | None - has_json_schemas: StrictBool | None - - class Config: - json_encoders = {dict: lambda v: json.dumps(v, default=pydantic_encoder)} diff --git a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/pylint.py b/airbyte-ci/connectors/connectors_insights/src/connectors_insights/pylint.py deleted file mode 100644 index eef3fe1cd086..000000000000 --- a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/pylint.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -import os -from pathlib import Path -from typing import TYPE_CHECKING - -from connector_ops.utils import ConnectorLanguage # type: ignore - -from connectors_insights.utils import never_fail_exec - -if TYPE_CHECKING: - import dagger - from connector_ops.utils import Connector # type: ignore - -PYLINT_COMMAND = [ - "pylint", - "--load-plugins=custom_plugin", - "--disable=all", - "--output-format=json", - "--enable=deprecated-class", - "--enable=deprecated-module", - "--enable=forbidden-method-name", - ".", -] - - -async def get_pylint_output(dagger_client: dagger.Client, connector: Connector) -> str | None: - """Invoke pylint to check for deprecated classes and modules in the connector code. - We use the custom plugin cdk_deprecation_checkers.py to check for deprecated classes and modules. - The plugin is located in the `pylint_plugins` directory. - - Args: - dagger_client (dagger.Client): Current dagger client. - connector (Connector): Connector object. - - Returns: - str | None: Pylint output. - """ - if connector.language not in [ConnectorLanguage.PYTHON, ConnectorLanguage.LOW_CODE, ConnectorLanguage.MANIFEST_ONLY]: - return None - cdk_deprecation_checker_path = Path(os.path.abspath(__file__)).parent / "pylint_plugins/cdk_deprecation_checkers.py" - pip_cache_volume: dagger.CacheVolume = dagger_client.cache_volume("pip_cache") - - return await ( - dagger_client.container() - .from_(connector.image_address) - .with_user("root") - .with_mounted_cache("/root/.cache/pip", pip_cache_volume) - .with_new_file("__init__.py", contents="") - .with_exec(["pip", "install", "pylint"]) - .with_workdir(connector.technical_name.replace("-", "_")) - .with_env_variable("PYTHONPATH", ".") - .with_new_file("custom_plugin.py", contents=cdk_deprecation_checker_path.read_text()) - .with_(never_fail_exec(PYLINT_COMMAND)) - .stdout() - ) diff --git a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/pylint_plugins/cdk_deprecation_checkers.py b/airbyte-ci/connectors/connectors_insights/src/connectors_insights/pylint_plugins/cdk_deprecation_checkers.py deleted file mode 100644 index a961e1a3e223..000000000000 --- a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/pylint_plugins/cdk_deprecation_checkers.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -from collections import namedtuple -from typing import TYPE_CHECKING - -from pylint.checkers import BaseChecker, DeprecatedMixin # type: ignore - -if TYPE_CHECKING: - from typing import Set - - import astroid # type: ignore - from pylint.lint import PyLinter # type: ignore - -DeprecatedClass = namedtuple("DeprecatedClass", ["module", "name"]) - -DEPRECATED_CLASSES: Set[DeprecatedClass] = { - DeprecatedClass("airbyte_cdk.logger", "AirbyteLogger"), - DeprecatedClass(None, "GoogleAnalyticsDataApiBaseStream"), -} - -DEPRECATED_MODULES = {"airbyte_cdk.sources.streams.http.auth"} - -FORBIDDEN_METHOD_NAMES = {"get_updated_state"} - - -class ForbiddenMethodNameChecker(BaseChecker): - name = "forbidden-method-name-checker" - msgs = { - "C9001": ('Method name "%s" is forbidden', "forbidden-method-name", "Used when a forbidden method name is detected."), - } - - def visit_functiondef(self, node: astroid.node) -> None: - if node.name in FORBIDDEN_METHOD_NAMES: - self.add_message("forbidden-method-name", node=node, args=(node.name,)) - - -class DeprecationChecker(DeprecatedMixin, BaseChecker): - """Check for deprecated classes and modules. - The DeprecatedMixin class is here: - https://github.com/pylint-dev/pylint/blob/a5a77f6e891f6e143439d19b5e7f0a29eb5ea1cd/pylint/checkers/deprecated.py#L31 - """ - - name = "deprecated" - - msgs = { - **DeprecatedMixin.DEPRECATED_METHOD_MESSAGE, - **DeprecatedMixin.DEPRECATED_ARGUMENT_MESSAGE, - **DeprecatedMixin.DEPRECATED_CLASS_MESSAGE, - **DeprecatedMixin.DEPRECATED_MODULE_MESSAGE, - } - - def deprecated_modules(self) -> set[str]: - """Callback method called by DeprecatedMixin for every module found in the code. - - Returns: - collections.abc.Container of deprecated module names. - """ - return DEPRECATED_MODULES - - def deprecated_classes(self, module: str) -> set[str]: - """Callback method called by DeprecatedMixin for every class found in the code. - - Returns: - collections.abc.Container of deprecated class names. - """ - _deprecated_classes = set() - for deprecated_class in DEPRECATED_CLASSES: - if deprecated_class.module is None or deprecated_class.module == module: - _deprecated_classes.add(deprecated_class.name) - return _deprecated_classes - - -def register(linter: PyLinter) -> None: - linter.register_checker(DeprecationChecker(linter)) - linter.register_checker(ForbiddenMethodNameChecker(linter)) diff --git a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/result_backends.py b/airbyte-ci/connectors/connectors_insights/src/connectors_insights/result_backends.py deleted file mode 100644 index 28c32d622417..000000000000 --- a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/result_backends.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -import logging -from abc import ABC, abstractmethod -from dataclasses import dataclass -from pathlib import Path -from typing import TYPE_CHECKING - -from connector_ops.utils import Connector # type: ignore -from google.cloud import storage # type: ignore - -if TYPE_CHECKING: - from typing import Any - - -@dataclass -class FileToPersist: - file_name: str - file_content: str | None = None - - def set_file_content(self, file_content: str) -> None: - self.file_content = file_content - - -class ResultBackend(ABC): - def __init__(self, *args: Any, **kwargs: Any): - self.logger = logging.getLogger(self.__class__.__name__) - - def write(self, connector: Connector, file_to_persist: FileToPersist) -> None: - if not file_to_persist.file_content: - raise ValueError("File content must be set before writing to local directory") - self._write(connector, file_to_persist) - - @abstractmethod - def _write(self, connector: Connector, file_to_persist: FileToPersist) -> None: - raise NotImplementedError("write method must be implemented by subclass") - - @abstractmethod - def artifact_already_exists(self, connector: Connector, file_to_persist: FileToPersist) -> bool: - raise NotImplementedError("insights_already_exist method must be implemented by subclass") - - -class LocalDir(ResultBackend): - def __init__(self, local_directory: Path): - super().__init__() - if not local_directory.exists(): - local_directory.mkdir(parents=True) - - self.local_directory = local_directory - - def _write(self, connector: Connector, file_to_persist: FileToPersist) -> None: - assert file_to_persist.file_content is not None - connector_result_directory = self.local_directory / connector.technical_name / connector.version - connector_result_directory.mkdir(parents=True, exist_ok=True) - file_path = connector_result_directory / file_to_persist.file_name - with open(file_path, "w") as f: - f.write(file_to_persist.file_content) - self.logger.info(f"{file_to_persist.file_name} written to {file_path}") - - def artifact_already_exists(self, connector: Connector, file_to_persist: FileToPersist) -> bool: - connector_result_directory = self.local_directory / connector.technical_name / connector.version - return (connector_result_directory / file_to_persist.file_name).exists() - - -class GCSBucket(ResultBackend): - DEFAULT_GCP_PROJECT = "prod-ab-cloud-proj" - - def __init__(self, bucket_name: str, key_prefix: str, gcp_project: str = DEFAULT_GCP_PROJECT): - super().__init__() - self.bucket_name = bucket_name - self.key_prefix = key_prefix - self.storage_client = storage.Client(project=gcp_project) - self.bucket = self.storage_client.bucket(self.bucket_name) - - def _write(self, connector: Connector, file_to_persist: FileToPersist) -> None: - assert file_to_persist.file_content is not None - version_blob_prefix = f"{self.key_prefix}/{connector.technical_name}/{connector.version}" - latest_blob_prefix = f"{self.key_prefix}/{connector.technical_name}/latest" - for blob_prefix in [version_blob_prefix, latest_blob_prefix]: - blob = self.bucket.blob(f"{blob_prefix}/{file_to_persist.file_name}") - blob.upload_from_string(file_to_persist.file_content) - self.logger.info(f"{file_to_persist.file_name} written to {blob.public_url}") - - def artifact_already_exists(self, connector: Connector, file_to_persist: FileToPersist) -> bool: - blob_prefix = f"{self.key_prefix}/{connector.technical_name}/{connector.version}" - return self.bucket.blob(f"{blob_prefix}/{file_to_persist.file_name}").exists() diff --git a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/utils.py b/airbyte-ci/connectors/connectors_insights/src/connectors_insights/utils.py deleted file mode 100644 index b68e62b61670..000000000000 --- a/airbyte-ci/connectors/connectors_insights/src/connectors_insights/utils.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -import re -from pathlib import Path -from typing import TYPE_CHECKING - -import requests - -if TYPE_CHECKING: - from typing import Callable, List, Set, Tuple - - from dagger import Container - -from connector_ops.utils import METADATA_FILE_NAME, Connector # type: ignore - - -def remove_strict_encrypt_suffix(connector_technical_name: str) -> str: - """Remove the strict encrypt suffix from a connector name. - - Args: - connector_technical_name (str): the connector name. - - Returns: - str: the connector name without the strict encrypt suffix. - """ - strict_encrypt_suffixes = [ - "-strict-encrypt", - "-secure", - ] - - for suffix in strict_encrypt_suffixes: - if connector_technical_name.endswith(suffix): - new_connector_technical_name = connector_technical_name.replace(suffix, "") - return new_connector_technical_name - return connector_technical_name - - -def get_all_connectors_in_directory(directory: Path) -> Set[Connector]: - """Get all connectors in a directory. - - Args: - directory (Path): the directory to search for connectors. - - Returns: - List[Connector]: the list of connectors in the directory. - """ - connectors = [] - for connector_directory in directory.iterdir(): - if ( - connector_directory.is_dir() - and (connector_directory / METADATA_FILE_NAME).exists() - and "scaffold" not in str(connector_directory) - ): - connectors.append(Connector(remove_strict_encrypt_suffix(connector_directory.name))) - return set(connectors) - - -def gcs_uri_to_bucket_key(gcs_uri: str) -> Tuple[str, str]: - # Ensure the GCS URI follows the expected pattern - match = re.match(r"^gs://([^/]+)/(.+)$", gcs_uri) - if not match: - raise ValueError(f"Invalid GCS URI: {gcs_uri}") - - bucket, key = match.groups() - return bucket, key - - -def never_fail_exec(command: List[str]) -> Callable[[Container], Container]: - """ - Wrap a command execution with some bash sugar to always exit with a 0 exit code but write the actual exit code to a file. - - Underlying issue: - When a classic dagger with_exec is returning a >0 exit code an ExecError is raised. - It's OK for the majority of our container interaction. - But some execution, like running CAT, are expected to often fail. - In CAT we don't want ExecError to be raised on container interaction because CAT might write updated secrets that we need to pull from the container after the test run. - The bash trick below is a hack to always return a 0 exit code but write the actual exit code to a file. - The file is then read by the pipeline to determine the exit code of the container. - - Args: - command (List[str]): The command to run in the container. - - Returns: - Callable: _description_ - """ - - def never_fail_exec_inner(container: Container) -> Container: - return container.with_exec(["sh", "-c", f"{' '.join(command)}; echo $? > /exit_code"]) - - return never_fail_exec_inner diff --git a/airbyte-ci/connectors/erd/README.md b/airbyte-ci/connectors/erd/README.md deleted file mode 100644 index 7623b907d5ff..000000000000 --- a/airbyte-ci/connectors/erd/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# erd - -A collection of utilities for generating ERDs. - -# Setup - -## Installation - -`erd` tools use [Poetry](https://github.com/python-poetry/poetry) to manage dependencies, -and targets Python 3.11 and higher. - -Assuming you're in Airbyte repo root: - -```bash -cd airbyte-ci/connectors/erd -poetry install -``` - -## Usage - -Pre-requisites: -* Env variable `GENAI_API_KEY`. Can be found at URL https://aistudio.google.com/app/apikey - -`poetry run erd --source-path --source-technical-name ` - -The script supports the option to ignore the LLM generation by passing parameter `--skip-llm-relationships` - -## Contributing to `erd` - -### Running tests - -To run tests locally: - -```bash -poetry run pytest -``` - -## Changelog -- 0.1.1: Update Python version requirement from 3.10 to 3.11. -- 0.1.0: Initial commit diff --git a/airbyte-ci/connectors/erd/poetry.lock b/airbyte-ci/connectors/erd/poetry.lock deleted file mode 100644 index f2fe4611891b..000000000000 --- a/airbyte-ci/connectors/erd/poetry.lock +++ /dev/null @@ -1,2369 +0,0 @@ -# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. - -[[package]] -name = "airbyte-cdk" -version = "6.36.4" -description = "A framework for writing Airbyte Connectors." -optional = false -python-versions = "<3.13,>=3.10" -groups = ["main"] -files = [ - {file = "airbyte_cdk-6.36.4-py3-none-any.whl", hash = "sha256:a8c30929188737c80fccc660fdaef7d36893c6a7491b338761bcfe7e6a62fefa"}, - {file = "airbyte_cdk-6.36.4.tar.gz", hash = "sha256:3e0530c9209c2ab778e8414a24b3c08b90768e9e3707e00b95dd1f351b4945e0"}, -] - -[package.dependencies] -airbyte-protocol-models-dataclasses = ">=0.14,<0.15" -backoff = "*" -cachetools = "*" -cryptography = ">=42.0.5,<44.0.0" -dpath = ">=2.1.6,<3.0.0" -dunamai = ">=1.22.0,<2.0.0" -genson = "1.3.0" -isodate = ">=0.6.1,<0.7.0" -Jinja2 = ">=3.1.2,<3.2.0" -jsonref = ">=0.2,<0.3" -jsonschema = ">=4.17.3,<4.18.0" -langchain_core = "0.1.42" -nltk = "3.9.1" -numpy = "<2" -orjson = ">=3.10.7,<4.0.0" -pandas = "2.2.2" -psutil = "6.1.0" -pydantic = ">=2.7,<3.0" -pyjwt = ">=2.8.0,<3.0.0" -pyrate-limiter = ">=3.1.0,<3.2.0" -python-dateutil = ">=2.9.0,<3.0.0" -python-ulid = ">=3.0.0,<4.0.0" -pytz = "2024.2" -PyYAML = ">=6.0.1,<7.0.0" -rapidfuzz = ">=3.10.1,<4.0.0" -requests = "*" -requests_cache = "*" -serpyco-rs = ">=1.10.2,<2.0.0" -Unidecode = ">=1.3,<2.0" -wcmatch = "10.0" -whenever = ">=0.6.16,<0.7.0" -xmltodict = ">=0.13,<0.15" - -[package.extras] -file-based = ["avro (>=1.11.2,<1.13.0)", "fastavro (>=1.8.0,<1.9.0)", "markdown", "pdf2image (==1.16.3)", "pdfminer.six (==20221105)", "pyarrow (>=15.0.0,<15.1.0)", "pytesseract (==0.3.10)", "python-calamine (==0.2.3)", "python-snappy (==0.7.3)", "unstructured.pytesseract (>=0.3.12)", "unstructured[docx,pptx] (==0.10.27)"] -sql = ["sqlalchemy (>=2.0,!=2.0.36,<3.0)"] -vector-db-based = ["cohere (==4.21)", "langchain (==0.1.16)", "openai[embeddings] (==0.27.9)", "tiktoken (==0.8.0)"] - -[[package]] -name = "airbyte-protocol-models-dataclasses" -version = "0.14.2" -description = "Declares the Airbyte Protocol using Python Dataclasses. Dataclasses in Python have less performance overhead compared to Pydantic models, making them a more efficient choice for scenarios where speed and memory usage are critical" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "airbyte_protocol_models_dataclasses-0.14.2-py3-none-any.whl", hash = "sha256:ae06a406df031afa42f1156bacc587958197e5c7d9bbaf11893480903d4ded8b"}, - {file = "airbyte_protocol_models_dataclasses-0.14.2.tar.gz", hash = "sha256:9279237156b722cdd54e7b9ec8f97d264bd96e3f3008bc5fc47c215288a2212a"}, -] - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "attributes-doc" -version = "0.4.0" -description = "PEP 224 implementation" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "attributes-doc-0.4.0.tar.gz", hash = "sha256:b1576c94a714e9fc2c65c47cf10d0c8e1a5f7c4f5ae7f69006be108d95cbfbfb"}, - {file = "attributes_doc-0.4.0-py2.py3-none-any.whl", hash = "sha256:4c3007d9e58f3a6cb4b9c614c4d4ce2d92161581f28e594ddd8241cc3a113bdd"}, -] - -[[package]] -name = "attrs" -version = "24.2.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, - {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, -] - -[package.extras] -benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] - -[[package]] -name = "backoff" -version = "2.2.1" -description = "Function decoration for backoff and retry" -optional = false -python-versions = ">=3.7,<4.0" -groups = ["main"] -files = [ - {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, - {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, -] - -[[package]] -name = "bracex" -version = "2.5" -description = "Bash style brace expander." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "bracex-2.5-py3-none-any.whl", hash = "sha256:d2fcf4b606a82ac325471affe1706dd9bbaa3536c91ef86a31f6b766f3dad1d0"}, - {file = "bracex-2.5.tar.gz", hash = "sha256:0725da5045e8d37ea9592ab3614d8b561e22c3c5fde3964699be672e072ab611"}, -] - -[[package]] -name = "cachetools" -version = "5.4.0" -description = "Extensible memoizing collections and decorators" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "cachetools-5.4.0-py3-none-any.whl", hash = "sha256:3ae3b49a3d5e28a77a0be2b37dbcb89005058959cb2323858c2657c4a8cab474"}, - {file = "cachetools-5.4.0.tar.gz", hash = "sha256:b8adc2e7c07f105ced7bc56dbb6dfbe7c4a00acce20e2227b3f355be89bc6827"}, -] - -[[package]] -name = "cattrs" -version = "23.2.3" -description = "Composable complex class support for attrs and dataclasses." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "cattrs-23.2.3-py3-none-any.whl", hash = "sha256:0341994d94971052e9ee70662542699a3162ea1e0c62f7ce1b4a57f563685108"}, - {file = "cattrs-23.2.3.tar.gz", hash = "sha256:a934090d95abaa9e911dac357e3a8699e0b4b14f8529bcc7d2b1ad9d51672b9f"}, -] - -[package.dependencies] -attrs = ">=23.1.0" - -[package.extras] -bson = ["pymongo (>=4.4.0)"] -cbor2 = ["cbor2 (>=5.4.6)"] -msgpack = ["msgpack (>=1.0.5)"] -orjson = ["orjson (>=3.9.2)"] -pyyaml = ["pyyaml (>=6.0)"] -tomlkit = ["tomlkit (>=0.11.8)"] -ujson = ["ujson (>=5.7.0)"] - -[[package]] -name = "certifi" -version = "2024.7.4" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, - {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, -] - -[[package]] -name = "cffi" -version = "1.17.0" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "platform_python_implementation != \"PyPy\"" -files = [ - {file = "cffi-1.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb"}, - {file = "cffi-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f"}, - {file = "cffi-1.17.0-cp310-cp310-win32.whl", hash = "sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc"}, - {file = "cffi-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb"}, - {file = "cffi-1.17.0-cp311-cp311-win32.whl", hash = "sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9"}, - {file = "cffi-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885"}, - {file = "cffi-1.17.0-cp312-cp312-win32.whl", hash = "sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492"}, - {file = "cffi-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4"}, - {file = "cffi-1.17.0-cp313-cp313-win32.whl", hash = "sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a"}, - {file = "cffi-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7"}, - {file = "cffi-1.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c"}, - {file = "cffi-1.17.0-cp38-cp38-win32.whl", hash = "sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499"}, - {file = "cffi-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4"}, - {file = "cffi-1.17.0-cp39-cp39-win32.whl", hash = "sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb"}, - {file = "cffi-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29"}, - {file = "cffi-1.17.0.tar.gz", hash = "sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76"}, -] - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "charset-normalizer" -version = "3.3.2" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7.0" -groups = ["main"] -files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, -] - -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main"] -markers = "platform_system == \"Windows\" or sys_platform == \"win32\"" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "cryptography" -version = "42.0.8" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"}, - {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"}, - {file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"}, - {file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"}, - {file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"}, - {file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"}, - {file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"}, - {file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"}, -] - -[package.dependencies] -cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] -docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] -nox = ["nox"] -pep8test = ["check-sdist", "click", "mypy", "ruff"] -sdist = ["build"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] -test-randomorder = ["pytest-randomly"] - -[[package]] -name = "dpath" -version = "2.2.0" -description = "Filesystem-like pathing and searching for dictionaries" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "dpath-2.2.0-py3-none-any.whl", hash = "sha256:b330a375ded0a0d2ed404440f6c6a715deae5313af40bbb01c8a41d891900576"}, - {file = "dpath-2.2.0.tar.gz", hash = "sha256:34f7e630dc55ea3f219e555726f5da4b4b25f2200319c8e6902c394258dd6a3e"}, -] - -[[package]] -name = "dunamai" -version = "1.23.0" -description = "Dynamic version generation" -optional = false -python-versions = ">=3.5" -groups = ["main"] -files = [ - {file = "dunamai-1.23.0-py3-none-any.whl", hash = "sha256:a0906d876e92441793c6a423e16a4802752e723e9c9a5aabdc5535df02dbe041"}, - {file = "dunamai-1.23.0.tar.gz", hash = "sha256:a163746de7ea5acb6dacdab3a6ad621ebc612ed1e528aaa8beedb8887fccd2c4"}, -] - -[package.dependencies] -packaging = ">=20.9" - -[[package]] -name = "genson" -version = "1.3.0" -description = "GenSON is a powerful, user-friendly JSON Schema generator." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "genson-1.3.0-py3-none-any.whl", hash = "sha256:468feccd00274cc7e4c09e84b08704270ba8d95232aa280f65b986139cec67f7"}, - {file = "genson-1.3.0.tar.gz", hash = "sha256:e02db9ac2e3fd29e65b5286f7135762e2cd8a986537c075b06fc5f1517308e37"}, -] - -[[package]] -name = "google-ai-generativelanguage" -version = "0.6.6" -description = "Google Ai Generativelanguage API client library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google-ai-generativelanguage-0.6.6.tar.gz", hash = "sha256:1739f035caeeeca5c28f887405eec8690f3372daf79fecf26454a97a4f1733a8"}, - {file = "google_ai_generativelanguage-0.6.6-py3-none-any.whl", hash = "sha256:59297737931f073d55ce1268dcc6d95111ee62850349d2b6cde942b16a4fca5c"}, -] - -[package.dependencies] -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} -google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" -proto-plus = ">=1.22.3,<2.0.0dev" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" - -[[package]] -name = "google-api-core" -version = "2.19.1" -description = "Google API client core library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google-api-core-2.19.1.tar.gz", hash = "sha256:f4695f1e3650b316a795108a76a1c416e6afb036199d1c1f1f110916df479ffd"}, - {file = "google_api_core-2.19.1-py3-none-any.whl", hash = "sha256:f12a9b8309b5e21d92483bbd47ce2c445861ec7d269ef6784ecc0ea8c1fa6125"}, -] - -[package.dependencies] -google-auth = ">=2.14.1,<3.0.dev0" -googleapis-common-protos = ">=1.56.2,<2.0.dev0" -grpcio = {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""} -grpcio-status = {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""} -proto-plus = ">=1.22.3,<2.0.0dev" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" -requests = ">=2.18.0,<3.0.0.dev0" - -[package.extras] -grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status (>=1.33.2,<2.0.dev0)", "grpcio-status (>=1.49.1,<2.0.dev0)"] -grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] -grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] - -[[package]] -name = "google-api-python-client" -version = "2.141.0" -description = "Google API Client Library for Python" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google_api_python_client-2.141.0-py2.py3-none-any.whl", hash = "sha256:43c05322b91791204465291b3852718fae38d4f84b411d8be847c4f86882652a"}, - {file = "google_api_python_client-2.141.0.tar.gz", hash = "sha256:0f225b1f45d5a6f8c2a400f48729f5d6da9a81138e81e0478d61fdd8edf6563a"}, -] - -[package.dependencies] -google-api-core = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0.dev0" -google-auth = ">=1.32.0,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0.dev0" -google-auth-httplib2 = ">=0.2.0,<1.0.0" -httplib2 = ">=0.19.0,<1.dev0" -uritemplate = ">=3.0.1,<5" - -[[package]] -name = "google-auth" -version = "2.33.0" -description = "Google Authentication Library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google_auth-2.33.0-py2.py3-none-any.whl", hash = "sha256:8eff47d0d4a34ab6265c50a106a3362de6a9975bb08998700e389f857e4d39df"}, - {file = "google_auth-2.33.0.tar.gz", hash = "sha256:d6a52342160d7290e334b4d47ba390767e4438ad0d45b7630774533e82655b95"}, -] - -[package.dependencies] -cachetools = ">=2.0.0,<6.0" -pyasn1-modules = ">=0.2.1" -rsa = ">=3.1.4,<5" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] -enterprise-cert = ["cryptography (==36.0.2)", "pyopenssl (==22.0.0)"] -pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] -reauth = ["pyu2f (>=0.1.5)"] -requests = ["requests (>=2.20.0,<3.0.0.dev0)"] - -[[package]] -name = "google-auth-httplib2" -version = "0.2.0" -description = "Google Authentication Library: httplib2 transport" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "google-auth-httplib2-0.2.0.tar.gz", hash = "sha256:38aa7badf48f974f1eb9861794e9c0cb2a0511a4ec0679b1f886d108f5640e05"}, - {file = "google_auth_httplib2-0.2.0-py2.py3-none-any.whl", hash = "sha256:b65a0a2123300dd71281a7bf6e64d65a0759287df52729bdd1ae2e47dc311a3d"}, -] - -[package.dependencies] -google-auth = "*" -httplib2 = ">=0.19.0" - -[[package]] -name = "google-generativeai" -version = "0.7.2" -description = "Google Generative AI High level API client library and tools." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "google_generativeai-0.7.2-py3-none-any.whl", hash = "sha256:3117d1ebc92ee77710d4bc25ab4763492fddce9b6332eb25d124cf5d8b78b339"}, -] - -[package.dependencies] -google-ai-generativelanguage = "0.6.6" -google-api-core = "*" -google-api-python-client = "*" -google-auth = ">=2.15.0" -protobuf = "*" -pydantic = "*" -tqdm = "*" -typing-extensions = "*" - -[package.extras] -dev = ["Pillow", "absl-py", "black", "ipython", "nose2", "pandas", "pytype", "pyyaml"] - -[[package]] -name = "googleapis-common-protos" -version = "1.63.2" -description = "Common protobufs used in Google APIs" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "googleapis-common-protos-1.63.2.tar.gz", hash = "sha256:27c5abdffc4911f28101e635de1533fb4cfd2c37fbaa9174587c799fac90aa87"}, - {file = "googleapis_common_protos-1.63.2-py2.py3-none-any.whl", hash = "sha256:27a2499c7e8aff199665b22741997e485eccc8645aa9176c7c988e6fae507945"}, -] - -[package.dependencies] -protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" - -[package.extras] -grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] - -[[package]] -name = "grpcio" -version = "1.65.4" -description = "HTTP/2-based RPC framework" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "grpcio-1.65.4-cp310-cp310-linux_armv7l.whl", hash = "sha256:0e85c8766cf7f004ab01aff6a0393935a30d84388fa3c58d77849fcf27f3e98c"}, - {file = "grpcio-1.65.4-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:e4a795c02405c7dfa8affd98c14d980f4acea16ea3b539e7404c645329460e5a"}, - {file = "grpcio-1.65.4-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:d7b984a8dd975d949c2042b9b5ebcf297d6d5af57dcd47f946849ee15d3c2fb8"}, - {file = "grpcio-1.65.4-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:644a783ce604a7d7c91412bd51cf9418b942cf71896344b6dc8d55713c71ce82"}, - {file = "grpcio-1.65.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5764237d751d3031a36fafd57eb7d36fd2c10c658d2b4057c516ccf114849a3e"}, - {file = "grpcio-1.65.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ee40d058cf20e1dd4cacec9c39e9bce13fedd38ce32f9ba00f639464fcb757de"}, - {file = "grpcio-1.65.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4482a44ce7cf577a1f8082e807a5b909236bce35b3e3897f839f2fbd9ae6982d"}, - {file = "grpcio-1.65.4-cp310-cp310-win32.whl", hash = "sha256:66bb051881c84aa82e4f22d8ebc9d1704b2e35d7867757f0740c6ef7b902f9b1"}, - {file = "grpcio-1.65.4-cp310-cp310-win_amd64.whl", hash = "sha256:870370524eff3144304da4d1bbe901d39bdd24f858ce849b7197e530c8c8f2ec"}, - {file = "grpcio-1.65.4-cp311-cp311-linux_armv7l.whl", hash = "sha256:85e9c69378af02e483bc626fc19a218451b24a402bdf44c7531e4c9253fb49ef"}, - {file = "grpcio-1.65.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2bd672e005afab8bf0d6aad5ad659e72a06dd713020554182a66d7c0c8f47e18"}, - {file = "grpcio-1.65.4-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:abccc5d73f5988e8f512eb29341ed9ced923b586bb72e785f265131c160231d8"}, - {file = "grpcio-1.65.4-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:886b45b29f3793b0c2576201947258782d7e54a218fe15d4a0468d9a6e00ce17"}, - {file = "grpcio-1.65.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be952436571dacc93ccc7796db06b7daf37b3b56bb97e3420e6503dccfe2f1b4"}, - {file = "grpcio-1.65.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8dc9ddc4603ec43f6238a5c95400c9a901b6d079feb824e890623da7194ff11e"}, - {file = "grpcio-1.65.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ade1256c98cba5a333ef54636095f2c09e6882c35f76acb04412f3b1aa3c29a5"}, - {file = "grpcio-1.65.4-cp311-cp311-win32.whl", hash = "sha256:280e93356fba6058cbbfc6f91a18e958062ef1bdaf5b1caf46c615ba1ae71b5b"}, - {file = "grpcio-1.65.4-cp311-cp311-win_amd64.whl", hash = "sha256:d2b819f9ee27ed4e3e737a4f3920e337e00bc53f9e254377dd26fc7027c4d558"}, - {file = "grpcio-1.65.4-cp312-cp312-linux_armv7l.whl", hash = "sha256:926a0750a5e6fb002542e80f7fa6cab8b1a2ce5513a1c24641da33e088ca4c56"}, - {file = "grpcio-1.65.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:2a1d4c84d9e657f72bfbab8bedf31bdfc6bfc4a1efb10b8f2d28241efabfaaf2"}, - {file = "grpcio-1.65.4-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:17de4fda50967679677712eec0a5c13e8904b76ec90ac845d83386b65da0ae1e"}, - {file = "grpcio-1.65.4-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3dee50c1b69754a4228e933696408ea87f7e896e8d9797a3ed2aeed8dbd04b74"}, - {file = "grpcio-1.65.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74c34fc7562bdd169b77966068434a93040bfca990e235f7a67cdf26e1bd5c63"}, - {file = "grpcio-1.65.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:24a2246e80a059b9eb981e4c2a6d8111b1b5e03a44421adbf2736cc1d4988a8a"}, - {file = "grpcio-1.65.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:18c10f0d054d2dce34dd15855fcca7cc44ec3b811139437543226776730c0f28"}, - {file = "grpcio-1.65.4-cp312-cp312-win32.whl", hash = "sha256:d72962788b6c22ddbcdb70b10c11fbb37d60ae598c51eb47ec019db66ccfdff0"}, - {file = "grpcio-1.65.4-cp312-cp312-win_amd64.whl", hash = "sha256:7656376821fed8c89e68206a522522317787a3d9ed66fb5110b1dff736a5e416"}, - {file = "grpcio-1.65.4-cp38-cp38-linux_armv7l.whl", hash = "sha256:4934077b33aa6fe0b451de8b71dabde96bf2d9b4cb2b3187be86e5adebcba021"}, - {file = "grpcio-1.65.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0cef8c919a3359847c357cb4314e50ed1f0cca070f828ee8f878d362fd744d52"}, - {file = "grpcio-1.65.4-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:a925446e6aa12ca37114840d8550f308e29026cdc423a73da3043fd1603a6385"}, - {file = "grpcio-1.65.4-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf53e6247f1e2af93657e62e240e4f12e11ee0b9cef4ddcb37eab03d501ca864"}, - {file = "grpcio-1.65.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdb34278e4ceb224c89704cd23db0d902e5e3c1c9687ec9d7c5bb4c150f86816"}, - {file = "grpcio-1.65.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e6cbdd107e56bde55c565da5fd16f08e1b4e9b0674851d7749e7f32d8645f524"}, - {file = "grpcio-1.65.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:626319a156b1f19513156a3b0dbfe977f5f93db63ca673a0703238ebd40670d7"}, - {file = "grpcio-1.65.4-cp38-cp38-win32.whl", hash = "sha256:3d1bbf7e1dd1096378bd83c83f554d3b93819b91161deaf63e03b7022a85224a"}, - {file = "grpcio-1.65.4-cp38-cp38-win_amd64.whl", hash = "sha256:a99e6dffefd3027b438116f33ed1261c8d360f0dd4f943cb44541a2782eba72f"}, - {file = "grpcio-1.65.4-cp39-cp39-linux_armv7l.whl", hash = "sha256:874acd010e60a2ec1e30d5e505b0651ab12eb968157cd244f852b27c6dbed733"}, - {file = "grpcio-1.65.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b07f36faf01fca5427d4aa23645e2d492157d56c91fab7e06fe5697d7e171ad4"}, - {file = "grpcio-1.65.4-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:b81711bf4ec08a3710b534e8054c7dcf90f2edc22bebe11c1775a23f145595fe"}, - {file = "grpcio-1.65.4-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88fcabc332a4aef8bcefadc34a02e9ab9407ab975d2c7d981a8e12c1aed92aa1"}, - {file = "grpcio-1.65.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9ba3e63108a8749994f02c7c0e156afb39ba5bdf755337de8e75eb685be244b"}, - {file = "grpcio-1.65.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8eb485801957a486bf5de15f2c792d9f9c897a86f2f18db8f3f6795a094b4bb2"}, - {file = "grpcio-1.65.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:075f3903bc1749ace93f2b0664f72964ee5f2da5c15d4b47e0ab68e4f442c257"}, - {file = "grpcio-1.65.4-cp39-cp39-win32.whl", hash = "sha256:0a0720299bdb2cc7306737295d56e41ce8827d5669d4a3cd870af832e3b17c4d"}, - {file = "grpcio-1.65.4-cp39-cp39-win_amd64.whl", hash = "sha256:a146bc40fa78769f22e1e9ff4f110ef36ad271b79707577bf2a31e3e931141b9"}, - {file = "grpcio-1.65.4.tar.gz", hash = "sha256:2a4f476209acffec056360d3e647ae0e14ae13dcf3dfb130c227ae1c594cbe39"}, -] - -[package.extras] -protobuf = ["grpcio-tools (>=1.65.4)"] - -[[package]] -name = "grpcio-status" -version = "1.62.3" -description = "Status proto mapping for gRPC" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "grpcio-status-1.62.3.tar.gz", hash = "sha256:289bdd7b2459794a12cf95dc0cb727bd4a1742c37bd823f760236c937e53a485"}, - {file = "grpcio_status-1.62.3-py3-none-any.whl", hash = "sha256:f9049b762ba8de6b1086789d8315846e094edac2c50beaf462338b301a8fd4b8"}, -] - -[package.dependencies] -googleapis-common-protos = ">=1.5.5" -grpcio = ">=1.62.3" -protobuf = ">=4.21.6" - -[[package]] -name = "httplib2" -version = "0.22.0" -description = "A comprehensive HTTP client library." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] -files = [ - {file = "httplib2-0.22.0-py3-none-any.whl", hash = "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc"}, - {file = "httplib2-0.22.0.tar.gz", hash = "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81"}, -] - -[package.dependencies] -pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0.2,<3.0.3 || >3.0.3,<4", markers = "python_version > \"3.0\""} - -[[package]] -name = "idna" -version = "3.7" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.5" -groups = ["main"] -files = [ - {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, - {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, -] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - -[[package]] -name = "isodate" -version = "0.6.1" -description = "An ISO 8601 date/time/duration parser and formatter" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "isodate-0.6.1-py2.py3-none-any.whl", hash = "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96"}, - {file = "isodate-0.6.1.tar.gz", hash = "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9"}, -] - -[package.dependencies] -six = "*" - -[[package]] -name = "jinja2" -version = "3.1.4" -description = "A very fast and expressive template engine." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, - {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "joblib" -version = "1.4.2" -description = "Lightweight pipelining with Python functions" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "joblib-1.4.2-py3-none-any.whl", hash = "sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6"}, - {file = "joblib-1.4.2.tar.gz", hash = "sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e"}, -] - -[[package]] -name = "jsonpatch" -version = "1.33" -description = "Apply JSON-Patches (RFC 6902)" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" -groups = ["main"] -files = [ - {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, - {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, -] - -[package.dependencies] -jsonpointer = ">=1.9" - -[[package]] -name = "jsonpointer" -version = "3.0.0" -description = "Identify specific nodes in a JSON document (RFC 6901)" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"}, - {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"}, -] - -[[package]] -name = "jsonref" -version = "0.2" -description = "An implementation of JSON Reference for Python" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "jsonref-0.2-py3-none-any.whl", hash = "sha256:b1e82fa0b62e2c2796a13e5401fe51790b248f6d9bf9d7212a3e31a3501b291f"}, - {file = "jsonref-0.2.tar.gz", hash = "sha256:f3c45b121cf6257eafabdc3a8008763aed1cd7da06dbabc59a9e4d2a5e4e6697"}, -] - -[[package]] -name = "jsonschema" -version = "4.17.3" -description = "An implementation of JSON Schema validation for Python" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, - {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, -] - -[package.dependencies] -attrs = ">=17.4.0" -pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" - -[package.extras] -format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] - -[[package]] -name = "langchain-core" -version = "0.1.42" -description = "Building applications with LLMs through composability" -optional = false -python-versions = "<4.0,>=3.8.1" -groups = ["main"] -files = [ - {file = "langchain_core-0.1.42-py3-none-any.whl", hash = "sha256:c5653ffa08a44f740295c157a24c0def4a753333f6a2c41f76bf431cd00be8b5"}, - {file = "langchain_core-0.1.42.tar.gz", hash = "sha256:40751bf60ea5d8e2b2efe65290db434717ee3834870c002e40e2811f09d814e6"}, -] - -[package.dependencies] -jsonpatch = ">=1.33,<2.0" -langsmith = ">=0.1.0,<0.2.0" -packaging = ">=23.2,<24.0" -pydantic = ">=1,<3" -PyYAML = ">=5.3" -tenacity = ">=8.1.0,<9.0.0" - -[package.extras] -extended-testing = ["jinja2 (>=3,<4)"] - -[[package]] -name = "langsmith" -version = "0.1.99" -description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." -optional = false -python-versions = "<4.0,>=3.8.1" -groups = ["main"] -files = [ - {file = "langsmith-0.1.99-py3-none-any.whl", hash = "sha256:ef8d1d74a2674c514aa429b0171a9fbb661207dc3835142cca0e8f1bf97b26b0"}, - {file = "langsmith-0.1.99.tar.gz", hash = "sha256:b5c6a1f158abda61600a4a445081ee848b4a28b758d91f2793dc02aeffafcaf1"}, -] - -[package.dependencies] -orjson = ">=3.9.14,<4.0.0" -pydantic = {version = ">=1,<3", markers = "python_full_version < \"3.12.4\""} -requests = ">=2,<3" - -[[package]] -name = "markdown-it-py" -version = "3.0.0" -description = "Python port of markdown-it. Markdown parsing, done right!" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, - {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, -] - -[package.dependencies] -mdurl = ">=0.1,<1.0" - -[package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark"] -code-style = ["pre-commit (>=3.0,<4.0)"] -compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] -linkify = ["linkify-it-py (>=1,<3)"] -plugins = ["mdit-py-plugins"] -profiling = ["gprof2dot"] -rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] - -[[package]] -name = "markupsafe" -version = "2.1.5" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, - {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, -] - -[[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, -] - -[[package]] -name = "mypy" -version = "1.11.1" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "mypy-1.11.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a32fc80b63de4b5b3e65f4be82b4cfa362a46702672aa6a0f443b4689af7008c"}, - {file = "mypy-1.11.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c1952f5ea8a5a959b05ed5f16452fddadbaae48b5d39235ab4c3fc444d5fd411"}, - {file = "mypy-1.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1e30dc3bfa4e157e53c1d17a0dad20f89dc433393e7702b813c10e200843b03"}, - {file = "mypy-1.11.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2c63350af88f43a66d3dfeeeb8d77af34a4f07d760b9eb3a8697f0386c7590b4"}, - {file = "mypy-1.11.1-cp310-cp310-win_amd64.whl", hash = "sha256:a831671bad47186603872a3abc19634f3011d7f83b083762c942442d51c58d58"}, - {file = "mypy-1.11.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7b6343d338390bb946d449677726edf60102a1c96079b4f002dedff375953fc5"}, - {file = "mypy-1.11.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e4fe9f4e5e521b458d8feb52547f4bade7ef8c93238dfb5bbc790d9ff2d770ca"}, - {file = "mypy-1.11.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:886c9dbecc87b9516eff294541bf7f3655722bf22bb898ee06985cd7269898de"}, - {file = "mypy-1.11.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fca4a60e1dd9fd0193ae0067eaeeb962f2d79e0d9f0f66223a0682f26ffcc809"}, - {file = "mypy-1.11.1-cp311-cp311-win_amd64.whl", hash = "sha256:0bd53faf56de9643336aeea1c925012837432b5faf1701ccca7fde70166ccf72"}, - {file = "mypy-1.11.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f39918a50f74dc5969807dcfaecafa804fa7f90c9d60506835036cc1bc891dc8"}, - {file = "mypy-1.11.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0bc71d1fb27a428139dd78621953effe0d208aed9857cb08d002280b0422003a"}, - {file = "mypy-1.11.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b868d3bcff720dd7217c383474008ddabaf048fad8d78ed948bb4b624870a417"}, - {file = "mypy-1.11.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a707ec1527ffcdd1c784d0924bf5cb15cd7f22683b919668a04d2b9c34549d2e"}, - {file = "mypy-1.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:64f4a90e3ea07f590c5bcf9029035cf0efeae5ba8be511a8caada1a4893f5525"}, - {file = "mypy-1.11.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:749fd3213916f1751fff995fccf20c6195cae941dc968f3aaadf9bb4e430e5a2"}, - {file = "mypy-1.11.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b639dce63a0b19085213ec5fdd8cffd1d81988f47a2dec7100e93564f3e8fb3b"}, - {file = "mypy-1.11.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c956b49c5d865394d62941b109728c5c596a415e9c5b2be663dd26a1ff07bc0"}, - {file = "mypy-1.11.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45df906e8b6804ef4b666af29a87ad9f5921aad091c79cc38e12198e220beabd"}, - {file = "mypy-1.11.1-cp38-cp38-win_amd64.whl", hash = "sha256:d44be7551689d9d47b7abc27c71257adfdb53f03880841a5db15ddb22dc63edb"}, - {file = "mypy-1.11.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2684d3f693073ab89d76da8e3921883019ea8a3ec20fa5d8ecca6a2db4c54bbe"}, - {file = "mypy-1.11.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:79c07eb282cb457473add5052b63925e5cc97dfab9812ee65a7c7ab5e3cb551c"}, - {file = "mypy-1.11.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11965c2f571ded6239977b14deebd3f4c3abd9a92398712d6da3a772974fad69"}, - {file = "mypy-1.11.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a2b43895a0f8154df6519706d9bca8280cda52d3d9d1514b2d9c3e26792a0b74"}, - {file = "mypy-1.11.1-cp39-cp39-win_amd64.whl", hash = "sha256:1a81cf05975fd61aec5ae16501a091cfb9f605dc3e3c878c0da32f250b74760b"}, - {file = "mypy-1.11.1-py3-none-any.whl", hash = "sha256:0624bdb940255d2dd24e829d99a13cfeb72e4e9031f9492148f410ed30bcab54"}, - {file = "mypy-1.11.1.tar.gz", hash = "sha256:f404a0b069709f18bbdb702eb3dcfe51910602995de00bd39cea3050b5772d08"}, -] - -[package.dependencies] -mypy-extensions = ">=1.0.0" -typing-extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -groups = ["dev"] -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "nltk" -version = "3.9.1" -description = "Natural Language Toolkit" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "nltk-3.9.1-py3-none-any.whl", hash = "sha256:4fa26829c5b00715afe3061398a8989dc643b92ce7dd93fb4585a70930d168a1"}, - {file = "nltk-3.9.1.tar.gz", hash = "sha256:87d127bd3de4bd89a4f81265e5fa59cb1b199b27440175370f7417d2bc7ae868"}, -] - -[package.dependencies] -click = "*" -joblib = "*" -regex = ">=2021.8.3" -tqdm = "*" - -[package.extras] -all = ["matplotlib", "numpy", "pyparsing", "python-crfsuite", "requests", "scikit-learn", "scipy", "twython"] -corenlp = ["requests"] -machine-learning = ["numpy", "python-crfsuite", "scikit-learn", "scipy"] -plot = ["matplotlib"] -tgrep = ["pyparsing"] -twitter = ["twython"] - -[[package]] -name = "numpy" -version = "1.26.4" -description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, - {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, - {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, - {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, - {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, - {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, - {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, - {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, - {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, - {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, - {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, - {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, - {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, - {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, - {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, - {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, - {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, - {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, - {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, - {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, - {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, - {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, - {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, - {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, - {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, - {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, - {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, - {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, - {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, - {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, - {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, - {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, - {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, -] - -[[package]] -name = "orjson" -version = "3.10.7" -description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "orjson-3.10.7-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:74f4544f5a6405b90da8ea724d15ac9c36da4d72a738c64685003337401f5c12"}, - {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34a566f22c28222b08875b18b0dfbf8a947e69df21a9ed5c51a6bf91cfb944ac"}, - {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf6ba8ebc8ef5792e2337fb0419f8009729335bb400ece005606336b7fd7bab7"}, - {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac7cf6222b29fbda9e3a472b41e6a5538b48f2c8f99261eecd60aafbdb60690c"}, - {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de817e2f5fc75a9e7dd350c4b0f54617b280e26d1631811a43e7e968fa71e3e9"}, - {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:348bdd16b32556cf8d7257b17cf2bdb7ab7976af4af41ebe79f9796c218f7e91"}, - {file = "orjson-3.10.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:479fd0844ddc3ca77e0fd99644c7fe2de8e8be1efcd57705b5c92e5186e8a250"}, - {file = "orjson-3.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fdf5197a21dd660cf19dfd2a3ce79574588f8f5e2dbf21bda9ee2d2b46924d84"}, - {file = "orjson-3.10.7-cp310-none-win32.whl", hash = "sha256:d374d36726746c81a49f3ff8daa2898dccab6596864ebe43d50733275c629175"}, - {file = "orjson-3.10.7-cp310-none-win_amd64.whl", hash = "sha256:cb61938aec8b0ffb6eef484d480188a1777e67b05d58e41b435c74b9d84e0b9c"}, - {file = "orjson-3.10.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:7db8539039698ddfb9a524b4dd19508256107568cdad24f3682d5773e60504a2"}, - {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:480f455222cb7a1dea35c57a67578848537d2602b46c464472c995297117fa09"}, - {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8a9c9b168b3a19e37fe2778c0003359f07822c90fdff8f98d9d2a91b3144d8e0"}, - {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8de062de550f63185e4c1c54151bdddfc5625e37daf0aa1e75d2a1293e3b7d9a"}, - {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6b0dd04483499d1de9c8f6203f8975caf17a6000b9c0c54630cef02e44ee624e"}, - {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b58d3795dafa334fc8fd46f7c5dc013e6ad06fd5b9a4cc98cb1456e7d3558bd6"}, - {file = "orjson-3.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33cfb96c24034a878d83d1a9415799a73dc77480e6c40417e5dda0710d559ee6"}, - {file = "orjson-3.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e724cebe1fadc2b23c6f7415bad5ee6239e00a69f30ee423f319c6af70e2a5c0"}, - {file = "orjson-3.10.7-cp311-none-win32.whl", hash = "sha256:82763b46053727a7168d29c772ed5c870fdae2f61aa8a25994c7984a19b1021f"}, - {file = "orjson-3.10.7-cp311-none-win_amd64.whl", hash = "sha256:eb8d384a24778abf29afb8e41d68fdd9a156cf6e5390c04cc07bbc24b89e98b5"}, - {file = "orjson-3.10.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44a96f2d4c3af51bfac6bc4ef7b182aa33f2f054fd7f34cc0ee9a320d051d41f"}, - {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76ac14cd57df0572453543f8f2575e2d01ae9e790c21f57627803f5e79b0d3c3"}, - {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bdbb61dcc365dd9be94e8f7df91975edc9364d6a78c8f7adb69c1cdff318ec93"}, - {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b48b3db6bb6e0a08fa8c83b47bc169623f801e5cc4f24442ab2b6617da3b5313"}, - {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23820a1563a1d386414fef15c249040042b8e5d07b40ab3fe3efbfbbcbcb8864"}, - {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0c6a008e91d10a2564edbb6ee5069a9e66df3fbe11c9a005cb411f441fd2c09"}, - {file = "orjson-3.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d352ee8ac1926d6193f602cbe36b1643bbd1bbcb25e3c1a657a4390f3000c9a5"}, - {file = "orjson-3.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d2d9f990623f15c0ae7ac608103c33dfe1486d2ed974ac3f40b693bad1a22a7b"}, - {file = "orjson-3.10.7-cp312-none-win32.whl", hash = "sha256:7c4c17f8157bd520cdb7195f75ddbd31671997cbe10aee559c2d613592e7d7eb"}, - {file = "orjson-3.10.7-cp312-none-win_amd64.whl", hash = "sha256:1d9c0e733e02ada3ed6098a10a8ee0052dd55774de3d9110d29868d24b17faa1"}, - {file = "orjson-3.10.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:77d325ed866876c0fa6492598ec01fe30e803272a6e8b10e992288b009cbe149"}, - {file = "orjson-3.10.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ea2c232deedcb605e853ae1db2cc94f7390ac776743b699b50b071b02bea6fe"}, - {file = "orjson-3.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3dcfbede6737fdbef3ce9c37af3fb6142e8e1ebc10336daa05872bfb1d87839c"}, - {file = "orjson-3.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:11748c135f281203f4ee695b7f80bb1358a82a63905f9f0b794769483ea854ad"}, - {file = "orjson-3.10.7-cp313-none-win32.whl", hash = "sha256:a7e19150d215c7a13f39eb787d84db274298d3f83d85463e61d277bbd7f401d2"}, - {file = "orjson-3.10.7-cp313-none-win_amd64.whl", hash = "sha256:eef44224729e9525d5261cc8d28d6b11cafc90e6bd0be2157bde69a52ec83024"}, - {file = "orjson-3.10.7-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6ea2b2258eff652c82652d5e0f02bd5e0463a6a52abb78e49ac288827aaa1469"}, - {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:430ee4d85841e1483d487e7b81401785a5dfd69db5de01314538f31f8fbf7ee1"}, - {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4b6146e439af4c2472c56f8540d799a67a81226e11992008cb47e1267a9b3225"}, - {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:084e537806b458911137f76097e53ce7bf5806dda33ddf6aaa66a028f8d43a23"}, - {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4829cf2195838e3f93b70fd3b4292156fc5e097aac3739859ac0dcc722b27ac0"}, - {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1193b2416cbad1a769f868b1749535d5da47626ac29445803dae7cc64b3f5c98"}, - {file = "orjson-3.10.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:4e6c3da13e5a57e4b3dca2de059f243ebec705857522f188f0180ae88badd354"}, - {file = "orjson-3.10.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c31008598424dfbe52ce8c5b47e0752dca918a4fdc4a2a32004efd9fab41d866"}, - {file = "orjson-3.10.7-cp38-none-win32.whl", hash = "sha256:7122a99831f9e7fe977dc45784d3b2edc821c172d545e6420c375e5a935f5a1c"}, - {file = "orjson-3.10.7-cp38-none-win_amd64.whl", hash = "sha256:a763bc0e58504cc803739e7df040685816145a6f3c8a589787084b54ebc9f16e"}, - {file = "orjson-3.10.7-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e76be12658a6fa376fcd331b1ea4e58f5a06fd0220653450f0d415b8fd0fbe20"}, - {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed350d6978d28b92939bfeb1a0570c523f6170efc3f0a0ef1f1df287cd4f4960"}, - {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:144888c76f8520e39bfa121b31fd637e18d4cc2f115727865fdf9fa325b10412"}, - {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09b2d92fd95ad2402188cf51573acde57eb269eddabaa60f69ea0d733e789fe9"}, - {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b24a579123fa884f3a3caadaed7b75eb5715ee2b17ab5c66ac97d29b18fe57f"}, - {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591bcfe7512353bd609875ab38050efe3d55e18934e2f18950c108334b4ff"}, - {file = "orjson-3.10.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f4db56635b58cd1a200b0a23744ff44206ee6aa428185e2b6c4a65b3197abdcd"}, - {file = "orjson-3.10.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0fa5886854673222618638c6df7718ea7fe2f3f2384c452c9ccedc70b4a510a5"}, - {file = "orjson-3.10.7-cp39-none-win32.whl", hash = "sha256:8272527d08450ab16eb405f47e0f4ef0e5ff5981c3d82afe0efd25dcbef2bcd2"}, - {file = "orjson-3.10.7-cp39-none-win_amd64.whl", hash = "sha256:974683d4618c0c7dbf4f69c95a979734bf183d0658611760017f6e70a145af58"}, - {file = "orjson-3.10.7.tar.gz", hash = "sha256:75ef0640403f945f3a1f9f6400686560dbfb0fb5b16589ad62cd477043c4eee3"}, -] - -[[package]] -name = "packaging" -version = "23.2" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, - {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, -] - -[[package]] -name = "pandas" -version = "2.2.2" -description = "Powerful data structures for data analysis, time series, and statistics" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"}, - {file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"}, - {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08"}, - {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0"}, - {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51"}, - {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99"}, - {file = "pandas-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772"}, - {file = "pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288"}, - {file = "pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151"}, - {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b"}, - {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee"}, - {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db"}, - {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1"}, - {file = "pandas-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24"}, - {file = "pandas-2.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef"}, - {file = "pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce"}, - {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad"}, - {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad"}, - {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76"}, - {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32"}, - {file = "pandas-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23"}, - {file = "pandas-2.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2"}, - {file = "pandas-2.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd"}, - {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863"}, - {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921"}, - {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a"}, - {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57"}, - {file = "pandas-2.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4"}, - {file = "pandas-2.2.2.tar.gz", hash = "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54"}, -] - -[package.dependencies] -numpy = {version = ">=1.23.2", markers = "python_version == \"3.11\""} -python-dateutil = ">=2.8.2" -pytz = ">=2020.1" -tzdata = ">=2022.7" - -[package.extras] -all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] -aws = ["s3fs (>=2022.11.0)"] -clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] -compression = ["zstandard (>=0.19.0)"] -computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] -consortium-standard = ["dataframe-api-compat (>=0.1.7)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] -feather = ["pyarrow (>=10.0.1)"] -fss = ["fsspec (>=2022.11.0)"] -gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] -hdf5 = ["tables (>=3.8.0)"] -html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] -mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] -output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] -parquet = ["pyarrow (>=10.0.1)"] -performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] -plot = ["matplotlib (>=3.6.3)"] -postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] -pyarrow = ["pyarrow (>=10.0.1)"] -spss = ["pyreadstat (>=1.2.0)"] -sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] -test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] -xml = ["lxml (>=4.9.2)"] - -[[package]] -name = "platformdirs" -version = "4.2.2" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, - {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, -] - -[package.extras] -docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] -type = ["mypy (>=1.8)"] - -[[package]] -name = "pluggy" -version = "1.5.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "proto-plus" -version = "1.24.0" -description = "Beautiful, Pythonic protocol buffers." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "proto-plus-1.24.0.tar.gz", hash = "sha256:30b72a5ecafe4406b0d339db35b56c4059064e69227b8c3bda7462397f966445"}, - {file = "proto_plus-1.24.0-py3-none-any.whl", hash = "sha256:402576830425e5f6ce4c2a6702400ac79897dab0b4343821aa5188b0fab81a12"}, -] - -[package.dependencies] -protobuf = ">=3.19.0,<6.0.0dev" - -[package.extras] -testing = ["google-api-core (>=1.31.5)"] - -[[package]] -name = "protobuf" -version = "4.25.4" -description = "" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "protobuf-4.25.4-cp310-abi3-win32.whl", hash = "sha256:db9fd45183e1a67722cafa5c1da3e85c6492a5383f127c86c4c4aa4845867dc4"}, - {file = "protobuf-4.25.4-cp310-abi3-win_amd64.whl", hash = "sha256:ba3d8504116a921af46499471c63a85260c1a5fc23333154a427a310e015d26d"}, - {file = "protobuf-4.25.4-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:eecd41bfc0e4b1bd3fa7909ed93dd14dd5567b98c941d6c1ad08fdcab3d6884b"}, - {file = "protobuf-4.25.4-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:4c8a70fdcb995dcf6c8966cfa3a29101916f7225e9afe3ced4395359955d3835"}, - {file = "protobuf-4.25.4-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:3319e073562e2515c6ddc643eb92ce20809f5d8f10fead3332f71c63be6a7040"}, - {file = "protobuf-4.25.4-cp38-cp38-win32.whl", hash = "sha256:7e372cbbda66a63ebca18f8ffaa6948455dfecc4e9c1029312f6c2edcd86c4e1"}, - {file = "protobuf-4.25.4-cp38-cp38-win_amd64.whl", hash = "sha256:051e97ce9fa6067a4546e75cb14f90cf0232dcb3e3d508c448b8d0e4265b61c1"}, - {file = "protobuf-4.25.4-cp39-cp39-win32.whl", hash = "sha256:90bf6fd378494eb698805bbbe7afe6c5d12c8e17fca817a646cd6a1818c696ca"}, - {file = "protobuf-4.25.4-cp39-cp39-win_amd64.whl", hash = "sha256:ac79a48d6b99dfed2729ccccee547b34a1d3d63289c71cef056653a846a2240f"}, - {file = "protobuf-4.25.4-py3-none-any.whl", hash = "sha256:bfbebc1c8e4793cfd58589acfb8a1026be0003e852b9da7db5a4285bde996978"}, - {file = "protobuf-4.25.4.tar.gz", hash = "sha256:0dc4a62cc4052a036ee2204d26fe4d835c62827c855c8a03f29fe6da146b380d"}, -] - -[[package]] -name = "psutil" -version = "6.1.0" -description = "Cross-platform lib for process and system monitoring in Python." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -groups = ["main"] -files = [ - {file = "psutil-6.1.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ff34df86226c0227c52f38b919213157588a678d049688eded74c76c8ba4a5d0"}, - {file = "psutil-6.1.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:c0e0c00aa18ca2d3b2b991643b799a15fc8f0563d2ebb6040f64ce8dc027b942"}, - {file = "psutil-6.1.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:000d1d1ebd634b4efb383f4034437384e44a6d455260aaee2eca1e9c1b55f047"}, - {file = "psutil-6.1.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:5cd2bcdc75b452ba2e10f0e8ecc0b57b827dd5d7aaffbc6821b2a9a242823a76"}, - {file = "psutil-6.1.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:045f00a43c737f960d273a83973b2511430d61f283a44c96bf13a6e829ba8fdc"}, - {file = "psutil-6.1.0-cp27-none-win32.whl", hash = "sha256:9118f27452b70bb1d9ab3198c1f626c2499384935aaf55388211ad982611407e"}, - {file = "psutil-6.1.0-cp27-none-win_amd64.whl", hash = "sha256:a8506f6119cff7015678e2bce904a4da21025cc70ad283a53b099e7620061d85"}, - {file = "psutil-6.1.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6e2dcd475ce8b80522e51d923d10c7871e45f20918e027ab682f94f1c6351688"}, - {file = "psutil-6.1.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0895b8414afafc526712c498bd9de2b063deaac4021a3b3c34566283464aff8e"}, - {file = "psutil-6.1.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dcbfce5d89f1d1f2546a2090f4fcf87c7f669d1d90aacb7d7582addece9fb38"}, - {file = "psutil-6.1.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:498c6979f9c6637ebc3a73b3f87f9eb1ec24e1ce53a7c5173b8508981614a90b"}, - {file = "psutil-6.1.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d905186d647b16755a800e7263d43df08b790d709d575105d419f8b6ef65423a"}, - {file = "psutil-6.1.0-cp36-cp36m-win32.whl", hash = "sha256:6d3fbbc8d23fcdcb500d2c9f94e07b1342df8ed71b948a2649b5cb060a7c94ca"}, - {file = "psutil-6.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1209036fbd0421afde505a4879dee3b2fd7b1e14fee81c0069807adcbbcca747"}, - {file = "psutil-6.1.0-cp37-abi3-win32.whl", hash = "sha256:1ad45a1f5d0b608253b11508f80940985d1d0c8f6111b5cb637533a0e6ddc13e"}, - {file = "psutil-6.1.0-cp37-abi3-win_amd64.whl", hash = "sha256:a8fb3752b491d246034fa4d279ff076501588ce8cbcdbb62c32fd7a377d996be"}, - {file = "psutil-6.1.0.tar.gz", hash = "sha256:353815f59a7f64cdaca1c0307ee13558a0512f6db064e92fe833784f08539c7a"}, -] - -[package.extras] -dev = ["black", "check-manifest", "coverage", "packaging", "pylint", "pyperf", "pypinfo", "pytest-cov", "requests", "rstcheck", "ruff", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "virtualenv", "wheel"] -test = ["pytest", "pytest-xdist", "setuptools"] - -[[package]] -name = "pyasn1" -version = "0.6.0" -description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pyasn1-0.6.0-py2.py3-none-any.whl", hash = "sha256:cca4bb0f2df5504f02f6f8a775b6e416ff9b0b3b16f7ee80b5a3153d9b804473"}, - {file = "pyasn1-0.6.0.tar.gz", hash = "sha256:3a35ab2c4b5ef98e17dfdec8ab074046fbda76e281c5a706ccd82328cfc8f64c"}, -] - -[[package]] -name = "pyasn1-modules" -version = "0.4.0" -description = "A collection of ASN.1-based protocols modules" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pyasn1_modules-0.4.0-py3-none-any.whl", hash = "sha256:be04f15b66c206eed667e0bb5ab27e2b1855ea54a842e5037738099e8ca4ae0b"}, - {file = "pyasn1_modules-0.4.0.tar.gz", hash = "sha256:831dbcea1b177b28c9baddf4c6d1013c24c3accd14a1873fffaa6a2e905f17b6"}, -] - -[package.dependencies] -pyasn1 = ">=0.4.6,<0.7.0" - -[[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "platform_python_implementation != \"PyPy\"" -files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, -] - -[[package]] -name = "pydantic" -version = "2.8.2" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pydantic-2.8.2-py3-none-any.whl", hash = "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"}, - {file = "pydantic-2.8.2.tar.gz", hash = "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a"}, -] - -[package.dependencies] -annotated-types = ">=0.4.0" -pydantic-core = "2.20.1" -typing-extensions = {version = ">=4.6.1", markers = "python_version < \"3.13\""} - -[package.extras] -email = ["email-validator (>=2.0.0)"] - -[[package]] -name = "pydantic-core" -version = "2.20.1" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840"}, - {file = "pydantic_core-2.20.1-cp310-none-win32.whl", hash = "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250"}, - {file = "pydantic_core-2.20.1-cp310-none-win_amd64.whl", hash = "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b"}, - {file = "pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a"}, - {file = "pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd"}, - {file = "pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688"}, - {file = "pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0"}, - {file = "pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e"}, - {file = "pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4745f4ac52cc6686390c40eaa01d48b18997cb130833154801a442323cc78f91"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8ad4c766d3f33ba8fd692f9aa297c9058970530a32c728a2c4bfd2616d3358b"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41e81317dd6a0127cabce83c0c9c3fbecceae981c8391e6f1dec88a77c8a569a"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaad4ff2de1c3823fddf82f41121bdf453d922e9a238642b1dedb33c4e4f98ad"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26ab812fa0c845df815e506be30337e2df27e88399b985d0bb4e3ecfe72df31c"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c5ebac750d9d5f2706654c638c041635c385596caf68f81342011ddfa1e5598"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2aafc5a503855ea5885559eae883978c9b6d8c8993d67766ee73d82e841300dd"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4868f6bd7c9d98904b748a2653031fc9c2f85b6237009d475b1008bfaeb0a5aa"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa2f457b4af386254372dfa78a2eda2563680d982422641a85f271c859df1987"}, - {file = "pydantic_core-2.20.1-cp38-none-win32.whl", hash = "sha256:225b67a1f6d602de0ce7f6c1c3ae89a4aa25d3de9be857999e9124f15dab486a"}, - {file = "pydantic_core-2.20.1-cp38-none-win_amd64.whl", hash = "sha256:6b507132dcfc0dea440cce23ee2182c0ce7aba7054576efc65634f080dbe9434"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b03f7941783b4c4a26051846dea594628b38f6940a2fdc0df00b221aed39314c"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1eedfeb6089ed3fad42e81a67755846ad4dcc14d73698c120a82e4ccf0f1f9f6"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:635fee4e041ab9c479e31edda27fcf966ea9614fff1317e280d99eb3e5ab6fe2"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77bf3ac639c1ff567ae3b47f8d4cc3dc20f9966a2a6dd2311dcc055d3d04fb8a"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ed1b0132f24beeec5a78b67d9388656d03e6a7c837394f99257e2d55b461611"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6514f963b023aeee506678a1cf821fe31159b925c4b76fe2afa94cc70b3222b"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d4204d8ca33146e761c79f83cc861df20e7ae9f6487ca290a97702daf56006"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d036c7187b9422ae5b262badb87a20a49eb6c5238b2004e96d4da1231badef1"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ebfef07dbe1d93efb94b4700f2d278494e9162565a54f124c404a5656d7ff09"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6b9d9bb600328a1ce523ab4f454859e9d439150abb0906c5a1983c146580ebab"}, - {file = "pydantic_core-2.20.1-cp39-none-win32.whl", hash = "sha256:784c1214cb6dd1e3b15dd8b91b9a53852aed16671cc3fbe4786f4f1db07089e2"}, - {file = "pydantic_core-2.20.1-cp39-none-win_amd64.whl", hash = "sha256:d2fe69c5434391727efa54b47a1e7986bb0186e72a41b203df8f5b0a19a4f669"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7"}, - {file = "pydantic_core-2.20.1.tar.gz", hash = "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pydbml" -version = "1.1.1" -description = "Python parser and builder for DBML" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pydbml-1.1.1-py3-none-any.whl", hash = "sha256:dbc0832fc9d24527ed004f4c8d8306cf7a06db4928ec7d5b73d864ab609225f5"}, - {file = "pydbml-1.1.1.tar.gz", hash = "sha256:a9833f93d20a5b48c032bdc8d4f151ca3bd6d8a97ce83301d211810d0b2a16cc"}, -] - -[package.dependencies] -pyparsing = ">=3.0.0" - -[[package]] -name = "pyjwt" -version = "2.9.0" -description = "JSON Web Token implementation in Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850"}, - {file = "pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"}, -] - -[package.extras] -crypto = ["cryptography (>=3.4.0)"] -dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"] -docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] - -[[package]] -name = "pyparsing" -version = "3.1.2" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -optional = false -python-versions = ">=3.6.8" -groups = ["main"] -files = [ - {file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"}, - {file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"}, -] - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - -[[package]] -name = "pyrate-limiter" -version = "3.1.1" -description = "Python Rate-Limiter using Leaky-Bucket Algorithm" -optional = false -python-versions = ">=3.8,<4.0" -groups = ["main"] -files = [ - {file = "pyrate_limiter-3.1.1-py3-none-any.whl", hash = "sha256:c51906f1d51d56dc992ff6c26e8300e32151bc6cfa3e6559792e31971dfd4e2b"}, - {file = "pyrate_limiter-3.1.1.tar.gz", hash = "sha256:2f57eda712687e6eccddf6afe8f8a15b409b97ed675fe64a626058f12863b7b7"}, -] - -[package.extras] -all = ["filelock (>=3.0)", "redis (>=5.0.0,<6.0.0)"] -docs = ["furo (>=2022.3.4,<2023.0.0)", "myst-parser (>=0.17)", "sphinx (>=4.3.0,<5.0.0)", "sphinx-autodoc-typehints (>=1.17,<2.0)", "sphinx-copybutton (>=0.5)", "sphinxcontrib-apidoc (>=0.3,<0.4)"] - -[[package]] -name = "pyrsistent" -version = "0.20.0" -description = "Persistent/Functional/Immutable data structures" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pyrsistent-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c3aba3e01235221e5b229a6c05f585f344734bd1ad42a8ac51493d74722bbce"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1beb78af5423b879edaf23c5591ff292cf7c33979734c99aa66d5914ead880f"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21cc459636983764e692b9eba7144cdd54fdec23ccdb1e8ba392a63666c60c34"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5ac696f02b3fc01a710427585c855f65cd9c640e14f52abe52020722bb4906b"}, - {file = "pyrsistent-0.20.0-cp310-cp310-win32.whl", hash = "sha256:0724c506cd8b63c69c7f883cc233aac948c1ea946ea95996ad8b1380c25e1d3f"}, - {file = "pyrsistent-0.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:8441cf9616d642c475684d6cf2520dd24812e996ba9af15e606df5f6fd9d04a7"}, - {file = "pyrsistent-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0f3b1bcaa1f0629c978b355a7c37acd58907390149b7311b5db1b37648eb6958"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cdd7ef1ea7a491ae70d826b6cc64868de09a1d5ff9ef8d574250d0940e275b8"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cae40a9e3ce178415040a0383f00e8d68b569e97f31928a3a8ad37e3fde6df6a"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6288b3fa6622ad8a91e6eb759cfc48ff3089e7c17fb1d4c59a919769314af224"}, - {file = "pyrsistent-0.20.0-cp311-cp311-win32.whl", hash = "sha256:7d29c23bdf6e5438c755b941cef867ec2a4a172ceb9f50553b6ed70d50dfd656"}, - {file = "pyrsistent-0.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:59a89bccd615551391f3237e00006a26bcf98a4d18623a19909a2c48b8e986ee"}, - {file = "pyrsistent-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:09848306523a3aba463c4b49493a760e7a6ca52e4826aa100ee99d8d39b7ad1e"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a14798c3005ec892bbada26485c2eea3b54109cb2533713e355c806891f63c5e"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b14decb628fac50db5e02ee5a35a9c0772d20277824cfe845c8a8b717c15daa3"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e2c116cc804d9b09ce9814d17df5edf1df0c624aba3b43bc1ad90411487036d"}, - {file = "pyrsistent-0.20.0-cp312-cp312-win32.whl", hash = "sha256:e78d0c7c1e99a4a45c99143900ea0546025e41bb59ebc10182e947cf1ece9174"}, - {file = "pyrsistent-0.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:4021a7f963d88ccd15b523787d18ed5e5269ce57aa4037146a2377ff607ae87d"}, - {file = "pyrsistent-0.20.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:79ed12ba79935adaac1664fd7e0e585a22caa539dfc9b7c7c6d5ebf91fb89054"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f920385a11207dc372a028b3f1e1038bb244b3ec38d448e6d8e43c6b3ba20e98"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f5c2d012671b7391803263419e31b5c7c21e7c95c8760d7fc35602353dee714"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef3992833fbd686ee783590639f4b8343a57f1f75de8633749d984dc0eb16c86"}, - {file = "pyrsistent-0.20.0-cp38-cp38-win32.whl", hash = "sha256:881bbea27bbd32d37eb24dd320a5e745a2a5b092a17f6debc1349252fac85423"}, - {file = "pyrsistent-0.20.0-cp38-cp38-win_amd64.whl", hash = "sha256:6d270ec9dd33cdb13f4d62c95c1a5a50e6b7cdd86302b494217137f760495b9d"}, - {file = "pyrsistent-0.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ca52d1ceae015859d16aded12584c59eb3825f7b50c6cfd621d4231a6cc624ce"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b318ca24db0f0518630e8b6f3831e9cba78f099ed5c1d65ffe3e023003043ba0"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed2c3216a605dc9a6ea50c7e84c82906e3684c4e80d2908208f662a6cbf9022"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e14c95c16211d166f59c6611533d0dacce2e25de0f76e4c140fde250997b3ca"}, - {file = "pyrsistent-0.20.0-cp39-cp39-win32.whl", hash = "sha256:f058a615031eea4ef94ead6456f5ec2026c19fb5bd6bfe86e9665c4158cf802f"}, - {file = "pyrsistent-0.20.0-cp39-cp39-win_amd64.whl", hash = "sha256:58b8f6366e152092194ae68fefe18b9f0b4f89227dfd86a07770c3d86097aebf"}, - {file = "pyrsistent-0.20.0-py3-none-any.whl", hash = "sha256:c55acc4733aad6560a7f5f818466631f07efc001fd023f34a6c203f8b6df0f0b"}, - {file = "pyrsistent-0.20.0.tar.gz", hash = "sha256:4c48f78f62ab596c679086084d0dd13254ae4f3d6c72a83ffdf5ebdef8f265a4"}, -] - -[[package]] -name = "pytest" -version = "8.3.2" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5"}, - {file = "pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=1.5,<2" - -[package.extras] -dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] -files = [ - {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, - {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "python-ulid" -version = "3.0.0" -description = "Universally unique lexicographically sortable identifier" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "python_ulid-3.0.0-py3-none-any.whl", hash = "sha256:e4c4942ff50dbd79167ad01ac725ec58f924b4018025ce22c858bfcff99a5e31"}, - {file = "python_ulid-3.0.0.tar.gz", hash = "sha256:e50296a47dc8209d28629a22fc81ca26c00982c78934bd7766377ba37ea49a9f"}, -] - -[package.extras] -pydantic = ["pydantic (>=2.0)"] - -[[package]] -name = "pytz" -version = "2024.2" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725"}, - {file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"}, -] - -[[package]] -name = "pyyaml" -version = "6.0.2" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, - {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, - {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, - {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, - {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, - {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, - {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, - {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, - {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, - {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, - {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, - {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, - {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, - {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, - {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, - {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, - {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, -] - -[[package]] -name = "rapidfuzz" -version = "3.12.1" -description = "rapid fuzzy string matching" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "rapidfuzz-3.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dbb7ea2fd786e6d66f225ef6eef1728832314f47e82fee877cb2a793ebda9579"}, - {file = "rapidfuzz-3.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1ae41361de05762c1eaa3955e5355de7c4c6f30d1ef1ea23d29bf738a35809ab"}, - {file = "rapidfuzz-3.12.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc3c39e0317e7f68ba01bac056e210dd13c7a0abf823e7b6a5fe7e451ddfc496"}, - {file = "rapidfuzz-3.12.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:69f2520296f1ae1165b724a3aad28c56fd0ac7dd2e4cff101a5d986e840f02d4"}, - {file = "rapidfuzz-3.12.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34dcbf5a7daecebc242f72e2500665f0bde9dd11b779246c6d64d106a7d57c99"}, - {file = "rapidfuzz-3.12.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:773ab37fccf6e0513891f8eb4393961ddd1053c6eb7e62eaa876e94668fc6d31"}, - {file = "rapidfuzz-3.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ecf0e6de84c0bc2c0f48bc03ba23cef2c5f1245db7b26bc860c11c6fd7a097c"}, - {file = "rapidfuzz-3.12.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4dc2ebad4adb29d84a661f6a42494df48ad2b72993ff43fad2b9794804f91e45"}, - {file = "rapidfuzz-3.12.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8389d98b9f54cb4f8a95f1fa34bf0ceee639e919807bb931ca479c7a5f2930bf"}, - {file = "rapidfuzz-3.12.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:165bcdecbfed9978962da1d3ec9c191b2ff9f1ccc2668fbaf0613a975b9aa326"}, - {file = "rapidfuzz-3.12.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:129d536740ab0048c1a06ccff73c683f282a2347c68069affae8dbc423a37c50"}, - {file = "rapidfuzz-3.12.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b67e390261ffe98ec86c771b89425a78b60ccb610c3b5874660216fcdbded4b"}, - {file = "rapidfuzz-3.12.1-cp310-cp310-win32.whl", hash = "sha256:a66520180d3426b9dc2f8d312f38e19bc1fc5601f374bae5c916f53fa3534a7d"}, - {file = "rapidfuzz-3.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:82260b20bc7a76556cecb0c063c87dad19246a570425d38f8107b8404ca3ac97"}, - {file = "rapidfuzz-3.12.1-cp310-cp310-win_arm64.whl", hash = "sha256:3a860d103bbb25c69c2e995fdf4fac8cb9f77fb69ec0a00469d7fd87ff148f46"}, - {file = "rapidfuzz-3.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6d9afad7b16d01c9e8929b6a205a18163c7e61b6cd9bcf9c81be77d5afc1067a"}, - {file = "rapidfuzz-3.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bb424ae7240f2d2f7d8dda66a61ebf603f74d92f109452c63b0dbf400204a437"}, - {file = "rapidfuzz-3.12.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42149e6d13bd6d06437d2a954dae2184dadbbdec0fdb82dafe92860d99f80519"}, - {file = "rapidfuzz-3.12.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:760ac95d788f2964b73da01e0bdffbe1bf2ad8273d0437565ce9092ae6ad1fbc"}, - {file = "rapidfuzz-3.12.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2cf27e8e4bf7bf9d92ef04f3d2b769e91c3f30ba99208c29f5b41e77271a2614"}, - {file = "rapidfuzz-3.12.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:00ceb8ff3c44ab0d6014106c71709c85dee9feedd6890eff77c814aa3798952b"}, - {file = "rapidfuzz-3.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b61c558574fbc093d85940c3264c08c2b857b8916f8e8f222e7b86b0bb7d12"}, - {file = "rapidfuzz-3.12.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:346a2d8f17224e99f9ef988606c83d809d5917d17ad00207237e0965e54f9730"}, - {file = "rapidfuzz-3.12.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d60d1db1b7e470e71ae096b6456e20ec56b52bde6198e2dbbc5e6769fa6797dc"}, - {file = "rapidfuzz-3.12.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2477da227e266f9c712f11393182c69a99d3c8007ea27f68c5afc3faf401cc43"}, - {file = "rapidfuzz-3.12.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8499c7d963ddea8adb6cffac2861ee39a1053e22ca8a5ee9de1197f8dc0275a5"}, - {file = "rapidfuzz-3.12.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:12802e5c4d8ae104fb6efeeb436098325ce0dca33b461c46e8df015c84fbef26"}, - {file = "rapidfuzz-3.12.1-cp311-cp311-win32.whl", hash = "sha256:e1061311d07e7cdcffa92c9b50c2ab4192907e70ca01b2e8e1c0b6b4495faa37"}, - {file = "rapidfuzz-3.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:c6e4ed63e204daa863a802eec09feea5448617981ba5d150f843ad8e3ae071a4"}, - {file = "rapidfuzz-3.12.1-cp311-cp311-win_arm64.whl", hash = "sha256:920733a28c3af47870835d59ca9879579f66238f10de91d2b4b3f809d1ebfc5b"}, - {file = "rapidfuzz-3.12.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f6235b57ae3faa3f85cb3f90c9fee49b21bd671b76e90fc99e8ca2bdf0b5e4a3"}, - {file = "rapidfuzz-3.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:af4585e5812632c357fee5ab781c29f00cd06bea58f8882ff244cc4906ba6c9e"}, - {file = "rapidfuzz-3.12.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5942dc4460e5030c5f9e1d4c9383de2f3564a2503fe25e13e89021bcbfea2f44"}, - {file = "rapidfuzz-3.12.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b31ab59e1a0df5afc21f3109b6cfd77b34040dbf54f1bad3989f885cfae1e60"}, - {file = "rapidfuzz-3.12.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97c885a7a480b21164f57a706418c9bbc9a496ec6da087e554424358cadde445"}, - {file = "rapidfuzz-3.12.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d844c0587d969ce36fbf4b7cbf0860380ffeafc9ac5e17a7cbe8abf528d07bb"}, - {file = "rapidfuzz-3.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a93c95dce8917bf428064c64024de43ffd34ec5949dd4425780c72bd41f9d969"}, - {file = "rapidfuzz-3.12.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:834f6113d538af358f39296604a1953e55f8eeffc20cb4caf82250edbb8bf679"}, - {file = "rapidfuzz-3.12.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a940aa71a7f37d7f0daac186066bf6668d4d3b7e7ef464cb50bc7ba89eae1f51"}, - {file = "rapidfuzz-3.12.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ec9eaf73501c9a7de2c6938cb3050392e2ee0c5ca3921482acf01476b85a7226"}, - {file = "rapidfuzz-3.12.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3c5ec360694ac14bfaeb6aea95737cf1a6cf805b5fe8ea7fd28814706c7fa838"}, - {file = "rapidfuzz-3.12.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6b5e176524653ac46f1802bdd273a4b44a5f8d0054ed5013a8e8a4b72f254599"}, - {file = "rapidfuzz-3.12.1-cp312-cp312-win32.whl", hash = "sha256:6f463c6f1c42ec90e45d12a6379e18eddd5cdf74138804d8215619b6f4d31cea"}, - {file = "rapidfuzz-3.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:b894fa2b30cd6498a29e5c470cb01c6ea898540b7e048a0342775a5000531334"}, - {file = "rapidfuzz-3.12.1-cp312-cp312-win_arm64.whl", hash = "sha256:43bb17056c5d1332f517b888c4e57846c4b5f936ed304917eeb5c9ac85d940d4"}, - {file = "rapidfuzz-3.12.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:97f824c15bc6933a31d6e3cbfa90188ba0e5043cf2b6dd342c2b90ee8b3fd47c"}, - {file = "rapidfuzz-3.12.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a973b3f5cabf931029a3ae4a0f72e3222e53d412ea85fc37ddc49e1774f00fbf"}, - {file = "rapidfuzz-3.12.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df7880e012228722dec1be02b9ef3898ed023388b8a24d6fa8213d7581932510"}, - {file = "rapidfuzz-3.12.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c78582f50e75e6c2bc38c791ed291cb89cf26a3148c47860c1a04d6e5379c8e"}, - {file = "rapidfuzz-3.12.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2d7d9e6a04d8344b0198c96394c28874086888d0a2b2f605f30d1b27b9377b7d"}, - {file = "rapidfuzz-3.12.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5620001fd4d6644a2f56880388179cc8f3767670f0670160fcb97c3b46c828af"}, - {file = "rapidfuzz-3.12.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0666ab4c52e500af7ba5cc17389f5d15c0cdad06412c80312088519fdc25686d"}, - {file = "rapidfuzz-3.12.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:27b4d440fa50b50c515a91a01ee17e8ede719dca06eef4c0cccf1a111a4cfad3"}, - {file = "rapidfuzz-3.12.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:83dccfd5a754f2a0e8555b23dde31f0f7920601bfa807aa76829391ea81e7c67"}, - {file = "rapidfuzz-3.12.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b572b634740e047c53743ed27a1bb3b4f93cf4abbac258cd7af377b2c4a9ba5b"}, - {file = "rapidfuzz-3.12.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7fa7b81fb52902d5f78dac42b3d6c835a6633b01ddf9b202a3ca8443be4b2d6a"}, - {file = "rapidfuzz-3.12.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b1d4fbff980cb6baef4ee675963c081f7b5d6580a105d6a4962b20f1f880e1fb"}, - {file = "rapidfuzz-3.12.1-cp313-cp313-win32.whl", hash = "sha256:3fe8da12ea77271097b303fa7624cfaf5afd90261002314e3b0047d36f4afd8d"}, - {file = "rapidfuzz-3.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:6f7e92fc7d2a7f02e1e01fe4f539324dfab80f27cb70a30dd63a95445566946b"}, - {file = "rapidfuzz-3.12.1-cp313-cp313-win_arm64.whl", hash = "sha256:e31be53d7f4905a6a038296d8b773a79da9ee9f0cd19af9490c5c5a22e37d2e5"}, - {file = "rapidfuzz-3.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bef5c91d5db776523530073cda5b2a276283258d2f86764be4a008c83caf7acd"}, - {file = "rapidfuzz-3.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:841e0c2a5fbe8fc8b9b1a56e924c871899932c0ece7fbd970aa1c32bfd12d4bf"}, - {file = "rapidfuzz-3.12.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:046fc67f3885d94693a2151dd913aaf08b10931639cbb953dfeef3151cb1027c"}, - {file = "rapidfuzz-3.12.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b4d2d39b2e76c17f92edd6d384dc21fa020871c73251cdfa017149358937a41d"}, - {file = "rapidfuzz-3.12.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5857dda85165b986c26a474b22907db6b93932c99397c818bcdec96340a76d5"}, - {file = "rapidfuzz-3.12.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4c26cd1b9969ea70dbf0dbda3d2b54ab4b2e683d0fd0f17282169a19563efeb1"}, - {file = "rapidfuzz-3.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf56ea4edd69005786e6c80a9049d95003aeb5798803e7a2906194e7a3cb6472"}, - {file = "rapidfuzz-3.12.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fbe7580b5fb2db8ebd53819171ff671124237a55ada3f64d20fc9a149d133960"}, - {file = "rapidfuzz-3.12.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:018506a53c3b20dcbda8c93d4484b9eb1764c93d5ea16be103cf6b0d8b11d860"}, - {file = "rapidfuzz-3.12.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:325c9c71b737fcd32e2a4e634c430c07dd3d374cfe134eded3fe46e4c6f9bf5d"}, - {file = "rapidfuzz-3.12.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:930756639643e3aa02d3136b6fec74e5b9370a24f8796e1065cd8a857a6a6c50"}, - {file = "rapidfuzz-3.12.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0acbd27543b158cb915fde03877383816a9e83257832818f1e803bac9b394900"}, - {file = "rapidfuzz-3.12.1-cp39-cp39-win32.whl", hash = "sha256:80ff9283c54d7d29b2d954181e137deee89bec62f4a54675d8b6dbb6b15d3e03"}, - {file = "rapidfuzz-3.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:fd37e53f0ed239d0cec27b250cec958982a8ba252ce64aa5e6052de3a82fa8db"}, - {file = "rapidfuzz-3.12.1-cp39-cp39-win_arm64.whl", hash = "sha256:4a4422e4f73a579755ab60abccb3ff148b5c224b3c7454a13ca217dfbad54da6"}, - {file = "rapidfuzz-3.12.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b7cba636c32a6fc3a402d1cb2c70c6c9f8e6319380aaf15559db09d868a23e56"}, - {file = "rapidfuzz-3.12.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b79286738a43e8df8420c4b30a92712dec6247430b130f8e015c3a78b6d61ac2"}, - {file = "rapidfuzz-3.12.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dc1937198e7ff67e217e60bfa339f05da268d91bb15fec710452d11fe2fdf60"}, - {file = "rapidfuzz-3.12.1-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b85817a57cf8db32dd5d2d66ccfba656d299b09eaf86234295f89f91be1a0db2"}, - {file = "rapidfuzz-3.12.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04283c6f3e79f13a784f844cd5b1df4f518ad0f70c789aea733d106c26e1b4fb"}, - {file = "rapidfuzz-3.12.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a718f740553aad5f4daef790191511da9c6eae893ee1fc2677627e4b624ae2db"}, - {file = "rapidfuzz-3.12.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cbdf145c7e4ebf2e81c794ed7a582c4acad19e886d5ad6676086369bd6760753"}, - {file = "rapidfuzz-3.12.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:0d03ad14a26a477be221fddc002954ae68a9e2402b9d85433f2d0a6af01aa2bb"}, - {file = "rapidfuzz-3.12.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1187aeae9c89e838d2a0a2b954b4052e4897e5f62e5794ef42527bf039d469e"}, - {file = "rapidfuzz-3.12.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd47dfb1bca9673a48b923b3d988b7668ee8efd0562027f58b0f2b7abf27144c"}, - {file = "rapidfuzz-3.12.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:187cdb402e223264eebed2fe671e367e636a499a7a9c82090b8d4b75aa416c2a"}, - {file = "rapidfuzz-3.12.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d6899b41bf6c30282179f77096c1939f1454836440a8ab05b48ebf7026a3b590"}, - {file = "rapidfuzz-3.12.1.tar.gz", hash = "sha256:6a98bbca18b4a37adddf2d8201856441c26e9c981d8895491b5bc857b5f780eb"}, -] - -[package.extras] -all = ["numpy"] - -[[package]] -name = "regex" -version = "2024.7.24" -description = "Alternative regular expression module, to replace re." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "regex-2024.7.24-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b0d3f567fafa0633aee87f08b9276c7062da9616931382993c03808bb68ce"}, - {file = "regex-2024.7.24-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3426de3b91d1bc73249042742f45c2148803c111d1175b283270177fdf669024"}, - {file = "regex-2024.7.24-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f273674b445bcb6e4409bf8d1be67bc4b58e8b46fd0d560055d515b8830063cd"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23acc72f0f4e1a9e6e9843d6328177ae3074b4182167e34119ec7233dfeccf53"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65fd3d2e228cae024c411c5ccdffae4c315271eee4a8b839291f84f796b34eca"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c414cbda77dbf13c3bc88b073a1a9f375c7b0cb5e115e15d4b73ec3a2fbc6f59"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf7a89eef64b5455835f5ed30254ec19bf41f7541cd94f266ab7cbd463f00c41"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19c65b00d42804e3fbea9708f0937d157e53429a39b7c61253ff15670ff62cb5"}, - {file = "regex-2024.7.24-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7a5486ca56c8869070a966321d5ab416ff0f83f30e0e2da1ab48815c8d165d46"}, - {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6f51f9556785e5a203713f5efd9c085b4a45aecd2a42573e2b5041881b588d1f"}, - {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a4997716674d36a82eab3e86f8fa77080a5d8d96a389a61ea1d0e3a94a582cf7"}, - {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:c0abb5e4e8ce71a61d9446040c1e86d4e6d23f9097275c5bd49ed978755ff0fe"}, - {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:18300a1d78cf1290fa583cd8b7cde26ecb73e9f5916690cf9d42de569c89b1ce"}, - {file = "regex-2024.7.24-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:416c0e4f56308f34cdb18c3f59849479dde5b19febdcd6e6fa4d04b6c31c9faa"}, - {file = "regex-2024.7.24-cp310-cp310-win32.whl", hash = "sha256:fb168b5924bef397b5ba13aabd8cf5df7d3d93f10218d7b925e360d436863f66"}, - {file = "regex-2024.7.24-cp310-cp310-win_amd64.whl", hash = "sha256:6b9fc7e9cc983e75e2518496ba1afc524227c163e43d706688a6bb9eca41617e"}, - {file = "regex-2024.7.24-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:382281306e3adaaa7b8b9ebbb3ffb43358a7bbf585fa93821300a418bb975281"}, - {file = "regex-2024.7.24-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4fdd1384619f406ad9037fe6b6eaa3de2749e2e12084abc80169e8e075377d3b"}, - {file = "regex-2024.7.24-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3d974d24edb231446f708c455fd08f94c41c1ff4f04bcf06e5f36df5ef50b95a"}, - {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2ec4419a3fe6cf8a4795752596dfe0adb4aea40d3683a132bae9c30b81e8d73"}, - {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb563dd3aea54c797adf513eeec819c4213d7dbfc311874eb4fd28d10f2ff0f2"}, - {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:45104baae8b9f67569f0f1dca5e1f1ed77a54ae1cd8b0b07aba89272710db61e"}, - {file = "regex-2024.7.24-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:994448ee01864501912abf2bad9203bffc34158e80fe8bfb5b031f4f8e16da51"}, - {file = "regex-2024.7.24-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fac296f99283ac232d8125be932c5cd7644084a30748fda013028c815ba3364"}, - {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7e37e809b9303ec3a179085415cb5f418ecf65ec98cdfe34f6a078b46ef823ee"}, - {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:01b689e887f612610c869421241e075c02f2e3d1ae93a037cb14f88ab6a8934c"}, - {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f6442f0f0ff81775eaa5b05af8a0ffa1dda36e9cf6ec1e0d3d245e8564b684ce"}, - {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:871e3ab2838fbcb4e0865a6e01233975df3a15e6fce93b6f99d75cacbd9862d1"}, - {file = "regex-2024.7.24-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c918b7a1e26b4ab40409820ddccc5d49871a82329640f5005f73572d5eaa9b5e"}, - {file = "regex-2024.7.24-cp311-cp311-win32.whl", hash = "sha256:2dfbb8baf8ba2c2b9aa2807f44ed272f0913eeeba002478c4577b8d29cde215c"}, - {file = "regex-2024.7.24-cp311-cp311-win_amd64.whl", hash = "sha256:538d30cd96ed7d1416d3956f94d54e426a8daf7c14527f6e0d6d425fcb4cca52"}, - {file = "regex-2024.7.24-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:fe4ebef608553aff8deb845c7f4f1d0740ff76fa672c011cc0bacb2a00fbde86"}, - {file = "regex-2024.7.24-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:74007a5b25b7a678459f06559504f1eec2f0f17bca218c9d56f6a0a12bfffdad"}, - {file = "regex-2024.7.24-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7df9ea48641da022c2a3c9c641650cd09f0cd15e8908bf931ad538f5ca7919c9"}, - {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a1141a1dcc32904c47f6846b040275c6e5de0bf73f17d7a409035d55b76f289"}, - {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80c811cfcb5c331237d9bad3bea2c391114588cf4131707e84d9493064d267f9"}, - {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7214477bf9bd195894cf24005b1e7b496f46833337b5dedb7b2a6e33f66d962c"}, - {file = "regex-2024.7.24-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d55588cba7553f0b6ec33130bc3e114b355570b45785cebdc9daed8c637dd440"}, - {file = "regex-2024.7.24-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:558a57cfc32adcf19d3f791f62b5ff564922942e389e3cfdb538a23d65a6b610"}, - {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a512eed9dfd4117110b1881ba9a59b31433caed0c4101b361f768e7bcbaf93c5"}, - {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:86b17ba823ea76256b1885652e3a141a99a5c4422f4a869189db328321b73799"}, - {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5eefee9bfe23f6df09ffb6dfb23809f4d74a78acef004aa904dc7c88b9944b05"}, - {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:731fcd76bbdbf225e2eb85b7c38da9633ad3073822f5ab32379381e8c3c12e94"}, - {file = "regex-2024.7.24-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eaef80eac3b4cfbdd6de53c6e108b4c534c21ae055d1dbea2de6b3b8ff3def38"}, - {file = "regex-2024.7.24-cp312-cp312-win32.whl", hash = "sha256:185e029368d6f89f36e526764cf12bf8d6f0e3a2a7737da625a76f594bdfcbfc"}, - {file = "regex-2024.7.24-cp312-cp312-win_amd64.whl", hash = "sha256:2f1baff13cc2521bea83ab2528e7a80cbe0ebb2c6f0bfad15be7da3aed443908"}, - {file = "regex-2024.7.24-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:66b4c0731a5c81921e938dcf1a88e978264e26e6ac4ec96a4d21ae0354581ae0"}, - {file = "regex-2024.7.24-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:88ecc3afd7e776967fa16c80f974cb79399ee8dc6c96423321d6f7d4b881c92b"}, - {file = "regex-2024.7.24-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:64bd50cf16bcc54b274e20235bf8edbb64184a30e1e53873ff8d444e7ac656b2"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb462f0e346fcf41a901a126b50f8781e9a474d3927930f3490f38a6e73b6950"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a82465ebbc9b1c5c50738536fdfa7cab639a261a99b469c9d4c7dcbb2b3f1e57"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:68a8f8c046c6466ac61a36b65bb2395c74451df2ffb8458492ef49900efed293"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac8e84fff5d27420f3c1e879ce9929108e873667ec87e0c8eeb413a5311adfe"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba2537ef2163db9e6ccdbeb6f6424282ae4dea43177402152c67ef869cf3978b"}, - {file = "regex-2024.7.24-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:43affe33137fcd679bdae93fb25924979517e011f9dea99163f80b82eadc7e53"}, - {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:c9bb87fdf2ab2370f21e4d5636e5317775e5d51ff32ebff2cf389f71b9b13750"}, - {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:945352286a541406f99b2655c973852da7911b3f4264e010218bbc1cc73168f2"}, - {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:8bc593dcce679206b60a538c302d03c29b18e3d862609317cb560e18b66d10cf"}, - {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3f3b6ca8eae6d6c75a6cff525c8530c60e909a71a15e1b731723233331de4169"}, - {file = "regex-2024.7.24-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c51edc3541e11fbe83f0c4d9412ef6c79f664a3745fab261457e84465ec9d5a8"}, - {file = "regex-2024.7.24-cp38-cp38-win32.whl", hash = "sha256:d0a07763776188b4db4c9c7fb1b8c494049f84659bb387b71c73bbc07f189e96"}, - {file = "regex-2024.7.24-cp38-cp38-win_amd64.whl", hash = "sha256:8fd5afd101dcf86a270d254364e0e8dddedebe6bd1ab9d5f732f274fa00499a5"}, - {file = "regex-2024.7.24-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0ffe3f9d430cd37d8fa5632ff6fb36d5b24818c5c986893063b4e5bdb84cdf24"}, - {file = "regex-2024.7.24-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:25419b70ba00a16abc90ee5fce061228206173231f004437730b67ac77323f0d"}, - {file = "regex-2024.7.24-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:33e2614a7ce627f0cdf2ad104797d1f68342d967de3695678c0cb84f530709f8"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d33a0021893ede5969876052796165bab6006559ab845fd7b515a30abdd990dc"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04ce29e2c5fedf296b1a1b0acc1724ba93a36fb14031f3abfb7abda2806c1535"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b16582783f44fbca6fcf46f61347340c787d7530d88b4d590a397a47583f31dd"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:836d3cc225b3e8a943d0b02633fb2f28a66e281290302a79df0e1eaa984ff7c1"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:438d9f0f4bc64e8dea78274caa5af971ceff0f8771e1a2333620969936ba10be"}, - {file = "regex-2024.7.24-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:973335b1624859cb0e52f96062a28aa18f3a5fc77a96e4a3d6d76e29811a0e6e"}, - {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c5e69fd3eb0b409432b537fe3c6f44ac089c458ab6b78dcec14478422879ec5f"}, - {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fbf8c2f00904eaf63ff37718eb13acf8e178cb940520e47b2f05027f5bb34ce3"}, - {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ae2757ace61bc4061b69af19e4689fa4416e1a04840f33b441034202b5cd02d4"}, - {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:44fc61b99035fd9b3b9453f1713234e5a7c92a04f3577252b45feefe1b327759"}, - {file = "regex-2024.7.24-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:84c312cdf839e8b579f504afcd7b65f35d60b6285d892b19adea16355e8343c9"}, - {file = "regex-2024.7.24-cp39-cp39-win32.whl", hash = "sha256:ca5b2028c2f7af4e13fb9fc29b28d0ce767c38c7facdf64f6c2cd040413055f1"}, - {file = "regex-2024.7.24-cp39-cp39-win_amd64.whl", hash = "sha256:7c479f5ae937ec9985ecaf42e2e10631551d909f203e31308c12d703922742f9"}, - {file = "regex-2024.7.24.tar.gz", hash = "sha256:9cfd009eed1a46b27c14039ad5bbc5e71b6367c5b2e6d5f5da0ea91600817506"}, -] - -[[package]] -name = "requests" -version = "2.32.3" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, - {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "requests-cache" -version = "1.2.1" -description = "A persistent cache for python requests" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "requests_cache-1.2.1-py3-none-any.whl", hash = "sha256:1285151cddf5331067baa82598afe2d47c7495a1334bfe7a7d329b43e9fd3603"}, - {file = "requests_cache-1.2.1.tar.gz", hash = "sha256:68abc986fdc5b8d0911318fbb5f7c80eebcd4d01bfacc6685ecf8876052511d1"}, -] - -[package.dependencies] -attrs = ">=21.2" -cattrs = ">=22.2" -platformdirs = ">=2.5" -requests = ">=2.22" -url-normalize = ">=1.4" -urllib3 = ">=1.25.5" - -[package.extras] -all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=6.0.1)", "redis (>=3)", "ujson (>=5.4)"] -bson = ["bson (>=0.5)"] -docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.9)"] -dynamodb = ["boto3 (>=1.15)", "botocore (>=1.18)"] -json = ["ujson (>=5.4)"] -mongodb = ["pymongo (>=3)"] -redis = ["redis (>=3)"] -security = ["itsdangerous (>=2.0)"] -yaml = ["pyyaml (>=6.0.1)"] - -[[package]] -name = "rsa" -version = "4.9" -description = "Pure-Python RSA implementation" -optional = false -python-versions = ">=3.6,<4" -groups = ["main"] -files = [ - {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, - {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, -] - -[package.dependencies] -pyasn1 = ">=0.1.3" - -[[package]] -name = "ruff" -version = "0.3.7" -description = "An extremely fast Python linter and code formatter, written in Rust." -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "ruff-0.3.7-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0e8377cccb2f07abd25e84fc5b2cbe48eeb0fea9f1719cad7caedb061d70e5ce"}, - {file = "ruff-0.3.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:15a4d1cc1e64e556fa0d67bfd388fed416b7f3b26d5d1c3e7d192c897e39ba4b"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d28bdf3d7dc71dd46929fafeec98ba89b7c3550c3f0978e36389b5631b793663"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:379b67d4f49774ba679593b232dcd90d9e10f04d96e3c8ce4a28037ae473f7bb"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c060aea8ad5ef21cdfbbe05475ab5104ce7827b639a78dd55383a6e9895b7c51"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:ebf8f615dde968272d70502c083ebf963b6781aacd3079081e03b32adfe4d58a"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d48098bd8f5c38897b03604f5428901b65e3c97d40b3952e38637b5404b739a2"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da8a4fda219bf9024692b1bc68c9cff4b80507879ada8769dc7e985755d662ea"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c44e0149f1d8b48c4d5c33d88c677a4aa22fd09b1683d6a7ff55b816b5d074f"}, - {file = "ruff-0.3.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3050ec0af72b709a62ecc2aca941b9cd479a7bf2b36cc4562f0033d688e44fa1"}, - {file = "ruff-0.3.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a29cc38e4c1ab00da18a3f6777f8b50099d73326981bb7d182e54a9a21bb4ff7"}, - {file = "ruff-0.3.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b15cc59c19edca917f51b1956637db47e200b0fc5e6e1878233d3a938384b0b"}, - {file = "ruff-0.3.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e491045781b1e38b72c91247cf4634f040f8d0cb3e6d3d64d38dcf43616650b4"}, - {file = "ruff-0.3.7-py3-none-win32.whl", hash = "sha256:bc931de87593d64fad3a22e201e55ad76271f1d5bfc44e1a1887edd0903c7d9f"}, - {file = "ruff-0.3.7-py3-none-win_amd64.whl", hash = "sha256:5ef0e501e1e39f35e03c2acb1d1238c595b8bb36cf7a170e7c1df1b73da00e74"}, - {file = "ruff-0.3.7-py3-none-win_arm64.whl", hash = "sha256:789e144f6dc7019d1f92a812891c645274ed08af6037d11fc65fcbc183b7d59f"}, - {file = "ruff-0.3.7.tar.gz", hash = "sha256:d5c1aebee5162c2226784800ae031f660c350e7a3402c4d1f8ea4e97e232e3ba"}, -] - -[[package]] -name = "serpyco-rs" -version = "1.13.0" -description = "" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "serpyco_rs-1.13.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e722b3053e627d8a304e462bce20cae1670a2c4b0ef875b84d0de0081bec4029"}, - {file = "serpyco_rs-1.13.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f10e89c752ff78d720a42e026b0a9ada70717ad6306a9356f794280167d62bf"}, - {file = "serpyco_rs-1.13.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:99db4ec6b36130d81f409e64759d9e26290138b1000b62f9f244117738aae652"}, - {file = "serpyco_rs-1.13.0-cp310-cp310-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3265d4467a52540e7309d117c87a0fe97a9c942960159b37af55a164186e4885"}, - {file = "serpyco_rs-1.13.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb10e547491d960064e5d935770f503c425b4ab7fc8c81e05b3c4b13bef195b3"}, - {file = "serpyco_rs-1.13.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd38a763e9e23f69aad6ba78a8793b6eab9272b51ab01b36a9e3f6208f5c5525"}, - {file = "serpyco_rs-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35d49d6d81739aa0b264e303e90bede58a6487cbc6a78019df5ab6059ea988cc"}, - {file = "serpyco_rs-1.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:cad636c425d942a8de63b4f0e5a8ff91382f36956c129a629bcfd499d8450de2"}, - {file = "serpyco_rs-1.13.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:2b7ff9a0afc417958203bbb8f4f21ecc47307f6691542af27f61c086870d1c90"}, - {file = "serpyco_rs-1.13.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:657a765f588d23b02ba45b7d3fbe9d828f52eab30836408088abf08ebcbc1969"}, - {file = "serpyco_rs-1.13.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1c6ab6dfbb477745067871d896675d8c8d8d027d4b4bd36df8e6797caaaa169b"}, - {file = "serpyco_rs-1.13.0-cp311-cp311-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:bf3292411b63c89ca1273717cee374c03dd64da044f297166362b7e8d26bb440"}, - {file = "serpyco_rs-1.13.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e568e4bb6ffe51e7f428fe3aa37baa4a0cb52d27a64d7e9a5adfec56d3e8b1f"}, - {file = "serpyco_rs-1.13.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16e6b53056de511e3d211e04e0006924e45591c8f68f2aaae024accf28a6127d"}, - {file = "serpyco_rs-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34ffe84bb8b5fb361499e1cd9b93b06081e5230b80713341be81793d1d590d9b"}, - {file = "serpyco_rs-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:5988d48f5df9558ea874e385b11b6cfc1dd434d5ed64eefb7762b203e74ce16c"}, - {file = "serpyco_rs-1.13.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e7a9d3eb0494984066b6b4d3b8eb25f69a599f401e8ede487efdb035547381b1"}, - {file = "serpyco_rs-1.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47b519aaddc42b9d56a3a4760c74e4ef3a945e84eefbec96788f279efbd050d8"}, - {file = "serpyco_rs-1.13.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e2b463c6b9e307a5fda3579aacb96468c37d14314e3a0070eda2f5789e4b4c6"}, - {file = "serpyco_rs-1.13.0-cp312-cp312-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f659d8c058f223711d475dcae47adb033e3902591cbb1e5e1b17687ca15cd0bb"}, - {file = "serpyco_rs-1.13.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9edc243fdb67a6bd51ec13c9a17cb0d608cfde9beb171ab5200e24045ab123f"}, - {file = "serpyco_rs-1.13.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ad0b85f02f52ea93f8bf068f0e00c8980702be00375b8888090723a21f35e2bc"}, - {file = "serpyco_rs-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9e49a1a2d6eb9b855b34ce6f27dcbfb6e0dbfa675b3e3f760178c059c9c1100"}, - {file = "serpyco_rs-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:915eb70006944a2819077bb706a1e5deb671f9ac0c963bb3b46073604837f7ff"}, - {file = "serpyco_rs-1.13.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:69502ad3c56e6fdb700a27059590cf548a5e1aa03519eef607fdf8f8b320eeed"}, - {file = "serpyco_rs-1.13.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:324c6e3eec175cd8aabef071bcef763836fee94012b0b0819952224f9c7b855c"}, - {file = "serpyco_rs-1.13.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2097cda3ccf641a3c05ff2aa1a0122f4c47ef4de8807fec816afb93cc6570ee5"}, - {file = "serpyco_rs-1.13.0-cp313-cp313-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:54fbcd983b50a5ee294ea6d5b1c99c3f8063206660baec96bb4ab5dc211abe3e"}, - {file = "serpyco_rs-1.13.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea9608615a24aae8e95f3ccb58aeec7767ad54e6b69edffc7a231b4d6236b83c"}, - {file = "serpyco_rs-1.13.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12e4c07e35064a6827473d318e3f60bdf49d8cc2726e5283a51de5ab41a9cc25"}, - {file = "serpyco_rs-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fcbbe5c92d9517a2339a6c51f35c6eda8a0b5ed1a7e741feae960d07369459b"}, - {file = "serpyco_rs-1.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:11d430b894a2c003f103e1584b7ceb799235e4dcf109bc74e9937982ab8e48d6"}, - {file = "serpyco_rs-1.13.0-cp39-cp39-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:323c8f2615236d16dcd7995712fe63a77e6362c791890ced8af13b3b205bdbc8"}, - {file = "serpyco_rs-1.13.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70527c919bb1560728340d62974beaa1ed050f9d33603270477e089fc90dcc53"}, - {file = "serpyco_rs-1.13.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3944a6527ebfa736fc0f5d1841b01fdf9838260aa0f92d9a43ed33b455f911dd"}, - {file = "serpyco_rs-1.13.0-cp39-cp39-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2ce9f0592490eb87de2b91700c06c5fd7ab5112ae471b88ded9252af06b28f2b"}, - {file = "serpyco_rs-1.13.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d23a4b801abeb3494a4832250f8a41648914d0fdc8817bc010a2bbb190aa55ca"}, - {file = "serpyco_rs-1.13.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d57dd8dc10aa7a81d06c4eb2d523b5241047764a8fa65b94e716975b888d1d54"}, - {file = "serpyco_rs-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd96fc057c6cdc1336ab4e5072eb1710661464ae9b171950347c66c68e687d50"}, - {file = "serpyco_rs-1.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:94314ed652545eebdc90e83b671cf961ade881fdd0e1aa5579182d13050f8405"}, - {file = "serpyco_rs-1.13.0.tar.gz", hash = "sha256:981232323d2f195a0281b9beb735d5facfc919de6c65abd764cf908c7ad887fe"}, -] - -[package.dependencies] -attributes-doc = "*" -typing-extensions = "*" - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["main"] -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] - -[[package]] -name = "tenacity" -version = "8.5.0" -description = "Retry code until it succeeds" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "tenacity-8.5.0-py3-none-any.whl", hash = "sha256:b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687"}, - {file = "tenacity-8.5.0.tar.gz", hash = "sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78"}, -] - -[package.extras] -doc = ["reno", "sphinx"] -test = ["pytest", "tornado (>=4.5)", "typeguard"] - -[[package]] -name = "tqdm" -version = "4.66.5" -description = "Fast, Extensible Progress Meter" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "tqdm-4.66.5-py3-none-any.whl", hash = "sha256:90279a3770753eafc9194a0364852159802111925aa30eb3f9d85b0e805ac7cd"}, - {file = "tqdm-4.66.5.tar.gz", hash = "sha256:e1020aef2e5096702d8a025ac7d16b1577279c9d63f8375b63083e9a5f0fcbad"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] -notebook = ["ipywidgets (>=6)"] -slack = ["slack-sdk"] -telegram = ["requests"] - -[[package]] -name = "types-pyyaml" -version = "6.0.12.20241230" -description = "Typing stubs for PyYAML" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "types_PyYAML-6.0.12.20241230-py3-none-any.whl", hash = "sha256:fa4d32565219b68e6dee5f67534c722e53c00d1cfc09c435ef04d7353e1e96e6"}, - {file = "types_pyyaml-6.0.12.20241230.tar.gz", hash = "sha256:7f07622dbd34bb9c8b264fe860a17e0efcad00d50b5f27e93984909d9363498c"}, -] - -[[package]] -name = "typing-extensions" -version = "4.12.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, -] - -[[package]] -name = "tzdata" -version = "2025.1" -description = "Provider of IANA time zone data" -optional = false -python-versions = ">=2" -groups = ["main"] -files = [ - {file = "tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639"}, - {file = "tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694"}, -] - -[[package]] -name = "unidecode" -version = "1.3.8" -description = "ASCII transliterations of Unicode text" -optional = false -python-versions = ">=3.5" -groups = ["main"] -files = [ - {file = "Unidecode-1.3.8-py3-none-any.whl", hash = "sha256:d130a61ce6696f8148a3bd8fe779c99adeb4b870584eeb9526584e9aa091fd39"}, - {file = "Unidecode-1.3.8.tar.gz", hash = "sha256:cfdb349d46ed3873ece4586b96aa75258726e2fa8ec21d6f00a591d98806c2f4"}, -] - -[[package]] -name = "uritemplate" -version = "4.1.1" -description = "Implementation of RFC 6570 URI Templates" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "uritemplate-4.1.1-py2.py3-none-any.whl", hash = "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e"}, - {file = "uritemplate-4.1.1.tar.gz", hash = "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0"}, -] - -[[package]] -name = "url-normalize" -version = "1.4.3" -description = "URL normalization for Python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -groups = ["main"] -files = [ - {file = "url-normalize-1.4.3.tar.gz", hash = "sha256:d23d3a070ac52a67b83a1c59a0e68f8608d1cd538783b401bc9de2c0fac999b2"}, - {file = "url_normalize-1.4.3-py2.py3-none-any.whl", hash = "sha256:ec3c301f04e5bb676d333a7fa162fa977ad2ca04b7e652bfc9fac4e405728eed"}, -] - -[package.dependencies] -six = "*" - -[[package]] -name = "urllib3" -version = "2.2.2" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, - {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "wcmatch" -version = "10.0" -description = "Wildcard/glob file name matcher." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "wcmatch-10.0-py3-none-any.whl", hash = "sha256:0dd927072d03c0a6527a20d2e6ad5ba8d0380e60870c383bc533b71744df7b7a"}, - {file = "wcmatch-10.0.tar.gz", hash = "sha256:e72f0de09bba6a04e0de70937b0cf06e55f36f37b3deb422dfaf854b867b840a"}, -] - -[package.dependencies] -bracex = ">=2.1.1" - -[[package]] -name = "whenever" -version = "0.6.17" -description = "Modern datetime library for Python" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "whenever-0.6.17-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:8e9e905fd19b0679e5ab1a0d0110a1974b89bf4cbd1ff22c9e352db381e4ae4f"}, - {file = "whenever-0.6.17-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cd615e60f992fb9ae9d73fc3581ac63de981e51013b0fffbf8e2bd748c71e3df"}, - {file = "whenever-0.6.17-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd717faa660771bf6f2fda4f75f2693cd79f2a7e975029123284ea3859fb329c"}, - {file = "whenever-0.6.17-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2ea744d9666be8880062da0d6dee690e8f70a2bc2a42b96ee17e10e36b0b5266"}, - {file = "whenever-0.6.17-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f6b32593b44332660402c7e4c681cce6d7859b15a609d66ac3a28a6ad6357c2f"}, - {file = "whenever-0.6.17-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a01e4daaac24e0be48a6cb0bb03fa000a40126b1e9cb8d721ee116b2f44c1bb1"}, - {file = "whenever-0.6.17-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53e88fe9fccb868ee88bb2ee8bfcbc55937d0b40747069f595f10b4832ff1545"}, - {file = "whenever-0.6.17-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2dce7b9faf23325b38ca713b2c7a150a8befc832995213a8ec46fe15af6a03e7"}, - {file = "whenever-0.6.17-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c0925f7bf3448ef4f8c9b93de2d1270b82450a81b5d025a89f486ea61aa94319"}, - {file = "whenever-0.6.17-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:82203a572049070d685499dd695ff1914fee62f32aefa9e9952a60762217aa9e"}, - {file = "whenever-0.6.17-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c30e5b5b82783bc85169c8208ab3acf58648092515017b2a185a598160503dbb"}, - {file = "whenever-0.6.17-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:763e59062adc9adfbde45c3ad8b5f472b337cc5cebc70760627d004a4c286d33"}, - {file = "whenever-0.6.17-cp310-cp310-win32.whl", hash = "sha256:f71387bbe95cd98fc78653b942c6e02ff4245b6add012b3f11796220272984ce"}, - {file = "whenever-0.6.17-cp310-cp310-win_amd64.whl", hash = "sha256:996ab1f6f09bc9e0c699fa58937b5adc25e39e979ebbebfd77bae09221350f3d"}, - {file = "whenever-0.6.17-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:87e28378945182e822e211fcea9e89c7428749fd440b616d6d81365202cbed09"}, - {file = "whenever-0.6.17-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0cf4ee3e8d5a55d788e8a79aeff29482dd4facc38241901f18087c3e662d16ba"}, - {file = "whenever-0.6.17-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e97ffc43cd278f6f58732cd9d83c822faff3b1987c3b7b448b59b208cf6b6293"}, - {file = "whenever-0.6.17-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6ce99533865fd63029fa64aef1cfbd42be1d2ced33da38c82f8c763986583982"}, - {file = "whenever-0.6.17-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68b88e023d64e8ccfabe04028738d8041eccd5a078843cd9b506e51df3375e84"}, - {file = "whenever-0.6.17-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9159bae31f2edaf5e70e4437d871e52f51e7e90f1b9faaac19a8c2bccba5170a"}, - {file = "whenever-0.6.17-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f9c4ee1f1e85f857507d146d56973db28d148f50883babf1da3d24a40bbcf60"}, - {file = "whenever-0.6.17-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0acd8b3238aa28a20d1f93c74fd84c9b59e2662e553a55650a0e663a81d2908d"}, - {file = "whenever-0.6.17-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ae238cd46567b5741806517d307a81cca45fd49902312a9bdde27db5226e8825"}, - {file = "whenever-0.6.17-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:99f72853e8292284c2a89a06ab826892216c04540a0ca84b3d3eaa9317dbe026"}, - {file = "whenever-0.6.17-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ccb6c77b497d651a283ef0f40ada326602b313ee71d22015f53d5496124dfc10"}, - {file = "whenever-0.6.17-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d0a1918c9836dc331cd9a39175806668b57b93d538d288469ad8bedb144ec11b"}, - {file = "whenever-0.6.17-cp311-cp311-win32.whl", hash = "sha256:72492f130a8c5b8abb2d7b16cec33b6d6ed9e294bb63c56ab1030623de4ae343"}, - {file = "whenever-0.6.17-cp311-cp311-win_amd64.whl", hash = "sha256:88dc4961f8f6cd16d9b70db022fd6c86193fad429f98daeb82c8e9ba0ca27e5c"}, - {file = "whenever-0.6.17-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:d72c2413e32e3f382f6def337961ea7f20e66d0452ebc02e2fa215e1c45df73e"}, - {file = "whenever-0.6.17-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d12b891d780d9c98585b507e9f85097085337552b75f160ce6930af96509faa1"}, - {file = "whenever-0.6.17-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:503aaf2acfd5a7926ca5c6dc6ec09fc6c2891f536ab9cbd26a072c94bda3927f"}, - {file = "whenever-0.6.17-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6de09bcddfeb61c822019e88d8abed9ccc1d4f9d1a3a5d62d28d94d2fb6daff5"}, - {file = "whenever-0.6.17-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fdfe430df7f336d8793b6b844f0d2552e1589e39e72b7414ba67139b9b402bed"}, - {file = "whenever-0.6.17-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99776635ac174a3df4a372bfae7420b3de965044d69f2bee08a7486cabba0aaa"}, - {file = "whenever-0.6.17-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdbb6d8dae94b492370949c8d8bf818f9ee0b4a08f304dadf9d6d892b7513676"}, - {file = "whenever-0.6.17-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:45d66e68cdca52ca3e6e4990515d32f6bc4eb6a24ff8cbcbe4df16401dd2d3c7"}, - {file = "whenever-0.6.17-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73947bd633bc658f8a8e2ff2bff34ee7caabd6edd9951bb2d778e6071c772df4"}, - {file = "whenever-0.6.17-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9f9d5b108f9abf39471e3d5ef22ff2fed09cc51a0cfa63c833c393b21b8bdb81"}, - {file = "whenever-0.6.17-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a42231e7623b50a60747a752a97499f6ad03e03ce128bf97ded84e12b0f4a77e"}, - {file = "whenever-0.6.17-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a6d9458d544006131e1210343bf660019abfa11d46f5be8ad2d7616dc82340f4"}, - {file = "whenever-0.6.17-cp312-cp312-win32.whl", hash = "sha256:ca1eda94ca2ef7ad1a1249ea80949be252e78a0f10463e12c81ad126ec6b99e5"}, - {file = "whenever-0.6.17-cp312-cp312-win_amd64.whl", hash = "sha256:fd7de20d6bbb74c6bad528c0346ef679957db21ce8a53f118e53b5f60f76495b"}, - {file = "whenever-0.6.17-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ca9ee5b2b04c5a65112f55ff4a4efcba185f45b95766b669723e8b9a28bdb50b"}, - {file = "whenever-0.6.17-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8bef0cf1cd4282044d98e4af9969239dc139e5b192896d4110d0d3f4139bdb30"}, - {file = "whenever-0.6.17-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:04ac4e1fc1bc0bfb35f2c6a05d52de9fec297ea84ee60c655dec258cca1e6eb7"}, - {file = "whenever-0.6.17-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c792f96d021ba2883e6f4b70cc58b5d970f026eb156ff93866686e27a7cce93"}, - {file = "whenever-0.6.17-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e7a7f938b5533e751702de95a615b7903457a7618b94aef72c062fa871ad691b"}, - {file = "whenever-0.6.17-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:47d2dbb85c512e28c14eede36a148afbb90baa340e113b39b2b9f0e9a3b192dd"}, - {file = "whenever-0.6.17-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea2b49a91853c133e8954dffbf180adca539b3719fd269565bf085ba97b47f5f"}, - {file = "whenever-0.6.17-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:91fcb2f42381a8ad763fc7ee2259375b1ace1306a02266c195af27bd3696e0da"}, - {file = "whenever-0.6.17-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:32e4d5e3429015a5082cd171ceea633c6ea565d90491005cdcef49a7d6a17c99"}, - {file = "whenever-0.6.17-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:f05731f530e4af29582a70cf02f8441027a4534e67b7c484efdf210fc09d0421"}, - {file = "whenever-0.6.17-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0d417b7de29aea2cfa7ea47f344848491d44291f28c038df869017ae66a50b48"}, - {file = "whenever-0.6.17-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8208333ece7f2e0c232feeecbd21bde3888c6782d3b08372ae8b5269938645b3"}, - {file = "whenever-0.6.17-cp313-cp313-win32.whl", hash = "sha256:c4912104731fd2be89cd031d8d34227225f1fae5181f931b91f217e69ded48ff"}, - {file = "whenever-0.6.17-cp313-cp313-win_amd64.whl", hash = "sha256:4f46ad87fab336d7643e0c2248dcd27a0f4ae42ac2c5e864a9d06a8f5538efd0"}, - {file = "whenever-0.6.17-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:53f03ae8c54aa60f5f22c790eb63ad644e97f8fba4b22337572a4e16bc4abb73"}, - {file = "whenever-0.6.17-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:42fce832892578455d46870dc074521e627ba9272b839a8297784059170030f5"}, - {file = "whenever-0.6.17-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ac0786d6cb479275ea627d84536f38b6a408348961856e2e807d82d4dc768ed"}, - {file = "whenever-0.6.17-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3e2f490b5e90b314cf7615435e24effe2356b57fa907fedb98fe58d49c6109c5"}, - {file = "whenever-0.6.17-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c1f25ab893cfa724b319a838ef60b918bd35be8f3f6ded73e6fd6e508b5237e"}, - {file = "whenever-0.6.17-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ac5f644d0d3228e806b5129cebfb824a5e26553a0d47d89fc9e962cffa1b99ed"}, - {file = "whenever-0.6.17-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e185309314b1abcc14c18597dd0dfe7fd8b39670f63a7d9357544994cba0e251"}, - {file = "whenever-0.6.17-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cc78b8a73a71241bf356743dd76133ccf796616823d8bbe170701a51d10b9fd3"}, - {file = "whenever-0.6.17-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0ea05123a0b3673c7cf3ea1fe3d8aa9362571db59f8ea15d7a8fb05d885fd756"}, - {file = "whenever-0.6.17-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:9f0c874dbb49c3a733ce4dde86ffa243f166b9d1db4195e05127ec352b49d617"}, - {file = "whenever-0.6.17-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:86cfbd724b11e8a419056211381bde4c1d35ead4bea8d498c85bee3812cf4e7c"}, - {file = "whenever-0.6.17-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e1514f4a3094f11e1ad63b9defadf375d953709c7806cc1d2396634a7b00a009"}, - {file = "whenever-0.6.17-cp39-cp39-win32.whl", hash = "sha256:715ed172e929327c1b68e107f0dc9520237d92e11c26db95fd05869724f3e9d9"}, - {file = "whenever-0.6.17-cp39-cp39-win_amd64.whl", hash = "sha256:5fed15042b2b0ea44cafb8b7426e99170d3f4cd64dbeb966c77f14985e724d82"}, - {file = "whenever-0.6.17.tar.gz", hash = "sha256:9c4bfe755c8f06726c4031dbbecd0a7710e2058bc2f3b4e4e331755af015f55f"}, -] - -[package.dependencies] -tzdata = {version = ">=2020.1", markers = "sys_platform == \"win32\""} - -[[package]] -name = "xmltodict" -version = "0.14.2" -description = "Makes working with XML feel like you are working with JSON" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "xmltodict-0.14.2-py2.py3-none-any.whl", hash = "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac"}, - {file = "xmltodict-0.14.2.tar.gz", hash = "sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553"}, -] - -[metadata] -lock-version = "2.1" -python-versions = "^3.11,<3.12" -content-hash = "e466a804bd60f1e27e46d44e15e6af3bc4fc90f0b982f21b5c493346c3e09a76" diff --git a/airbyte-ci/connectors/erd/pyproject.toml b/airbyte-ci/connectors/erd/pyproject.toml deleted file mode 100644 index 5fab668695f5..000000000000 --- a/airbyte-ci/connectors/erd/pyproject.toml +++ /dev/null @@ -1,49 +0,0 @@ -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" - -[tool.poetry] -name = "erd" -version = "0.1.1" -description = "Contains utilities for generating ERDs." -authors = ["Airbyte "] -license = "MIT" -homepage = "https://github.com/airbytehq/airbyte" -readme = "README.md" -packages = [ - { include = "erd", from = "src" }, -] - -[tool.poetry.dependencies] -python = "^3.11,<3.12" -airbyte-cdk = "^6.0.0" -click = "^8.1.3" -dpath = "^2.1.6" -google-generativeai = "^0.7.2" -markdown-it-py = ">=2.2.0" -pydbml = "^1.1.0" -pytest = "^8.1.1" -pyyaml = "^6.0" - -[tool.poetry.group.dev.dependencies] -ruff = "^0.3.0" -mypy = "^1.8.0" -types-pyyaml = "^6.0.12.20240311" - -[tool.ruff.lint] -select = ["I", "F"] - -[tool.ruff.lint.isort] -known-first-party = ["connection-retriever"] - -[tool.poe.tasks] -test = "pytest tests" -type_check = "mypy src --disallow-untyped-defs" -pre-push = [] - -[tool.poetry.scripts] -erd = "erd.cli:main" - -[tool.airbyte_ci] -python_versions = ["3.11"] -poe_tasks = ["type_check", "test"] diff --git a/airbyte-ci/connectors/erd/src/erd/__init__.py b/airbyte-ci/connectors/erd/src/erd/__init__.py deleted file mode 100644 index f70ecfc3a89e..000000000000 --- a/airbyte-ci/connectors/erd/src/erd/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. diff --git a/airbyte-ci/connectors/erd/src/erd/dbml_assembler.py b/airbyte-ci/connectors/erd/src/erd/dbml_assembler.py deleted file mode 100644 index db5d8cd16855..000000000000 --- a/airbyte-ci/connectors/erd/src/erd/dbml_assembler.py +++ /dev/null @@ -1,240 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from pathlib import Path -from typing import List, Set, Union - -import yaml -from airbyte_cdk.models import ( - AirbyteCatalog, - AirbyteStream, -) -from airbyte_cdk.sources.declarative.parsers.manifest_reference_resolver import ( - ManifestReferenceResolver, -) -from pydbml import Database # type: ignore # missing library stubs or py.typed marker -from pydbml.classes import ( # type: ignore # missing library stubs or py.typed marker - Column, - Index, - Reference, - Table, -) - -from erd.relationships import Relationships - - -class Source: - def __init__(self, source_folder: Path, source_technical_name: str) -> None: - self._source_folder = source_folder - self._source_technical_name = source_technical_name - - def is_dynamic(self, stream_name: str) -> bool: - """ - This method is a very flaky heuristic to know if a stream is dynamic or not. A stream will be considered dynamic if: - * The stream name is in the schemas folder - * The stream is within the manifest and the schema definition is `InlineSchemaLoader` - """ - manifest_static_streams = set() - if self._has_manifest(): - with open(self._get_manifest_path()) as manifest_file: - resolved_manifest = ManifestReferenceResolver().preprocess_manifest( - yaml.safe_load(manifest_file) - ) - for stream in resolved_manifest["streams"]: - if "schema_loader" not in stream: - # stream is assumed to have `DefaultSchemaLoader` which will show in the schemas folder so we can skip - continue - if stream["schema_loader"]["type"] == "InlineSchemaLoader": - name = ( - stream["name"] - if "name" in stream - else stream.get("$parameters").get("name", None) - ) - if not name: - print(f"Could not retrieve name for this stream: {stream}") - continue - manifest_static_streams.add( - stream["name"] - if "name" in stream - else stream.get("$parameters").get("name", None) - ) - - return ( - stream_name - not in manifest_static_streams | self._get_streams_from_schemas_folder() - ) - - def _get_streams_from_schemas_folder(self) -> Set[str]: - schemas_folder = ( - self._source_folder - / self._source_technical_name.replace("-", "_") - / "schemas" - ) - return ( - { - p.name.replace(".json", "") - for p in schemas_folder.iterdir() - if p.is_file() - } - if schemas_folder.exists() - else set() - ) - - def _get_manifest_path(self) -> Path: - return ( - self._source_folder - / self._source_technical_name.replace("-", "_") - / "manifest.yaml" - ) - - def _has_manifest(self) -> bool: - return self._get_manifest_path().exists() - - -class DbmlAssembler: - def assemble( - self, - source: Source, - discovered_catalog: AirbyteCatalog, - relationships: Relationships, - ) -> Database: - database = Database() - for stream in discovered_catalog.streams: - if source.is_dynamic(stream.name): - print(f"Skipping stream {stream.name} as it is dynamic") - continue - - database.add(self._create_table(stream)) - - self._add_references(source, database, relationships) - - return database - - def _create_table(self, stream: AirbyteStream) -> Table: - dbml_table = Table(stream.name) - for property_name, property_information in stream.json_schema.get( - "properties" - ).items(): - try: - dbml_table.add_column( - Column( - name=property_name, - type=self._extract_type(property_information["type"]), - pk=self._is_pk(stream, property_name), - ) - ) - except (KeyError, ValueError) as exception: - print(f"Ignoring field {property_name}: {exception}") - continue - - if ( - stream.source_defined_primary_key - and len(stream.source_defined_primary_key) > 1 - ): - if any(map(lambda key: len(key) != 1, stream.source_defined_primary_key)): - raise ValueError( - f"Does not support nested key as part of primary key `{stream.source_defined_primary_key}`" - ) - - composite_key_columns = [ - column - for key in stream.source_defined_primary_key - for column in dbml_table.columns - if column.name in key - ] - if len(composite_key_columns) < len(stream.source_defined_primary_key): - raise ValueError("Unexpected error: missing PK column from dbml table") - - dbml_table.add_index( - Index( - subjects=composite_key_columns, - pk=True, - ) - ) - return dbml_table - - def _add_references( - self, source: Source, database: Database, relationships: Relationships - ) -> None: - for stream in relationships["streams"]: - for column_name, relationship in stream["relations"].items(): - if source.is_dynamic(stream["name"]): - print( - f"Skipping relationship as stream {stream['name']} from relationship is dynamic" - ) - continue - - try: - target_table_name, target_column_name = relationship.split( - ".", 1 - ) # we support the field names having dots but not stream name hence we split on the first dot only - except ValueError as exception: - raise ValueError( - f"Could not handle relationship {relationship}" - ) from exception - - if source.is_dynamic(target_table_name): - print( - f"Skipping relationship as target stream {target_table_name} is dynamic" - ) - continue - - try: - database.add_reference( - Reference( - type="<>", # we don't have the information of which relationship type it is so we assume many-to-many for now - col1=self._get_column( - database, stream["name"], column_name - ), - col2=self._get_column( - database, target_table_name, target_column_name - ), - ) - ) - except ValueError as exception: - print(f"Skipping relationship: {exception}") - - def _extract_type(self, property_type: Union[str, List[str]]) -> str: - if isinstance(property_type, str): - return property_type - - types = list(property_type) - if "null" in types: - # As we flag everything as nullable (except PK and cursor field), there is little value in keeping the information in order to - # show this in DBML - types.remove("null") - if len(types) != 1: - raise ValueError( - f"Expected only one type apart from `null` but got {len(types)}: {property_type}" - ) - return types[0] - - def _is_pk(self, stream: AirbyteStream, property_name: str) -> bool: - return stream.source_defined_primary_key == [[property_name]] - - def _get_column( - self, database: Database, table_name: str, column_name: str - ) -> Column: - matching_tables = list( - filter(lambda dbml_table: dbml_table.name == table_name, database.tables) - ) - if len(matching_tables) == 0: - raise ValueError(f"Could not find table {table_name}") - elif len(matching_tables) > 1: - raise ValueError( - f"Unexpected error: many tables found with name {table_name}" - ) - - table: Table = matching_tables[0] - matching_columns = list( - filter(lambda column: column.name == column_name, table.columns) - ) - if len(matching_columns) == 0: - raise ValueError( - f"Could not find column {column_name} in table {table_name}. Columns are: {table.columns}" - ) - elif len(matching_columns) > 1: - raise ValueError( - f"Unexpected error: many columns found with name {column_name} for table {table_name}" - ) - - return matching_columns[0] diff --git a/airbyte-ci/connectors/erd/src/erd/erd_service.py b/airbyte-ci/connectors/erd/src/erd/erd_service.py deleted file mode 100644 index 8a07c918e8c4..000000000000 --- a/airbyte-ci/connectors/erd/src/erd/erd_service.py +++ /dev/null @@ -1,151 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -import copy -import json -from pathlib import Path -from typing import Any - -import dpath -import google.generativeai as genai # type: ignore # missing library stubs or py.typed marker -from airbyte_cdk.models import ( - AirbyteCatalog, -) -from markdown_it import MarkdownIt -from pydbml.renderer.dbml.default import ( # type: ignore # missing library stubs or py.typed marker - DefaultDBMLRenderer, # type: ignore # missing library stubs or py.typed marker -) - -from erd.dbml_assembler import DbmlAssembler, Source -from erd.relationships import Relationships, RelationshipsMerger - - -class ErdService: - def __init__(self, source_technical_name: str, source_path: Path) -> None: - self._source_technical_name = source_technical_name - self._source_path = source_path - self._model = genai.GenerativeModel("gemini-1.5-flash") - - if not self._discovered_catalog_path.exists(): - raise ValueError( - f"Could not find discovered catalog at path {self._discovered_catalog_path}" - ) - - def generate_estimated_relationships(self) -> None: - normalized_catalog = self._normalize_schema_catalog(self._get_catalog()) - estimated_relationships = self._get_relations_from_gemini( - source_name=self._source_path.name, catalog=normalized_catalog - ) - with open( - self._estimated_relationships_file, "w" - ) as estimated_relationship_file: - json.dump(estimated_relationships, estimated_relationship_file, indent=4) - - def write_dbml_file(self) -> None: - database = DbmlAssembler().assemble( - Source(self._source_path, self._source_technical_name), - self._get_catalog(), - RelationshipsMerger().merge( - self._get_relationships(self._estimated_relationships_file), - self._get_relationships(self._confirmed_relationships_file), - ), - ) - - with open(self._erd_folder / "source.dbml", "w") as f: - f.write(DefaultDBMLRenderer.render_db(database)) - - @staticmethod - def _normalize_schema_catalog(catalog: AirbyteCatalog) -> dict[str, Any]: - """ - Foreign key cannot be of type object or array, therefore, we can remove these properties. - :param schema: json_schema in draft7 - :return: json_schema in draft7 with TOP level properties only. - """ - streams = copy.deepcopy(catalog.model_dump())["streams"] - for stream in streams: - to_rem = dpath.search( - stream["json_schema"]["properties"], - ["**"], - afilter=lambda x: isinstance(x, dict) - and ( - "array" in str(x.get("type", "")) - or "object" in str(x.get("type", "")) - ), - ) - for key in to_rem: - stream["json_schema"]["properties"].pop(key) - return streams # type: ignore # as this comes from an AirbyteCatalog dump, the format should be fine - - def _get_relations_from_gemini( - self, source_name: str, catalog: dict[str, Any] - ) -> Relationships: - """ - - :param source_name: - :param catalog: - :return: {"streams":[{'name': 'ads', 'relations': {'account_id': 'ad_account.id', 'campaign_id': 'campaigns.id', 'adset_id': 'ad_sets.id'}}, ...]} - """ - system = "You are an Database developer in charge of communicating well to your users." - - source_desc = """ -You are working on the {source_name} API service. - -The current JSON Schema format is as follows: -{current_schema}, where "streams" has a list of streams, which represents database tables, and list of properties in each, which in turn, represent DB columns. Streams presented in list are the only available ones. -Generate and add a `foreign_key` with reference for each field in top level of properties that is helpful in understanding what the data represents and how are streams related to each other. Pay attention to fields ends with '_id'. - """.format(source_name=source_name, current_schema=catalog) - task = """ -Please provide answer in the following format: -{streams: [{"name": "", "relations": {"": ""} }]} -Pay extra attention that in " "ref_table" should be one of the list of streams, and "column_name" should be one of the property in respective reference stream. -Limitations: -- Not all tables should have relations -- Reference should point to 1 table only. -- table cannot reference on itself, on other words, e.g. `ad_account` cannot have relations with "ad_account" as a "ref_table" - """ - response = self._model.generate_content(f"{system} {source_desc} {task}") - md = MarkdownIt("commonmark") - tokens = md.parse(response.text) - response_json = json.loads(tokens[0].content) - return response_json # type: ignore # we blindly assume Gemini returns a response with the Relationships format as asked - - @staticmethod - def _get_relationships(path: Path) -> Relationships: - if not path.exists(): - return {"streams": []} - - with open(path, "r") as file: - return json.load(file) # type: ignore # we assume the content of the file matches Relationships - - def _get_catalog(self) -> AirbyteCatalog: - with open(self._discovered_catalog_path, "r") as file: - try: - return AirbyteCatalog.model_validate(json.loads(file.read())) - except json.JSONDecodeError as error: - raise ValueError( - f"Could not read json file {self._discovered_catalog_path}: {error}. Please ensure that it is a valid JSON." - ) - - @property - def _erd_folder(self) -> Path: - """ - Note: if this folder change, make sure to update the exported folder in the pipeline - """ - path = self._source_path / "erd" - if not path.exists(): - path.mkdir() - return path - - @property - def _estimated_relationships_file(self) -> Path: - return self._erd_folder / "estimated_relationships.json" - - @property - def _confirmed_relationships_file(self) -> Path: - return self._erd_folder / "confirmed_relationships.json" - - @property - def _discovered_catalog_path(self) -> Path: - """ - Note: if this folder change, make sure to update the exported folder in the pipeline - """ - return self._source_path / "erd" / "discovered_catalog.json" diff --git a/airbyte-ci/connectors/erd/src/erd/relationships.py b/airbyte-ci/connectors/erd/src/erd/relationships.py deleted file mode 100644 index 432b19981124..000000000000 --- a/airbyte-ci/connectors/erd/src/erd/relationships.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -import copy -from typing import List, Optional, TypedDict - -from typing_extensions import NotRequired - - -class Relationship(TypedDict): - name: str - relations: dict[str, str] - false_positives: NotRequired[dict[str, str]] - - -Relationships = TypedDict("Relationships", {"streams": List[Relationship]}) - - -class RelationshipsMerger: - def merge( - self, - estimated_relationships: Relationships, - confirmed_relationships: Relationships, - ) -> Relationships: - streams = [] - for estimated_stream in estimated_relationships["streams"]: - confirmed_relationships_for_stream = self._get_stream( - confirmed_relationships, estimated_stream["name"] - ) - if confirmed_relationships_for_stream: - streams.append( - self._merge_for_stream( - estimated_stream, confirmed_relationships_for_stream - ) - ) # type: ignore # at this point, we know confirmed_relationships_for_stream is not None - else: - streams.append(estimated_stream) - - already_processed_streams = set( - map(lambda relationship: relationship["name"], streams) - ) - for confirmed_stream in confirmed_relationships["streams"]: - if confirmed_stream["name"] not in already_processed_streams: - streams.append( - { - "name": confirmed_stream["name"], - "relations": confirmed_stream["relations"], - } - ) - return {"streams": streams} - - def _merge_for_stream( - self, estimated: Relationship, confirmed: Relationship - ) -> Relationship: - relations = copy.deepcopy(confirmed.get("relations", {})) - - # get estimated but filter out false positives - for field, target in estimated.get("relations", {}).items(): - false_positives = ( - confirmed["false_positives"] if "false_positives" in confirmed else {} - ) - if field not in relations and ( - field not in false_positives - or false_positives.get(field, None) != target - ): # type: ignore # at this point, false_positives should not be None - relations[field] = target - - return { - "name": estimated["name"], - "relations": relations, - } - - def _get_stream( - self, relationships: Relationships, stream_name: str - ) -> Optional[Relationship]: - for stream in relationships["streams"]: - if stream.get("name", None) == stream_name: - return stream - - return None diff --git a/airbyte-ci/connectors/erd/tests/__init__.py b/airbyte-ci/connectors/erd/tests/__init__.py deleted file mode 100644 index f70ecfc3a89e..000000000000 --- a/airbyte-ci/connectors/erd/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. diff --git a/airbyte-ci/connectors/erd/tests/builder.py b/airbyte-ci/connectors/erd/tests/builder.py deleted file mode 100644 index e743edd2be50..000000000000 --- a/airbyte-ci/connectors/erd/tests/builder.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from erd.relationships import Relationship - - -class RelationshipBuilder: - def __init__(self, stream_name: str) -> None: - self._name = stream_name - self._relations: dict[str, str] = {} - self._false_positives: dict[str, str] = {} - - def with_relationship(self, column: str, target: str) -> "RelationshipBuilder": - self._relations[column] = target - return self - - def with_false_positive(self, column: str, target: str) -> "RelationshipBuilder": - self._false_positives[column] = target - return self - - def build(self) -> Relationship: - result = { - "name": self._name, - "relations": self._relations, - } - if self._false_positives: - result["false_positives"] = self._false_positives - return result diff --git a/airbyte-ci/connectors/erd/tests/test_dbml_assembler.py b/airbyte-ci/connectors/erd/tests/test_dbml_assembler.py deleted file mode 100644 index 08356e99856b..000000000000 --- a/airbyte-ci/connectors/erd/tests/test_dbml_assembler.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from unittest import TestCase -from unittest.mock import Mock - -from airbyte_cdk.models import AirbyteCatalog, AirbyteStream, SyncMode - -from erd.dbml_assembler import DbmlAssembler, Source -from tests.builder import RelationshipBuilder - -_A_STREAM_NAME = "a_stream_name" - - -class RelationshipsMergerTest(TestCase): - def setUp(self) -> None: - self._source = Mock(spec=Source) - self._source.is_dynamic.return_value = False - self._assembler = DbmlAssembler() - - def test_given_no_streams_then_database_is_empty(self) -> None: - dbml = self._assembler.assemble( - self._source, - AirbyteCatalog(streams=[]), - {"streams": [RelationshipBuilder(_A_STREAM_NAME).build()]}, - ) - assert not dbml.tables - - def test_given_stream_is_dynamic_then_ignore(self) -> None: - self._source.is_dynamic.return_value = True - dbml = self._assembler.assemble( - self._source, - AirbyteCatalog( - streams=[ - AirbyteStream( - name=_A_STREAM_NAME, - json_schema={"properties": {}}, - supported_sync_modes=[SyncMode.full_refresh], - ) - ] - ), - {"streams": [RelationshipBuilder(_A_STREAM_NAME).build()]}, - ) - assert not dbml.tables - - def test_given_stream_then_populate_table(self) -> None: - dbml = self._assembler.assemble( - self._source, - AirbyteCatalog( - streams=[ - AirbyteStream( - name=_A_STREAM_NAME, - json_schema={ - "properties": { - "a_primary_key": {"type": ["null", "string"]}, - "an_integer": {"type": ["null", "number"]}, - } - }, - supported_sync_modes=[SyncMode.full_refresh], - source_defined_primary_key=[["a_primary_key"]], - ) - ] - ), - {"streams": [RelationshipBuilder(_A_STREAM_NAME).build()]}, - ) - assert len(dbml.tables) == 1 - assert len(dbml.tables[0].columns) == 2 - assert dbml.tables[0].columns[0].name == "a_primary_key" - assert dbml.tables[0].columns[0].pk - assert dbml.tables[0].columns[1].name == "an_integer" diff --git a/airbyte-ci/connectors/erd/tests/test_relationships.py b/airbyte-ci/connectors/erd/tests/test_relationships.py deleted file mode 100644 index 968928eb1763..000000000000 --- a/airbyte-ci/connectors/erd/tests/test_relationships.py +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from unittest import TestCase - -from erd.relationships import Relationships, RelationshipsMerger -from tests.builder import RelationshipBuilder - -_A_STREAM_NAME = "a_stream_name" -_A_COLUMN = "a_column" -_ANOTHER_COLUMN = "another_column" -_A_TARGET = "a_target_table.a_target_column" -_ANOTHER_TARGET = "another_target_table.a_target_column" - - -class RelationshipsMergerTest(TestCase): - def setUp(self) -> None: - self._merger = RelationshipsMerger() - - def test_given_no_confirmed_then_return_estimation(self) -> None: - estimated: Relationships = { - "streams": [ - RelationshipBuilder(_A_STREAM_NAME) - .with_relationship(_A_COLUMN, _A_TARGET) - .build() - ] - } - confirmed: Relationships = {"streams": []} - - merged = self._merger.merge(estimated, confirmed) - - assert merged == estimated - - def test_given_confirmed_as_false_positive_then_remove_from_estimation( - self, - ) -> None: - estimated: Relationships = { - "streams": [ - RelationshipBuilder(_A_STREAM_NAME) - .with_relationship(_A_COLUMN, _A_TARGET) - .build() - ] - } - confirmed: Relationships = { - "streams": [ - RelationshipBuilder(_A_STREAM_NAME) - .with_false_positive(_A_COLUMN, _A_TARGET) - .build() - ] - } - - merged = self._merger.merge(estimated, confirmed) - - assert merged == {"streams": [{"name": "a_stream_name", "relations": {}}]} - - def test_given_no_estimated_but_confirmed_then_return_confirmed_without_false_positives( - self, - ) -> None: - estimated: Relationships = {"streams": []} - confirmed: Relationships = { - "streams": [ - RelationshipBuilder(_A_STREAM_NAME) - .with_relationship(_A_COLUMN, _A_TARGET) - .build() - ] - } - - merged = self._merger.merge(estimated, confirmed) - - assert merged == confirmed - - def test_given_different_columns_then_return_both(self) -> None: - estimated: Relationships = { - "streams": [ - RelationshipBuilder(_A_STREAM_NAME) - .with_relationship(_A_COLUMN, _A_TARGET) - .build() - ] - } - confirmed: Relationships = { - "streams": [ - RelationshipBuilder(_A_STREAM_NAME) - .with_relationship(_ANOTHER_COLUMN, _A_TARGET) - .build() - ] - } - - merged = self._merger.merge(estimated, confirmed) - - assert merged == { - "streams": [ - { - "name": "a_stream_name", - "relations": { - _A_COLUMN: _A_TARGET, - _ANOTHER_COLUMN: _A_TARGET, - }, - } - ] - } - - def test_given_same_column_but_different_value_then_prioritize_confirmed( - self, - ) -> None: - estimated: Relationships = { - "streams": [ - RelationshipBuilder(_A_STREAM_NAME) - .with_relationship(_A_COLUMN, _A_TARGET) - .build() - ] - } - confirmed: Relationships = { - "streams": [ - RelationshipBuilder(_A_STREAM_NAME) - .with_relationship(_A_COLUMN, _ANOTHER_TARGET) - .build() - ] - } - - merged = self._merger.merge(estimated, confirmed) - - assert merged == { - "streams": [ - { - "name": "a_stream_name", - "relations": { - _A_COLUMN: _ANOTHER_TARGET, - }, - } - ] - } diff --git a/airbyte-ci/connectors/live-tests/.gitignore b/airbyte-ci/connectors/live-tests/.gitignore deleted file mode 100644 index 452eecef73dd..000000000000 --- a/airbyte-ci/connectors/live-tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -regression_tests_artifacts diff --git a/airbyte-ci/connectors/live-tests/README.md b/airbyte-ci/connectors/live-tests/README.md deleted file mode 100644 index c866821115bc..000000000000 --- a/airbyte-ci/connectors/live-tests/README.md +++ /dev/null @@ -1,420 +0,0 @@ -# Connector Live Testing - -This project contains utilities for running connector tests against live data. - -## Requirements - -- `docker` -- `Python ^3.11` -- `pipx` -- `poetry` - -## Install - -```bash -# From airbyte-ci/connectors/live-tests -poetry install -``` - -Note that `poetry lock` + `poetry install` didn't seem to have impact on the version of connection_retriever. In order to update this dependency to the latest, I had to `poetry add git+https://github.com/airbytehq/airbyte-platform-internal.git@master#subdirectory=tools/connection-retriever`. - -## Regression tests - -We created a regression test suite to run tests to compare the outputs of connector commands on different versions of the same connector. - -## Validation tests - -The validation test suite makes assertions about the output of airbyte commands for the target version of the connector only. - -## Tutorial(s) - -- [Loom Walkthrough (Airbyte Only)](https://www.loom.com/share/97c49d7818664b119cff6911a8a211a2?sid=4570a5b6-9c81-4db3-ba33-c74dc5845c3c) -- [Internal Docs (Airbyte Only)](https://docs.google.com/document/d/1pzTxJTsooc9iQDlALjvOWtnq6yRTvzVtbkJxY4R36_I/edit) - -### How to Use - -> ⚠️ **Note:** While you can use this tool without building a dev image, to achieve your goals you will likely need to have installed [airbyte-ci](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/README.md) and know how to build a dev image. - -You can run the existing test suites with the following command: - -#### With local connection objects (`config.json`, `catalog.json`, `state.json`) - -```bash -poetry run pytest src/live_tests \ - --connector-image=airbyte/source-faker \ - --config-path= \ - --catalog-path= \ - --target-version=dev \ - --pr-url= # The URL of the PR you are testing -``` - -#### Using a live connection - -The live connection objects will be fetched. - -```bash - poetry run pytest src/live_tests \ - --connector-image=airbyte/source-faker \ - --target-version=dev \ - --pr-url= # The URL of the PR you are testing -``` - -You can also pass local connection objects path to override the live connection objects with `--config-path`, `--state-path` or `--catalog-path`. - -#### Test artifacts - -The test suite run will produce test artifacts in the `/tmp/regression_tests_artifacts/` folder. -**They will get cleared after each test run on prompt exit. Please do not copy them elsewhere in your filesystem as they contain sensitive data that are not meant to be stored outside of your debugging session!** - -##### Artifacts types - -- `report.html`: A report of the test run. -- `stdout.log`: The collected standard output following the command execution -- `stderr.log`: The collected standard error following the command execution -- `http_dump.mitm`: An `mitmproxy` http stream log. Can be consumed with `mitmweb` (version `>=10`) for debugging. -- `http_dump.har`: An `mitmproxy` http stream log in HAR format (a JSON encoded version of the mitm dump). -- `airbyte_messages`: A directory containing `.jsonl` files for each message type (logs, records, traces, controls, states etc.) produced by the connector. -- `duck.db`: A DuckDB database containing the messages produced by the connector. -- `dagger.log`: The log of the Dagger session, useful for debugging errors unrelated to the tests. - -**Tests can also write specific artifacts like diffs under a directory named after the test function.** - -``` -/tmp/regression_tests_artifacts -└── session_1710754231 - ├── duck.db - |── report.html - ├── command_execution_artifacts - │   └── source-orb - │   ├── check - │   │   ├── dev - │   │   │   ├── airbyte_messages - │   │   │   │   ├── connection_status.jsonl - │   │   │   │   └── logs.jsonl - │   │   │   ├── http_dump.har - │   │   │   ├── http_dump.mitm - │   │   │   ├── stderr.log - │   │   │   └── stdout.log - │   │   └── latest - │   │   ├── airbyte_messages - │   │   │   ├── connection_status.jsonl - │   │   │   └── logs.jsonl - │   │   ├── http_dump.har - │   │   ├── http_dump.mitm - │   │   ├── stderr.log - │   │   └── stdout.log - │   ├── discover - │   │   ├── dev - │   │   │   ├── airbyte_messages - │   │   │   │   └── catalog.jsonl - │   │   │   ├── http_dump.har - │   │   │   ├── http_dump.mitm - │   │   │   ├── stderr.log - │   │   │   └── stdout.log - │   │   └── latest - │   │   ├── airbyte_messages - │   │   │   └── catalog.jsonl - │   │   ├── http_dump.har - │   │   ├── http_dump.mitm - │   │   ├── stderr.log - │   │   └── stdout.log - │   ├── read-with-state - │   │   ├── dev - │   │   │   ├── airbyte_messages - │   │   │   │   ├── logs.jsonl - │   │   │   │   ├── records.jsonl - │   │   │   │   ├── states.jsonl - │   │   │   │   └── traces.jsonl - │   │   │   ├── http_dump.har - │   │   │   ├── http_dump.mitm - │   │   │   ├── stderr.log - │   │   │   └── stdout.log - │   │   └── latest - │   │   ├── airbyte_messages - │   │   │   ├── logs.jsonl - │   │   │   ├── records.jsonl - │   │   │   ├── states.jsonl - │   │   │   └── traces.jsonl - │   │   ├── http_dump.har - │   │   ├── http_dump.mitm - │   │   ├── stderr.log - │   │   └── stdout.log - │   └── spec - │   ├── dev - │   │   ├── airbyte_messages - │   │   │   └── spec.jsonl - │   │   ├── stderr.log - │   │   └── stdout.log - │   └── latest - │   ├── airbyte_messages - │   │   └── spec.jsonl - │   ├── stderr.log - │   └── stdout.log - └── dagger.log -``` - -#### HTTP Proxy and caching - -We use a containerized `mitmproxy` to capture the HTTP traffic between the connector and the source. Connector command runs produce `http_dump.mitm` (can be consumed with `mitmproxy` (version `>=10`) for debugging) and `http_dump.har` (a JSON encoded version of the mitm dump) artifacts. -The traffic recorded on the control connector is passed to the target connector proxy to cache the responses for requests with the same URL. This is useful to avoid hitting the source API multiple times when running the same command on different versions of the connector. - -### Custom CLI Arguments - -| Argument | Description | Required/Optional | -|----------------------------|----------------------------------------------------------------------------------------------------------------------------------------------| ----------------- | -| `--connector-image` | Docker image name of the connector to debug (e.g., `airbyte/source-faker`, `airbyte/source-faker`). | Required | -| `--control-version` | Version of the control connector for regression testing. Must be an unambiguous connector version (e.g. 1.2.3 rather than `latest`) | Required | -| `--target-version` | Version of the connector being tested. (Defaults to dev) | Optional | -| `--pr-url` | URL of the pull request being tested. | Required | -| `--connection-id` | ID of the connection for live testing. If not provided, a prompt will appear to choose. | Optional | -| `--config-path` | Path to the custom source configuration file. | Optional | -| `--catalog-path` | Path to the custom configured catalog file. | Optional | -| `--state-path` | Path to the custom state file. | Optional | -| `--http-cache` | Use the HTTP cache for the connector. | Optional | -| `--run-id` | Unique identifier for the test run. If not provided, a timestamp will be used. | Optional | -| `--auto-select-connection` | Automatically select a connection for testing. | Optional | -| `--stream` | Name of the stream to test. Can be specified multiple times to test multiple streams. | Optional | -| `--should-read-with-state` | Specify whether to read with state. If not provided, a prompt will appear to choose. | Optional | -| `--disable-proxy` | Specify whether to disable proxy. If not provided, a proxy will be enabled. | Optional | -| `--test-evaluation-mode` | Whether to run tests in "diagnostic" mode or "strict" mode. In diagnostic mode, eligible tests will always pass unless there's an exception. | Optional | -| `--connection-subset` | The subset of connections to select from. Possible values are "sandboxes" or "all" (defaults to sandboxes). | Optional | - -## Changelog - - -### 0.21.4 -Update connection id to use first 8 chars in the report - -### 0.21.3 -Update dependencies to avoid genson issue - -### 0.21.2 -Fix selected streams filter in regression tests - -### 0.21.1 -Update Python version requirement from 3.10 to 3.11. - -### 0.21.0 -Add `disable_proxy` flag - - -### 0.20.0 -Support multiple connection objects in the regression tests suite. - - -### 0.19.10 -Pin the connection retriever until we make required changes to support the new version. - - -### 0.19.8 - -Give ownership of copied connection object files to the image user to make sure it has permission to write them (config migration). - -### 0.19.7 - -Mount connection objects to readable paths in the container for rootless images. - -### 0.19.6 - -Write connector output to a different in container path to avoid permission issues now that connector images are rootless. - -### 0.19.5 - -Fix `ZeroDivisionError` in Regression test tool - -### 0.19.4 - -Update `connection_retriever` to 0.7.4 - -### 0.19.3 - -Update `get_container_from_id` with the correct new Dagger API. - -### 0.19.2 - -Update Dagger to 0.13.3 - -### 0.19.1 - -Fixed the `UserDict` type annotation not found bug. - -### 0.19.0 - -Delete the `debug`command. - -### 0.18.8 - -Improve error message when failing to retrieve connection. -Ask to double-check that a sync ran with the control version on the selected connection. - -### 0.18.7 - -Improve error message when failing to retrieve connection. - -### 0.18.6 - -Disable the `SortQueryParams` MITM proxy addon to avoid double URL encoding. - -### 0.18.5 - -Relax test_oneof_usage criteria for constant value definitions in connector SPEC output. - -### 0.18.4 - -Bugfix: Use connection-retriever 0.7.2 - -### 0.18.3 - -Updated dependencies. - -### 0.18.2 - -Allow live tests with or without state in CI. - -### 0.18.1 - -Fix extra argument. - -### 0.18.0 - -Add support for selecting from a subset of connections. - -### 0.17.8 - -Fix the self-signed certificate path we bind to Python connectors. - -### 0.17.7 - -Explicitly pass the control version to the connection retriever. Defaults to the latest released version of the connector under test. - -### 0.17.6 - -Display diagnostic test with warning. - -### 0.17.5 - -Performance improvements using caching. - -### 0.17.4 - -Fix control image when running tests in CI. - -### 0.17.3 - -Pin requests dependency. - -### 0.17.2 - -Fix duckdb dependency. - -### 0.17.1 - -Bump the connection-retriever version to fix deprecated query. - -### 0.17.0 - -Enable running in GitHub actions. - -### 0.16.0 - -Enable running with airbyte-ci. - -### 0.15.0 - -Automatic retrieval of connection objects for regression tests. The connection id is not required anymore. - -### 0.14.2 - -Fix KeyError when target & control streams differ. - -### 0.14.1 - -Improve performance when reading records per stream. - -### 0.14.0 - -Track usage via Segment. - -### 0.13.0 - -Show test docstring in the test report. - -### 0.12.0 - -Implement a test to compare schema inferred on both control and target version. - -### 0.11.0 - -Create a global duckdb instance to store messages produced by the connector in target and control version. - -### 0.10.0 - -Show record count per stream in report and list untested streams. - -### 0.9.0 - -Make the regressions tests suite better at handling large connector outputs. - -### 0.8.1 - -Improve diff output. - -### 0.8.0 - -Regression tests: add an HTML report. - -### 0.7.0 - -Improve the proxy workflow and caching logic + generate HAR files. - -### 0.6.6 - -Exit pytest if connection can't be retrieved. - -### 0.6.6 - -Cleanup debug files when prompt is closed. - -### 0.6.5 - -Improve ConnectorRunner logging. - -### 0.6.4 - -Add more data integrity checks to the regression tests suite. - -### 0.6.3 - -Make catalog diffs more readable. - -### 0.6.2 - -Clean up regression test artifacts on any exception. - -### 0.6.1 - -Modify diff output for `discover` and `read` tests. - -### 0.5.1 - -Handle connector command execution errors. - -### 0.5.0 - -Add new tests and confirmation prompts. - -### 0.4.0 - -Introduce DuckDB to store the messages produced by the connector. - -### 0.3.0 - -Pass connection id to the regression tests suite. - -### 0.2.0 - -Declare the regression tests suite. - -### 0.1.0 - -Implement initial primitives and a `debug` command to run connector commands and persist the outputs to local storage. diff --git a/airbyte-ci/connectors/live-tests/poetry.lock b/airbyte-ci/connectors/live-tests/poetry.lock deleted file mode 100644 index 254f971fdab4..000000000000 --- a/airbyte-ci/connectors/live-tests/poetry.lock +++ /dev/null @@ -1,4667 +0,0 @@ -# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. - -[[package]] -name = "aiofiles" -version = "24.1.0" -description = "File support for asyncio." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5"}, - {file = "aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c"}, -] - -[[package]] -name = "aiohappyeyeballs" -version = "2.4.3" -description = "Happy Eyeballs for asyncio" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "aiohappyeyeballs-2.4.3-py3-none-any.whl", hash = "sha256:8a7a83727b2756f394ab2895ea0765a0a8c475e3c71e98d43d76f22b4b435572"}, - {file = "aiohappyeyeballs-2.4.3.tar.gz", hash = "sha256:75cf88a15106a5002a8eb1dab212525c00d1f4c0fa96e551c9fbe6f09a621586"}, -] - -[[package]] -name = "aiohttp" -version = "3.10.9" -description = "Async http client/server framework (asyncio)" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "aiohttp-3.10.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8b3fb28a9ac8f2558760d8e637dbf27aef1e8b7f1d221e8669a1074d1a266bb2"}, - {file = "aiohttp-3.10.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:91aa966858593f64c8a65cdefa3d6dc8fe3c2768b159da84c1ddbbb2c01ab4ef"}, - {file = "aiohttp-3.10.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:63649309da83277f06a15bbdc2a54fbe75efb92caa2c25bb57ca37762789c746"}, - {file = "aiohttp-3.10.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3e7fabedb3fe06933f47f1538df7b3a8d78e13d7167195f51ca47ee12690373"}, - {file = "aiohttp-3.10.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c070430fda1a550a1c3a4c2d7281d3b8cfc0c6715f616e40e3332201a253067"}, - {file = "aiohttp-3.10.9-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:51d0a4901b27272ae54e42067bc4b9a90e619a690b4dc43ea5950eb3070afc32"}, - {file = "aiohttp-3.10.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fec5fac7aea6c060f317f07494961236434928e6f4374e170ef50b3001e14581"}, - {file = "aiohttp-3.10.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:172ad884bb61ad31ed7beed8be776eb17e7fb423f1c1be836d5cb357a096bf12"}, - {file = "aiohttp-3.10.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d646fdd74c25bbdd4a055414f0fe32896c400f38ffbdfc78c68e62812a9e0257"}, - {file = "aiohttp-3.10.9-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e86260b76786c28acf0b5fe31c8dca4c2add95098c709b11e8c35b424ebd4f5b"}, - {file = "aiohttp-3.10.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d7cafc11d70fdd8801abfc2ff276744ae4cb39d8060b6b542c7e44e5f2cfc2"}, - {file = "aiohttp-3.10.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:fc262c3df78c8ff6020c782d9ce02e4bcffe4900ad71c0ecdad59943cba54442"}, - {file = "aiohttp-3.10.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:482c85cf3d429844396d939b22bc2a03849cb9ad33344689ad1c85697bcba33a"}, - {file = "aiohttp-3.10.9-cp310-cp310-win32.whl", hash = "sha256:aeebd3061f6f1747c011e1d0b0b5f04f9f54ad1a2ca183e687e7277bef2e0da2"}, - {file = "aiohttp-3.10.9-cp310-cp310-win_amd64.whl", hash = "sha256:fa430b871220dc62572cef9c69b41e0d70fcb9d486a4a207a5de4c1f25d82593"}, - {file = "aiohttp-3.10.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:16e6a51d8bc96b77f04a6764b4ad03eeef43baa32014fce71e882bd71302c7e4"}, - {file = "aiohttp-3.10.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8bd9125dd0cc8ebd84bff2be64b10fdba7dc6fd7be431b5eaf67723557de3a31"}, - {file = "aiohttp-3.10.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dcf354661f54e6a49193d0b5653a1b011ba856e0b7a76bda2c33e4c6892f34ea"}, - {file = "aiohttp-3.10.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42775de0ca04f90c10c5c46291535ec08e9bcc4756f1b48f02a0657febe89b10"}, - {file = "aiohttp-3.10.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87d1e4185c5d7187684d41ebb50c9aeaaaa06ca1875f4c57593071b0409d2444"}, - {file = "aiohttp-3.10.9-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2695c61cf53a5d4345a43d689f37fc0f6d3a2dc520660aec27ec0f06288d1f9"}, - {file = "aiohttp-3.10.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a3f063b41cc06e8d0b3fcbbfc9c05b7420f41287e0cd4f75ce0a1f3d80729e6"}, - {file = "aiohttp-3.10.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d37f4718002863b82c6f391c8efd4d3a817da37030a29e2682a94d2716209de"}, - {file = "aiohttp-3.10.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2746d8994ebca1bdc55a1e998feff4e94222da709623bb18f6e5cfec8ec01baf"}, - {file = "aiohttp-3.10.9-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6f3c6648aa123bcd73d6f26607d59967b607b0da8ffcc27d418a4b59f4c98c7c"}, - {file = "aiohttp-3.10.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:558b3d223fd631ad134d89adea876e7fdb4c93c849ef195049c063ada82b7d08"}, - {file = "aiohttp-3.10.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:4e6cb75f8ddd9c2132d00bc03c9716add57f4beff1263463724f6398b813e7eb"}, - {file = "aiohttp-3.10.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:608cecd8d58d285bfd52dbca5b6251ca8d6ea567022c8a0eaae03c2589cd9af9"}, - {file = "aiohttp-3.10.9-cp311-cp311-win32.whl", hash = "sha256:36d4fba838be5f083f5490ddd281813b44d69685db910907636bc5dca6322316"}, - {file = "aiohttp-3.10.9-cp311-cp311-win_amd64.whl", hash = "sha256:8be1a65487bdfc285bd5e9baf3208c2132ca92a9b4020e9f27df1b16fab998a9"}, - {file = "aiohttp-3.10.9-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4fd16b30567c5b8e167923be6e027eeae0f20cf2b8a26b98a25115f28ad48ee0"}, - {file = "aiohttp-3.10.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:40ff5b7660f903dc587ed36ef08a88d46840182d9d4b5694e7607877ced698a1"}, - {file = "aiohttp-3.10.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4edc3fd701e2b9a0d605a7b23d3de4ad23137d23fc0dbab726aa71d92f11aaaf"}, - {file = "aiohttp-3.10.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e525b69ee8a92c146ae5b4da9ecd15e518df4d40003b01b454ad694a27f498b5"}, - {file = "aiohttp-3.10.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5002a02c17fcfd796d20bac719981d2fca9c006aac0797eb8f430a58e9d12431"}, - {file = "aiohttp-3.10.9-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd4ceeae2fb8cabdd1b71c82bfdd39662473d3433ec95b962200e9e752fb70d0"}, - {file = "aiohttp-3.10.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6e395c3d1f773cf0651cd3559e25182eb0c03a2777b53b4575d8adc1149c6e9"}, - {file = "aiohttp-3.10.9-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbdb8def5268f3f9cd753a265756f49228a20ed14a480d151df727808b4531dd"}, - {file = "aiohttp-3.10.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f82ace0ec57c94aaf5b0e118d4366cff5889097412c75aa14b4fd5fc0c44ee3e"}, - {file = "aiohttp-3.10.9-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6ebdc3b3714afe1b134b3bbeb5f745eed3ecbcff92ab25d80e4ef299e83a5465"}, - {file = "aiohttp-3.10.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f9ca09414003c0e96a735daa1f071f7d7ed06962ef4fa29ceb6c80d06696d900"}, - {file = "aiohttp-3.10.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1298b854fd31d0567cbb916091be9d3278168064fca88e70b8468875ef9ff7e7"}, - {file = "aiohttp-3.10.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:60ad5b8a7452c0f5645c73d4dad7490afd6119d453d302cd5b72b678a85d6044"}, - {file = "aiohttp-3.10.9-cp312-cp312-win32.whl", hash = "sha256:1a0ee6c0d590c917f1b9629371fce5f3d3f22c317aa96fbdcce3260754d7ea21"}, - {file = "aiohttp-3.10.9-cp312-cp312-win_amd64.whl", hash = "sha256:c46131c6112b534b178d4e002abe450a0a29840b61413ac25243f1291613806a"}, - {file = "aiohttp-3.10.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2bd9f3eac515c16c4360a6a00c38119333901b8590fe93c3257a9b536026594d"}, - {file = "aiohttp-3.10.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8cc0d13b4e3b1362d424ce3f4e8c79e1f7247a00d792823ffd640878abf28e56"}, - {file = "aiohttp-3.10.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ba1a599255ad6a41022e261e31bc2f6f9355a419575b391f9655c4d9e5df5ff5"}, - {file = "aiohttp-3.10.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:776e9f3c9b377fcf097c4a04b241b15691e6662d850168642ff976780609303c"}, - {file = "aiohttp-3.10.9-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8debb45545ad95b58cc16c3c1cc19ad82cffcb106db12b437885dbee265f0ab5"}, - {file = "aiohttp-3.10.9-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2555e4949c8d8782f18ef20e9d39730d2656e218a6f1a21a4c4c0b56546a02e"}, - {file = "aiohttp-3.10.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c54dc329cd44f7f7883a9f4baaefe686e8b9662e2c6c184ea15cceee587d8d69"}, - {file = "aiohttp-3.10.9-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e709d6ac598c5416f879bb1bae3fd751366120ac3fa235a01de763537385d036"}, - {file = "aiohttp-3.10.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:17c272cfe7b07a5bb0c6ad3f234e0c336fb53f3bf17840f66bd77b5815ab3d16"}, - {file = "aiohttp-3.10.9-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0c21c82df33b264216abffff9f8370f303dab65d8eee3767efbbd2734363f677"}, - {file = "aiohttp-3.10.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9331dd34145ff105177855017920dde140b447049cd62bb589de320fd6ddd582"}, - {file = "aiohttp-3.10.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ac3196952c673822ebed8871cf8802e17254fff2a2ed4835d9c045d9b88c5ec7"}, - {file = "aiohttp-3.10.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2c33fa6e10bb7ed262e3ff03cc69d52869514f16558db0626a7c5c61dde3c29f"}, - {file = "aiohttp-3.10.9-cp313-cp313-win32.whl", hash = "sha256:a14e4b672c257a6b94fe934ee62666bacbc8e45b7876f9dd9502d0f0fe69db16"}, - {file = "aiohttp-3.10.9-cp313-cp313-win_amd64.whl", hash = "sha256:a35ed3d03910785f7d9d6f5381f0c24002b2b888b298e6f941b2fc94c5055fcd"}, - {file = "aiohttp-3.10.9-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f392ef50e22c31fa49b5a46af7f983fa3f118f3eccb8522063bee8bfa6755f8"}, - {file = "aiohttp-3.10.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d1f5c9169e26db6a61276008582d945405b8316aae2bb198220466e68114a0f5"}, - {file = "aiohttp-3.10.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8d9d10d10ec27c0d46ddaecc3c5598c4db9ce4e6398ca872cdde0525765caa2f"}, - {file = "aiohttp-3.10.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d97273a52d7f89a75b11ec386f786d3da7723d7efae3034b4dda79f6f093edc1"}, - {file = "aiohttp-3.10.9-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d271f770b52e32236d945911b2082f9318e90ff835d45224fa9e28374303f729"}, - {file = "aiohttp-3.10.9-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7003f33f5f7da1eb02f0446b0f8d2ccf57d253ca6c2e7a5732d25889da82b517"}, - {file = "aiohttp-3.10.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6e00c8a92e7663ed2be6fcc08a2997ff06ce73c8080cd0df10cc0321a3168d7"}, - {file = "aiohttp-3.10.9-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a61df62966ce6507aafab24e124e0c3a1cfbe23c59732987fc0fd0d71daa0b88"}, - {file = "aiohttp-3.10.9-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:60555211a006d26e1a389222e3fab8cd379f28e0fbf7472ee55b16c6c529e3a6"}, - {file = "aiohttp-3.10.9-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:d15a29424e96fad56dc2f3abed10a89c50c099f97d2416520c7a543e8fddf066"}, - {file = "aiohttp-3.10.9-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:a19caae0d670771ea7854ca30df76f676eb47e0fd9b2ee4392d44708f272122d"}, - {file = "aiohttp-3.10.9-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:99f9678bf0e2b1b695e8028fedac24ab6770937932eda695815d5a6618c37e04"}, - {file = "aiohttp-3.10.9-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2914caa46054f3b5ff910468d686742ff8cff54b8a67319d75f5d5945fd0a13d"}, - {file = "aiohttp-3.10.9-cp38-cp38-win32.whl", hash = "sha256:0bc059ecbce835630e635879f5f480a742e130d9821fbe3d2f76610a6698ee25"}, - {file = "aiohttp-3.10.9-cp38-cp38-win_amd64.whl", hash = "sha256:e883b61b75ca6efc2541fcd52a5c8ccfe288b24d97e20ac08fdf343b8ac672ea"}, - {file = "aiohttp-3.10.9-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:fcd546782d03181b0b1d20b43d612429a90a68779659ba8045114b867971ab71"}, - {file = "aiohttp-3.10.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:85711eec2d875cd88c7eb40e734c4ca6d9ae477d6f26bd2b5bb4f7f60e41b156"}, - {file = "aiohttp-3.10.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:02d1d6610588bcd743fae827bd6f2e47e0d09b346f230824b4c6fb85c6065f9c"}, - {file = "aiohttp-3.10.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3668d0c2a4d23fb136a753eba42caa2c0abbd3d9c5c87ee150a716a16c6deec1"}, - {file = "aiohttp-3.10.9-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d7c071235a47d407b0e93aa6262b49422dbe48d7d8566e1158fecc91043dd948"}, - {file = "aiohttp-3.10.9-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ac74e794e3aee92ae8f571bfeaa103a141e409863a100ab63a253b1c53b707eb"}, - {file = "aiohttp-3.10.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bbf94d4a0447705b7775417ca8bb8086cc5482023a6e17cdc8f96d0b1b5aba6"}, - {file = "aiohttp-3.10.9-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb0b2d5d51f96b6cc19e6ab46a7b684be23240426ae951dcdac9639ab111b45e"}, - {file = "aiohttp-3.10.9-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e83dfefb4f7d285c2d6a07a22268344a97d61579b3e0dce482a5be0251d672ab"}, - {file = "aiohttp-3.10.9-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f0a44bb40b6aaa4fb9a5c1ee07880570ecda2065433a96ccff409c9c20c1624a"}, - {file = "aiohttp-3.10.9-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c2b627d3c8982691b06d89d31093cee158c30629fdfebe705a91814d49b554f8"}, - {file = "aiohttp-3.10.9-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:03690541e4cc866eef79626cfa1ef4dd729c5c1408600c8cb9e12e1137eed6ab"}, - {file = "aiohttp-3.10.9-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ad3675c126f2a95bde637d162f8231cff6bc0bc9fbe31bd78075f9ff7921e322"}, - {file = "aiohttp-3.10.9-cp39-cp39-win32.whl", hash = "sha256:1321658f12b6caffafdc35cfba6c882cb014af86bef4e78c125e7e794dfb927b"}, - {file = "aiohttp-3.10.9-cp39-cp39-win_amd64.whl", hash = "sha256:9fdf5c839bf95fc67be5794c780419edb0dbef776edcfc6c2e5e2ffd5ee755fa"}, - {file = "aiohttp-3.10.9.tar.gz", hash = "sha256:143b0026a9dab07a05ad2dd9e46aa859bffdd6348ddc5967b42161168c24f857"}, -] - -[package.dependencies] -aiohappyeyeballs = ">=2.3.0" -aiosignal = ">=1.1.2" -attrs = ">=17.3.0" -frozenlist = ">=1.1.1" -multidict = ">=4.5,<7.0" -yarl = ">=1.12.0,<2.0" - -[package.extras] -speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] - -[[package]] -name = "aioquic" -version = "1.2.0" -description = "An implementation of QUIC and HTTP/3" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "aioquic-1.2.0-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3e23964dfb04526ade6e66f5b7cd0c830421b8138303ab60ba6e204015e7cb0b"}, - {file = "aioquic-1.2.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:84d733332927b76218a3b246216104116f766f5a9b2308ec306cd017b3049660"}, - {file = "aioquic-1.2.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2466499759b31ea4f1d17f4aeb1f8d4297169e05e3c1216d618c9757f4dd740d"}, - {file = "aioquic-1.2.0-cp38-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd75015462ca5070a888110dc201f35a9f4c7459f9201b77adc3c06013611bb8"}, - {file = "aioquic-1.2.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43ae3b11d43400a620ca0b4b4885d12b76a599c2cbddba755f74bebfa65fe587"}, - {file = "aioquic-1.2.0-cp38-abi3-win32.whl", hash = "sha256:910d8c91da86bba003d491d15deaeac3087d1b9d690b9edc1375905d8867b742"}, - {file = "aioquic-1.2.0-cp38-abi3-win_amd64.whl", hash = "sha256:e3dcfb941004333d477225a6689b55fc7f905af5ee6a556eb5083be0354e653a"}, - {file = "aioquic-1.2.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:8e600da7aa7e4a7bc53ee8f45fd66808032127ae00938c119ac77d66633b8961"}, - {file = "aioquic-1.2.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:358e2b9c1e0c24b9933094c3c2cf990faf44d03b64d6f8ff79b4b3f510c6c268"}, - {file = "aioquic-1.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fe683943ea3439dd0aca05ff80e85a552d4b39f9f34858c76ac54c205990e88"}, - {file = "aioquic-1.2.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c22689c33fe4799624aed6faaba0af9e6ea7d31ac45047745828ee68d67fe1d9"}, - {file = "aioquic-1.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3976b75e82d83742c8b811e38d273eda2ca7f81394b6a85da33a02849c5f1d9d"}, - {file = "aioquic-1.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cbe7167b2faee887e115d83d25332c4b8fa4604d5175807d978cb4fe39b4e36e"}, - {file = "aioquic-1.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f81e7946f09501a7c27e3f71b84a455e6bf92346fb5a28ef2d73c9d564463c63"}, - {file = "aioquic-1.2.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:e2c3c127cc3d9eac7a6d05142036bf4b2c593d750a115a2fa42c1f86cbe8c0a0"}, - {file = "aioquic-1.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb917143e7a4de5beba1e695fa89f2b05ef080b450dea07338cc67a9c75e0a4d"}, - {file = "aioquic-1.2.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1de513772fd04ff38028fdf748a9e2dec33d7aa2fbf67fda3011d9a85b620c54"}, - {file = "aioquic-1.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7dcc212bb529900757d8e99a76198b42c2a978ce735a1bfca394033c16cfc33c"}, - {file = "aioquic-1.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e7ce10198f8efa91986ad8ac83fa08e50972e0aacde45bdaf7b9365094e72c0c"}, - {file = "aioquic-1.2.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:6e418c92898a0af306e6f1b6a55a0d3d2597001c57a7b1ba36cf5b47bf41233b"}, - {file = "aioquic-1.2.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:81650d59bef05c514af2cfdcb2946e9d13367b745e68b36881d43630ef563d38"}, - {file = "aioquic-1.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6371c3afa1036294e1505fdbda8c147bc41c5b6709a47459e8c1b4eec41a86ef"}, - {file = "aioquic-1.2.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c332cffa3c2124e5db82b2b9eb2662bd7c39ee2247606b74de689f6d3091b61a"}, - {file = "aioquic-1.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fcc1eb083ed9f8d903482e375281c8c26a5ed2b6bee5ee2be3f13275d8fdb146"}, - {file = "aioquic-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f209ad5edbff8239e994c189dc74428420957448a190f4343faee4caedef4eee"}, - {file = "aioquic-1.2.0.tar.gz", hash = "sha256:f91263bb3f71948c5c8915b4d50ee370004f20a416f67fab3dcc90556c7e7199"}, -] - -[package.dependencies] -certifi = "*" -cryptography = ">=42.0.0" -pylsqpack = ">=0.3.3,<0.4.0" -pyopenssl = ">=24" -service-identity = ">=24.1.0" - -[package.extras] -dev = ["coverage[toml] (>=7.2.2)"] - -[[package]] -name = "aiosignal" -version = "1.3.1" -description = "aiosignal: a list of registered asynchronous callbacks" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, - {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, -] - -[package.dependencies] -frozenlist = ">=1.1.0" - -[[package]] -name = "airbyte-protocol-models" -version = "0.13.0" -description = "Declares the Airbyte Protocol." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "airbyte_protocol_models-0.13.0-py3-none-any.whl", hash = "sha256:fa8b7e1a85f9ae171c50b30d23b317da1740d051994fd3ed648f9dfba00250e2"}, - {file = "airbyte_protocol_models-0.13.0.tar.gz", hash = "sha256:09d8900ba8674a9315fa1799d17026f6b38d2187c08160449540ee93331ed2e7"}, -] - -[package.dependencies] -pydantic = ">=1.9.2,<2.0.0" - -[[package]] -name = "ansicon" -version = "1.89.0" -description = "Python wrapper for loading Jason Hood's ANSICON" -optional = false -python-versions = "*" -groups = ["main"] -markers = "platform_system == \"Windows\"" -files = [ - {file = "ansicon-1.89.0-py2.py3-none-any.whl", hash = "sha256:f1def52d17f65c2c9682cf8370c03f541f410c1752d6a14029f97318e4b9dfec"}, - {file = "ansicon-1.89.0.tar.gz", hash = "sha256:e4d039def5768a47e4afec8e89e83ec3ae5a26bf00ad851f914d1240b444d2b1"}, -] - -[[package]] -name = "anyio" -version = "4.6.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "anyio-4.6.0-py3-none-any.whl", hash = "sha256:c7d2e9d63e31599eeb636c8c5c03a7e108d73b345f064f1c19fdc87b79036a9a"}, - {file = "anyio-4.6.0.tar.gz", hash = "sha256:137b4559cbb034c477165047febb6ff83f390fc3b20bf181c1fc0a728cb8beeb"}, -] - -[package.dependencies] -idna = ">=2.8" -sniffio = ">=1.1" - -[package.extras] -doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.21.0b1)"] -trio = ["trio (>=0.26.1)"] - -[[package]] -name = "asgiref" -version = "3.8.1" -description = "ASGI specs, helper code, and adapters" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"}, - {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"}, -] - -[package.extras] -tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] - -[[package]] -name = "asn1crypto" -version = "1.5.1" -description = "Fast ASN.1 parser and serializer with definitions for private keys, public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, PKCS#12, PKCS#5, X.509 and TSP" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "asn1crypto-1.5.1-py2.py3-none-any.whl", hash = "sha256:db4e40728b728508912cbb3d44f19ce188f218e9eba635821bb4b68564f8fd67"}, - {file = "asn1crypto-1.5.1.tar.gz", hash = "sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c"}, -] - -[[package]] -name = "asyncclick" -version = "8.1.7.2" -description = "Composable command line interface toolkit, async version" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "asyncclick-8.1.7.2-py3-none-any.whl", hash = "sha256:1ab940b04b22cb89b5b400725132b069d01b0c3472a9702c7a2c9d5d007ded02"}, - {file = "asyncclick-8.1.7.2.tar.gz", hash = "sha256:219ea0f29ccdc1bb4ff43bcab7ce0769ac6d48a04f997b43ec6bee99a222daa0"}, -] - -[package.dependencies] -anyio = "*" -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "asyncer" -version = "0.0.5" -description = "Asyncer, async and await, focused on developer experience." -optional = false -python-versions = ">=3.8,<4.0" -groups = ["main"] -files = [ - {file = "asyncer-0.0.5-py3-none-any.whl", hash = "sha256:ba06d6de3c750763868dffacf89b18d40b667605b0241d31c2ee43f188e2ab74"}, - {file = "asyncer-0.0.5.tar.gz", hash = "sha256:2979f3e04cbedfe5cfeb79027dcf7d004fcc4430a0ca0066ae20490f218ec06e"}, -] - -[package.dependencies] -anyio = ">=3.4.0,<5.0" - -[[package]] -name = "attrs" -version = "24.2.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, - {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, -] - -[package.extras] -benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] - -[[package]] -name = "backoff" -version = "2.2.1" -description = "Function decoration for backoff and retry" -optional = false -python-versions = ">=3.7,<4.0" -groups = ["main"] -files = [ - {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, - {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, -] - -[[package]] -name = "beartype" -version = "0.19.0" -description = "Unbearably fast near-real-time hybrid runtime-static type-checking in pure Python." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "beartype-0.19.0-py3-none-any.whl", hash = "sha256:33b2694eda0daf052eb2aff623ed9a8a586703bbf0a90bbc475a83bbf427f699"}, - {file = "beartype-0.19.0.tar.gz", hash = "sha256:de42dfc1ba5c3710fde6c3002e3bd2cad236ed4d2aabe876345ab0b4234a6573"}, -] - -[package.extras] -dev = ["autoapi (>=0.9.0)", "coverage (>=5.5)", "equinox", "jax[cpu]", "jaxtyping", "mypy (>=0.800)", "numba", "numpy", "pandera", "pydata-sphinx-theme (<=0.7.2)", "pygments", "pyright (>=1.1.370)", "pytest (>=4.0.0)", "sphinx", "sphinx (>=4.2.0,<6.0.0)", "sphinxext-opengraph (>=0.7.5)", "tox (>=3.20.1)", "typing-extensions (>=3.10.0.0)"] -doc-rtd = ["autoapi (>=0.9.0)", "pydata-sphinx-theme (<=0.7.2)", "sphinx (>=4.2.0,<6.0.0)", "sphinxext-opengraph (>=0.7.5)"] -test = ["coverage (>=5.5)", "equinox", "jax[cpu]", "jaxtyping", "mypy (>=0.800)", "numba", "numpy", "pandera", "pygments", "pyright (>=1.1.370)", "pytest (>=4.0.0)", "sphinx", "tox (>=3.20.1)", "typing-extensions (>=3.10.0.0)"] -test-tox = ["equinox", "jax[cpu]", "jaxtyping", "mypy (>=0.800)", "numba", "numpy", "pandera", "pygments", "pyright (>=1.1.370)", "pytest (>=4.0.0)", "sphinx", "typing-extensions (>=3.10.0.0)"] -test-tox-coverage = ["coverage (>=5.5)"] - -[[package]] -name = "beautifulsoup4" -version = "4.14.2" -description = "Screen-scraping library" -optional = false -python-versions = ">=3.7.0" -groups = ["main"] -files = [ - {file = "beautifulsoup4-4.14.2-py3-none-any.whl", hash = "sha256:5ef6fa3a8cbece8488d66985560f97ed091e22bbc4e9c2338508a9d5de6d4515"}, - {file = "beautifulsoup4-4.14.2.tar.gz", hash = "sha256:2a98ab9f944a11acee9cc848508ec28d9228abfd522ef0fad6a02a72e0ded69e"}, -] - -[package.dependencies] -soupsieve = ">1.2" -typing-extensions = ">=4.0.0" - -[package.extras] -cchardet = ["cchardet"] -chardet = ["chardet"] -charset-normalizer = ["charset-normalizer"] -html5lib = ["html5lib"] -lxml = ["lxml"] - -[[package]] -name = "blessed" -version = "1.20.0" -description = "Easy, practical library for making terminal apps, by providing an elegant, well-documented interface to Colors, Keyboard input, and screen Positioning capabilities." -optional = false -python-versions = ">=2.7" -groups = ["main"] -files = [ - {file = "blessed-1.20.0-py2.py3-none-any.whl", hash = "sha256:0c542922586a265e699188e52d5f5ac5ec0dd517e5a1041d90d2bbf23f906058"}, - {file = "blessed-1.20.0.tar.gz", hash = "sha256:2cdd67f8746e048f00df47a2880f4d6acbcdb399031b604e34ba8f71d5787680"}, -] - -[package.dependencies] -jinxed = {version = ">=1.1.0", markers = "platform_system == \"Windows\""} -six = ">=1.9.0" -wcwidth = ">=0.1.4" - -[[package]] -name = "blinker" -version = "1.8.2" -description = "Fast, simple object-to-object and broadcast signaling" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "blinker-1.8.2-py3-none-any.whl", hash = "sha256:1779309f71bf239144b9399d06ae925637cf6634cf6bd131104184531bf67c01"}, - {file = "blinker-1.8.2.tar.gz", hash = "sha256:8f77b09d3bf7c795e969e9486f39c2c5e9c39d4ee07424be2bc594ece9642d83"}, -] - -[[package]] -name = "brotli" -version = "1.1.0" -description = "Python bindings for the Brotli compression library" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "Brotli-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1140c64812cb9b06c922e77f1c26a75ec5e3f0fb2bf92cc8c58720dec276752"}, - {file = "Brotli-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8fd5270e906eef71d4a8d19b7c6a43760c6abcfcc10c9101d14eb2357418de9"}, - {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ae56aca0402a0f9a3431cddda62ad71666ca9d4dc3a10a142b9dce2e3c0cda3"}, - {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43ce1b9935bfa1ede40028054d7f48b5469cd02733a365eec8a329ffd342915d"}, - {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7c4855522edb2e6ae7fdb58e07c3ba9111e7621a8956f481c68d5d979c93032e"}, - {file = "Brotli-1.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:38025d9f30cf4634f8309c6874ef871b841eb3c347e90b0851f63d1ded5212da"}, - {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e6a904cb26bfefc2f0a6f240bdf5233be78cd2488900a2f846f3c3ac8489ab80"}, - {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a37b8f0391212d29b3a91a799c8e4a2855e0576911cdfb2515487e30e322253d"}, - {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e84799f09591700a4154154cab9787452925578841a94321d5ee8fb9a9a328f0"}, - {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f66b5337fa213f1da0d9000bc8dc0cb5b896b726eefd9c6046f699b169c41b9e"}, - {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5dab0844f2cf82be357a0eb11a9087f70c5430b2c241493fc122bb6f2bb0917c"}, - {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e4fe605b917c70283db7dfe5ada75e04561479075761a0b3866c081d035b01c1"}, - {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:1e9a65b5736232e7a7f91ff3d02277f11d339bf34099a56cdab6a8b3410a02b2"}, - {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:58d4b711689366d4a03ac7957ab8c28890415e267f9b6589969e74b6e42225ec"}, - {file = "Brotli-1.1.0-cp310-cp310-win32.whl", hash = "sha256:be36e3d172dc816333f33520154d708a2657ea63762ec16b62ece02ab5e4daf2"}, - {file = "Brotli-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128"}, - {file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc"}, - {file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6"}, - {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd"}, - {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf"}, - {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a469274ad18dc0e4d316eefa616d1d0c2ff9da369af19fa6f3daa4f09671fd61"}, - {file = "Brotli-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327"}, - {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd"}, - {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9"}, - {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265"}, - {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8"}, - {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c247dd99d39e0338a604f8c2b3bc7061d5c2e9e2ac7ba9cc1be5a69cb6cd832f"}, - {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1b2c248cd517c222d89e74669a4adfa5577e06ab68771a529060cf5a156e9757"}, - {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2a24c50840d89ded6c9a8fdc7b6ed3692ed4e86f1c4a4a938e1e92def92933e0"}, - {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f31859074d57b4639318523d6ffdca586ace54271a73ad23ad021acd807eb14b"}, - {file = "Brotli-1.1.0-cp311-cp311-win32.whl", hash = "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50"}, - {file = "Brotli-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1"}, - {file = "Brotli-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:32d95b80260d79926f5fab3c41701dbb818fde1c9da590e77e571eefd14abe28"}, - {file = "Brotli-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b760c65308ff1e462f65d69c12e4ae085cff3b332d894637f6273a12a482d09f"}, - {file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409"}, - {file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2"}, - {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451"}, - {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91"}, - {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408"}, - {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0"}, - {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc"}, - {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180"}, - {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248"}, - {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966"}, - {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:87a3044c3a35055527ac75e419dfa9f4f3667a1e887ee80360589eb8c90aabb9"}, - {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c5529b34c1c9d937168297f2c1fde7ebe9ebdd5e121297ff9c043bdb2ae3d6fb"}, - {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ca63e1890ede90b2e4454f9a65135a4d387a4585ff8282bb72964fab893f2111"}, - {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e79e6520141d792237c70bcd7a3b122d00f2613769ae0cb61c52e89fd3443839"}, - {file = "Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0"}, - {file = "Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951"}, - {file = "Brotli-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8bf32b98b75c13ec7cf774164172683d6e7891088f6316e54425fde1efc276d5"}, - {file = "Brotli-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7bc37c4d6b87fb1017ea28c9508b36bbcb0c3d18b4260fcdf08b200c74a6aee8"}, - {file = "Brotli-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c0ef38c7a7014ffac184db9e04debe495d317cc9c6fb10071f7fefd93100a4f"}, - {file = "Brotli-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91d7cc2a76b5567591d12c01f019dd7afce6ba8cba6571187e21e2fc418ae648"}, - {file = "Brotli-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a93dde851926f4f2678e704fadeb39e16c35d8baebd5252c9fd94ce8ce68c4a0"}, - {file = "Brotli-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0db75f47be8b8abc8d9e31bc7aad0547ca26f24a54e6fd10231d623f183d089"}, - {file = "Brotli-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6967ced6730aed543b8673008b5a391c3b1076d834ca438bbd70635c73775368"}, - {file = "Brotli-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7eedaa5d036d9336c95915035fb57422054014ebdeb6f3b42eac809928e40d0c"}, - {file = "Brotli-1.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d487f5432bf35b60ed625d7e1b448e2dc855422e87469e3f450aa5552b0eb284"}, - {file = "Brotli-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:832436e59afb93e1836081a20f324cb185836c617659b07b129141a8426973c7"}, - {file = "Brotli-1.1.0-cp313-cp313-win32.whl", hash = "sha256:43395e90523f9c23a3d5bdf004733246fba087f2948f87ab28015f12359ca6a0"}, - {file = "Brotli-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9011560a466d2eb3f5a6e4929cf4a09be405c64154e12df0dd72713f6500e32b"}, - {file = "Brotli-1.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a090ca607cbb6a34b0391776f0cb48062081f5f60ddcce5d11838e67a01928d1"}, - {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de9d02f5bda03d27ede52e8cfe7b865b066fa49258cbab568720aa5be80a47d"}, - {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2333e30a5e00fe0fe55903c8832e08ee9c3b1382aacf4db26664a16528d51b4b"}, - {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4d4a848d1837973bf0f4b5e54e3bec977d99be36a7895c61abb659301b02c112"}, - {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fdc3ff3bfccdc6b9cc7c342c03aa2400683f0cb891d46e94b64a197910dc4064"}, - {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:5eeb539606f18a0b232d4ba45adccde4125592f3f636a6182b4a8a436548b914"}, - {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:fd5f17ff8f14003595ab414e45fce13d073e0762394f957182e69035c9f3d7c2"}, - {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:069a121ac97412d1fe506da790b3e69f52254b9df4eb665cd42460c837193354"}, - {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e93dfc1a1165e385cc8239fab7c036fb2cd8093728cbd85097b284d7b99249a2"}, - {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:aea440a510e14e818e67bfc4027880e2fb500c2ccb20ab21c7a7c8b5b4703d75"}, - {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_2_i686.whl", hash = "sha256:6974f52a02321b36847cd19d1b8e381bf39939c21efd6ee2fc13a28b0d99348c"}, - {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_2_ppc64le.whl", hash = "sha256:a7e53012d2853a07a4a79c00643832161a910674a893d296c9f1259859a289d2"}, - {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:d7702622a8b40c49bffb46e1e3ba2e81268d5c04a34f460978c6b5517a34dd52"}, - {file = "Brotli-1.1.0-cp36-cp36m-win32.whl", hash = "sha256:a599669fd7c47233438a56936988a2478685e74854088ef5293802123b5b2460"}, - {file = "Brotli-1.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:d143fd47fad1db3d7c27a1b1d66162e855b5d50a89666af46e1679c496e8e579"}, - {file = "Brotli-1.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:11d00ed0a83fa22d29bc6b64ef636c4552ebafcef57154b4ddd132f5638fbd1c"}, - {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f733d788519c7e3e71f0855c96618720f5d3d60c3cb829d8bbb722dddce37985"}, - {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:929811df5462e182b13920da56c6e0284af407d1de637d8e536c5cd00a7daf60"}, - {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b63b949ff929fbc2d6d3ce0e924c9b93c9785d877a21a1b678877ffbbc4423a"}, - {file = "Brotli-1.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d192f0f30804e55db0d0e0a35d83a9fead0e9a359a9ed0285dbacea60cc10a84"}, - {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f296c40e23065d0d6650c4aefe7470d2a25fffda489bcc3eb66083f3ac9f6643"}, - {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:919e32f147ae93a09fe064d77d5ebf4e35502a8df75c29fb05788528e330fe74"}, - {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:23032ae55523cc7bccb4f6a0bf368cd25ad9bcdcc1990b64a647e7bbcce9cb5b"}, - {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:224e57f6eac61cc449f498cc5f0e1725ba2071a3d4f48d5d9dffba42db196438"}, - {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:cb1dac1770878ade83f2ccdf7d25e494f05c9165f5246b46a621cc849341dc01"}, - {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:3ee8a80d67a4334482d9712b8e83ca6b1d9bc7e351931252ebef5d8f7335a547"}, - {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:5e55da2c8724191e5b557f8e18943b1b4839b8efc3ef60d65985bcf6f587dd38"}, - {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:d342778ef319e1026af243ed0a07c97acf3bad33b9f29e7ae6a1f68fd083e90c"}, - {file = "Brotli-1.1.0-cp37-cp37m-win32.whl", hash = "sha256:587ca6d3cef6e4e868102672d3bd9dc9698c309ba56d41c2b9c85bbb903cdb95"}, - {file = "Brotli-1.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2954c1c23f81c2eaf0b0717d9380bd348578a94161a65b3a2afc62c86467dd68"}, - {file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:efa8b278894b14d6da122a72fefcebc28445f2d3f880ac59d46c90f4c13be9a3"}, - {file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:03d20af184290887bdea3f0f78c4f737d126c74dc2f3ccadf07e54ceca3bf208"}, - {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6172447e1b368dcbc458925e5ddaf9113477b0ed542df258d84fa28fc45ceea7"}, - {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a743e5a28af5f70f9c080380a5f908d4d21d40e8f0e0c8901604d15cfa9ba751"}, - {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0541e747cce78e24ea12d69176f6a7ddb690e62c425e01d31cc065e69ce55b48"}, - {file = "Brotli-1.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cdbc1fc1bc0bff1cef838eafe581b55bfbffaed4ed0318b724d0b71d4d377619"}, - {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:890b5a14ce214389b2cc36ce82f3093f96f4cc730c1cffdbefff77a7c71f2a97"}, - {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ab4fbee0b2d9098c74f3057b2bc055a8bd92ccf02f65944a241b4349229185a"}, - {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:141bd4d93984070e097521ed07e2575b46f817d08f9fa42b16b9b5f27b5ac088"}, - {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fce1473f3ccc4187f75b4690cfc922628aed4d3dd013d047f95a9b3919a86596"}, - {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d2b35ca2c7f81d173d2fadc2f4f31e88cc5f7a39ae5b6db5513cf3383b0e0ec7"}, - {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:af6fa6817889314555aede9a919612b23739395ce767fe7fcbea9a80bf140fe5"}, - {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:2feb1d960f760a575dbc5ab3b1c00504b24caaf6986e2dc2b01c09c87866a943"}, - {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:4410f84b33374409552ac9b6903507cdb31cd30d2501fc5ca13d18f73548444a"}, - {file = "Brotli-1.1.0-cp38-cp38-win32.whl", hash = "sha256:db85ecf4e609a48f4b29055f1e144231b90edc90af7481aa731ba2d059226b1b"}, - {file = "Brotli-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3d7954194c36e304e1523f55d7042c59dc53ec20dd4e9ea9d151f1b62b4415c0"}, - {file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5fb2ce4b8045c78ebbc7b8f3c15062e435d47e7393cc57c25115cfd49883747a"}, - {file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7905193081db9bfa73b1219140b3d315831cbff0d8941f22da695832f0dd188f"}, - {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a77def80806c421b4b0af06f45d65a136e7ac0bdca3c09d9e2ea4e515367c7e9"}, - {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dadd1314583ec0bf2d1379f7008ad627cd6336625d6679cf2f8e67081b83acf"}, - {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:901032ff242d479a0efa956d853d16875d42157f98951c0230f69e69f9c09bac"}, - {file = "Brotli-1.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:22fc2a8549ffe699bfba2256ab2ed0421a7b8fadff114a3d201794e45a9ff578"}, - {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ae15b066e5ad21366600ebec29a7ccbc86812ed267e4b28e860b8ca16a2bc474"}, - {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:949f3b7c29912693cee0afcf09acd6ebc04c57af949d9bf77d6101ebb61e388c"}, - {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:89f4988c7203739d48c6f806f1e87a1d96e0806d44f0fba61dba81392c9e474d"}, - {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:de6551e370ef19f8de1807d0a9aa2cdfdce2e85ce88b122fe9f6b2b076837e59"}, - {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0737ddb3068957cf1b054899b0883830bb1fec522ec76b1098f9b6e0f02d9419"}, - {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4f3607b129417e111e30637af1b56f24f7a49e64763253bbc275c75fa887d4b2"}, - {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:6c6e0c425f22c1c719c42670d561ad682f7bfeeef918edea971a79ac5252437f"}, - {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:494994f807ba0b92092a163a0a283961369a65f6cbe01e8891132b7a320e61eb"}, - {file = "Brotli-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f0d8a7a6b5983c2496e364b969f0e526647a06b075d034f3297dc66f3b360c64"}, - {file = "Brotli-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cdad5b9014d83ca68c25d2e9444e28e967ef16e80f6b436918c700c117a85467"}, - {file = "Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724"}, -] - -[[package]] -name = "cachetools" -version = "5.3.3" -description = "Extensible memoizing collections and decorators" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, - {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, -] - -[[package]] -name = "cattrs" -version = "24.1.2" -description = "Composable complex class support for attrs and dataclasses." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "cattrs-24.1.2-py3-none-any.whl", hash = "sha256:67c7495b760168d931a10233f979b28dc04daf853b30752246f4f8471c6d68d0"}, - {file = "cattrs-24.1.2.tar.gz", hash = "sha256:8028cfe1ff5382df59dd36474a86e02d817b06eaf8af84555441bac915d2ef85"}, -] - -[package.dependencies] -attrs = ">=23.1.0" - -[package.extras] -bson = ["pymongo (>=4.4.0)"] -cbor2 = ["cbor2 (>=5.4.6)"] -msgpack = ["msgpack (>=1.0.5)"] -msgspec = ["msgspec (>=0.18.5)"] -orjson = ["orjson (>=3.9.2)"] -pyyaml = ["pyyaml (>=6.0)"] -tomlkit = ["tomlkit (>=0.11.8)"] -ujson = ["ujson (>=5.7.0)"] - -[[package]] -name = "certifi" -version = "2024.8.30" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, - {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, -] - -[[package]] -name = "cffi" -version = "1.17.1" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, - {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, - {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, - {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, - {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, - {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, - {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, - {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, - {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, - {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, - {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, - {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, - {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, - {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, - {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, - {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, -] - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "charset-normalizer" -version = "3.3.2" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7.0" -groups = ["main"] -files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, -] - -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "cloud-sql-python-connector" -version = "1.12.1" -description = "The Cloud SQL Python Connector is a library that can be used alongside a database driver to allow users with sufficient permissions to connect to a Cloud SQL database without having to manually allowlist IPs or manage SSL certificates." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "cloud_sql_python_connector-1.12.1-py2.py3-none-any.whl", hash = "sha256:4cb5750dec34f52c70701c07a3c059f9d3e3c7cfeb2f4eff0691abd10a25204a"}, - {file = "cloud_sql_python_connector-1.12.1.tar.gz", hash = "sha256:94d0adf9bb42685ff0b401c2c51d031d9875d33aa614164f585e178824cced0a"}, -] - -[package.dependencies] -aiofiles = "*" -aiohttp = "*" -cryptography = ">=42.0.0" -google-auth = ">=2.28.0" -pg8000 = {version = ">=1.31.1", optional = true, markers = "extra == \"pg8000\""} -Requests = "*" - -[package.extras] -asyncpg = ["asyncpg (>=0.29.0)"] -pg8000 = ["pg8000 (>=1.31.1)"] -pymysql = ["PyMySQL (>=1.1.0)"] -pytds = ["python-tds (>=1.15.0)"] - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main"] -markers = "sys_platform == \"win32\" or platform_system == \"Windows\"" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "connection-retriever" -version = "1.0.0" -description = "A tool to retrieve connection information from our Airbyte Cloud config api database" -optional = false -python-versions = "^3.10" -groups = ["main"] -files = [] -develop = false - -[package.dependencies] -click = "^8.1.7" -cloud-sql-python-connector = {version = "^1.7.0", extras = ["pg8000"]} -dpath = "^2.1.6" -google-cloud-iam = "^2.14.3" -google-cloud-logging = "^3.9.0" -google-cloud-secret-manager = "^2.18.3" -inquirer = "^3.4" -jinja2 = "^3.1.3" -pandas-gbq = "^0.22.0" -python-dotenv = "^1.0.1" -requests = "^2.31.0" -sqlalchemy = "^2.0.28" -tqdm = "^4.66.2" - -[package.source] -type = "git" -url = "ssh://git@github.com/airbytehq/airbyte-platform-internal" -reference = "HEAD" -resolved_reference = "d71a5ae1f1621628f49d88832d7496949b89e1c7" -subdirectory = "tools/connection-retriever" - -[[package]] -name = "cryptography" -version = "42.0.8" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"}, - {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"}, - {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"}, - {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"}, - {file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"}, - {file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"}, - {file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"}, - {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"}, - {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"}, - {file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"}, - {file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"}, - {file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"}, - {file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"}, - {file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"}, -] - -[package.dependencies] -cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] -docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] -nox = ["nox"] -pep8test = ["check-sdist", "click", "mypy", "ruff"] -sdist = ["build"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] -test-randomorder = ["pytest-randomly"] - -[[package]] -name = "dagger-io" -version = "0.13.3" -description = "A client package for running Dagger pipelines in Python." -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "dagger_io-0.13.3-py3-none-any.whl", hash = "sha256:c3be14bd2c77ad265f944612123ef6f7653cf0365ffee0c70bf2a2662dc9783d"}, - {file = "dagger_io-0.13.3.tar.gz", hash = "sha256:fb9f602b8493f6e5f66afba4c6f51485dccb7c4795fbde7d92e188c69e8961b7"}, -] - -[package.dependencies] -anyio = ">=3.6.2" -beartype = ">=0.18.2" -cattrs = ">=22.2.0" -gql = {version = ">=3.5.0", extras = ["httpx"]} -opentelemetry-exporter-otlp-proto-grpc = ">=1.23.0" -opentelemetry-sdk = ">=1.23.0" -platformdirs = ">=2.6.2" -rich = ">=10.11.0" -typing-extensions = ">=4.8.0" - -[[package]] -name = "db-dtypes" -version = "1.3.0" -description = "Pandas Data Types for SQL systems (BigQuery, Spanner)" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "db_dtypes-1.3.0-py2.py3-none-any.whl", hash = "sha256:7e65c59f849ccbe6f7bc4d0253edcc212a7907662906921caba3e4aadd0bc277"}, - {file = "db_dtypes-1.3.0.tar.gz", hash = "sha256:7bcbc8858b07474dc85b77bb2f3ae488978d1336f5ea73b58c39d9118bc3e91b"}, -] - -[package.dependencies] -numpy = ">=1.16.6" -packaging = ">=17.0" -pandas = ">=0.24.2" -pyarrow = ">=3.0.0" - -[[package]] -name = "decorator" -version = "5.1.1" -description = "Decorators for Humans" -optional = false -python-versions = ">=3.5" -groups = ["main"] -files = [ - {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, - {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, -] - -[[package]] -name = "deepdiff" -version = "6.7.1" -description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "deepdiff-6.7.1-py3-none-any.whl", hash = "sha256:58396bb7a863cbb4ed5193f548c56f18218060362311aa1dc36397b2f25108bd"}, - {file = "deepdiff-6.7.1.tar.gz", hash = "sha256:b367e6fa6caac1c9f500adc79ada1b5b1242c50d5f716a1a4362030197847d30"}, -] - -[package.dependencies] -ordered-set = ">=4.0.2,<4.2.0" - -[package.extras] -cli = ["click (==8.1.3)", "pyyaml (==6.0.1)"] -optimize = ["orjson"] - -[[package]] -name = "deprecated" -version = "1.2.14" -description = "Python @deprecated decorator to deprecate old python classes, functions or methods." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] -files = [ - {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, - {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, -] - -[package.dependencies] -wrapt = ">=1.10,<2" - -[package.extras] -dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] - -[[package]] -name = "distro" -version = "1.9.0" -description = "Distro - an OS platform information API" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, - {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, -] - -[[package]] -name = "docker" -version = "6.1.3" -description = "A Python library for the Docker Engine API." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "docker-6.1.3-py3-none-any.whl", hash = "sha256:aecd2277b8bf8e506e484f6ab7aec39abe0038e29fa4a6d3ba86c3fe01844ed9"}, - {file = "docker-6.1.3.tar.gz", hash = "sha256:aa6d17830045ba5ef0168d5eaa34d37beeb113948c413affe1d5991fc11f9a20"}, -] - -[package.dependencies] -packaging = ">=14.0" -pywin32 = {version = ">=304", markers = "sys_platform == \"win32\""} -requests = ">=2.26.0" -urllib3 = ">=1.26.0" -websocket-client = ">=0.32.0" - -[package.extras] -ssh = ["paramiko (>=2.4.3)"] - -[[package]] -name = "dpath" -version = "2.2.0" -description = "Filesystem-like pathing and searching for dictionaries" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "dpath-2.2.0-py3-none-any.whl", hash = "sha256:b330a375ded0a0d2ed404440f6c6a715deae5313af40bbb01c8a41d891900576"}, - {file = "dpath-2.2.0.tar.gz", hash = "sha256:34f7e630dc55ea3f219e555726f5da4b4b25f2200319c8e6902c394258dd6a3e"}, -] - -[[package]] -name = "duckdb" -version = "0.10.1" -description = "DuckDB in-process database" -optional = false -python-versions = ">=3.7.0" -groups = ["main"] -files = [ - {file = "duckdb-0.10.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0ac172788e3d8e410e009e3699016a4d7f17b4c7cde20f98856fca1fea79d247"}, - {file = "duckdb-0.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f754c20d3b963574da58b0d22029681b79c63f2e32060f10b687f41b7bba54d7"}, - {file = "duckdb-0.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6c68b1ef88b8cce185381ec69f437d20059c30623375bab41ac07a1104acdb57"}, - {file = "duckdb-0.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f566f615278844ea240c9a3497c0ef201331628f78e0f9f4d64f72f82210e750"}, - {file = "duckdb-0.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67d2996c3372a0f7d8f41f1c49e00ecdb26f83cdd9132b76730224ad68b1f1e3"}, - {file = "duckdb-0.10.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5c3b3a18a58eebabb426beafc2f7da01d59805d660fc909e5e143b6db04d881a"}, - {file = "duckdb-0.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:343795d13ec3d8cd06c250225a05fd3c348c3ed49cccdde01addd46cb50f3559"}, - {file = "duckdb-0.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:33f99c2e9e4060464673912312b4ec91060d66638756592c9484c62824ff4e85"}, - {file = "duckdb-0.10.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fdbe4173729043b2fd949be83135b035820bb2faf64648500563b16f3f6f02ee"}, - {file = "duckdb-0.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f90738310a76bd1618acbc7345175582d36b6907cb0ed07841a3d800dea189d6"}, - {file = "duckdb-0.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d14d00560832592cbac2817847b649bd1d573f125d064518afb6eec5b02e15a"}, - {file = "duckdb-0.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11c0bf253c96079c6139e8a0880300d80f4dc9f21a8c5c239d2ebc060b227d46"}, - {file = "duckdb-0.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcc60833bb1a1fb2c33b052cf793fef48f681c565d982acff6ac7a86369794da"}, - {file = "duckdb-0.10.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:88cdc0c2501dd7a65b1df2a76d7624b93d9b6d27febd2ee80b7e5643a0b40bcb"}, - {file = "duckdb-0.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:698a8d1d48b150d344d8aa6dbc30a22ea30fb14ff2b15c90004fc9fcb0b3a3e9"}, - {file = "duckdb-0.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:b450aa2b3e0eb1fc0f7ad276bd1e4a5a03b1a4def6c45366af17557de2cafbdf"}, - {file = "duckdb-0.10.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:40dd55ea9c31abc69e5a8299f16c877e0b1950fd9a311c117efb4dd3c0dc8458"}, - {file = "duckdb-0.10.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7c1b3538bb9c2b49f48b26f092444525b22186efa4e77ba070603ed4a348a66"}, - {file = "duckdb-0.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bce024b69bae426b0739c470803f7b44261bdc0c0700ea7c41dff5f2d70ca4f3"}, - {file = "duckdb-0.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52af2a078340b2e1b57958477ebc1be07786d3ad5796777e87d4f453e0477b4c"}, - {file = "duckdb-0.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3c52b08c773e52484542300339ebf295e3c9b12d5d7d49b2567e252c16205a7"}, - {file = "duckdb-0.10.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:097aa9b6d5c9f5d3ed8c35b16020a67731d04befc35f6b89ccb5db9d5f1489c4"}, - {file = "duckdb-0.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b5a14a80ad09d65c270d16761b04ea6b074811cdfde6b5e4db1a8b0184125d1b"}, - {file = "duckdb-0.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fb98dbbdbf8048b07223dc6e7401333bb4e83681dde4cded2d239051ea102b5"}, - {file = "duckdb-0.10.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:28857b0d595c229827cc3631ae9b74ff52d11614435aa715e09d8629d2e1b609"}, - {file = "duckdb-0.10.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d85645136fc25026978b5db81869e8a120cfb60e1645a29a0f6dd155be9e59e"}, - {file = "duckdb-0.10.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e2e10582db74b99051e718279c1be204c98a63a5b6aa4e09226b7249e414146"}, - {file = "duckdb-0.10.1-cp37-cp37m-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d6a88358d86a8ce689fdd4136514aebedf958e910361156a0bb0e53dc3c55f7d"}, - {file = "duckdb-0.10.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b025afa30fcdcede094386e7c519e6964d26de5ad95f4e04a2a0a713676d4465"}, - {file = "duckdb-0.10.1-cp37-cp37m-win_amd64.whl", hash = "sha256:910be5005de7427c5231a7200027e0adb951e048c612b895340effcd3e660d5a"}, - {file = "duckdb-0.10.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:13d81752763f14203a53981f32bd09731900eb6fda4048fbc532eae5e7bf30e5"}, - {file = "duckdb-0.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:21858225b8a5c5dead128f62e4e88facdcbfdce098e18cbcd86a6cd8f48fb2b3"}, - {file = "duckdb-0.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8bf46d55685906729998eca70ee751934e0425d86863148e658277526c54282e"}, - {file = "duckdb-0.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f786b4402b9c31461ea0520d919e2166df4f9e6e21fd3c7bb0035fa985b5dfe"}, - {file = "duckdb-0.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32e52c6e939a4bada220803e6bde6fc0ce870da5662a33cabdd3be14824183a6"}, - {file = "duckdb-0.10.1-cp38-cp38-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5c563b565ea68cfebe9c4078646503b3d38930218f9c3c278277d58952873771"}, - {file = "duckdb-0.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:af8382280f24273a535e08b80e9383ad739c66e22855ce68716dfbaeaf8910b9"}, - {file = "duckdb-0.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:2e6e01e2499e07873b09316bf4d6808f712c57034fa24c255565c4f92386e8e3"}, - {file = "duckdb-0.10.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7791a0aa2cea972a612d31d4a289c81c5d00181328ed4f7642907f68f8b1fb9f"}, - {file = "duckdb-0.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1ace20383fb0ba06229e060a6bb0bcfd48a4582a02e43f05991720504508eb59"}, - {file = "duckdb-0.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5aad3e085c33253c689205b5ea3c5d9d54117c1249276c90d495cb85d9adce76"}, - {file = "duckdb-0.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa08173f68e678793dfe6aab6490ac753204ca7935beb8dbde778dbe593552d8"}, - {file = "duckdb-0.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:525efad4e6caff80d0f6a51d466470839146e3880da36d4544fee7ff842e7e20"}, - {file = "duckdb-0.10.1-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48d84577216010ee407913bad9dc47af4cbc65e479c91e130f7bd909a32caefe"}, - {file = "duckdb-0.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6e65f00294c3b8576ae651e91e732ea1cefc4aada89c307fb02f49231fd11e1f"}, - {file = "duckdb-0.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:30aa9dbbfc1f9607249fc148af9e6d6fd253fdc2f4c9924d4957d6a535558b4f"}, - {file = "duckdb-0.10.1.tar.gz", hash = "sha256:0d5b6daa9bb54a635e371798994caa08f26d2f145ebcbc989e16b0a0104e84fb"}, -] - -[[package]] -name = "editor" -version = "1.6.6" -description = "🖋 Open the default text editor 🖋" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "editor-1.6.6-py3-none-any.whl", hash = "sha256:e818e6913f26c2a81eadef503a2741d7cca7f235d20e217274a009ecd5a74abf"}, - {file = "editor-1.6.6.tar.gz", hash = "sha256:bb6989e872638cd119db9a4fce284cd8e13c553886a1c044c6b8d8a160c871f8"}, -] - -[package.dependencies] -runs = "*" -xmod = "*" - -[[package]] -name = "flask" -version = "3.0.3" -description = "A simple framework for building complex web applications." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "flask-3.0.3-py3-none-any.whl", hash = "sha256:34e815dfaa43340d1d15a5c3a02b8476004037eb4840b34910c6e21679d288f3"}, - {file = "flask-3.0.3.tar.gz", hash = "sha256:ceb27b0af3823ea2737928a4d99d125a06175b8512c445cbd9a9ce200ef76842"}, -] - -[package.dependencies] -blinker = ">=1.6.2" -click = ">=8.1.3" -itsdangerous = ">=2.1.2" -Jinja2 = ">=3.1.2" -Werkzeug = ">=3.0.0" - -[package.extras] -async = ["asgiref (>=3.2)"] -dotenv = ["python-dotenv"] - -[[package]] -name = "frozenlist" -version = "1.4.1" -description = "A list-like structure which implements collections.abc.MutableSequence" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, - {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, - {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, - {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, - {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, - {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, - {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, - {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, - {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, - {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, - {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, - {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, - {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, -] - -[[package]] -name = "genson" -version = "1.3.0" -description = "GenSON is a powerful, user-friendly JSON Schema generator." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "genson-1.3.0-py3-none-any.whl", hash = "sha256:468feccd00274cc7e4c09e84b08704270ba8d95232aa280f65b986139cec67f7"}, - {file = "genson-1.3.0.tar.gz", hash = "sha256:e02db9ac2e3fd29e65b5286f7135762e2cd8a986537c075b06fc5f1517308e37"}, -] - -[[package]] -name = "google-api-core" -version = "2.20.0" -description = "Google API client core library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google_api_core-2.20.0-py3-none-any.whl", hash = "sha256:ef0591ef03c30bb83f79b3d0575c3f31219001fc9c5cf37024d08310aeffed8a"}, - {file = "google_api_core-2.20.0.tar.gz", hash = "sha256:f74dff1889ba291a4b76c5079df0711810e2d9da81abfdc99957bc961c1eb28f"}, -] - -[package.dependencies] -google-auth = ">=2.14.1,<3.0.dev0" -googleapis-common-protos = ">=1.56.2,<2.0.dev0" -grpcio = {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""} -grpcio-status = {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""} -proto-plus = ">=1.22.3,<2.0.0dev" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" -requests = ">=2.18.0,<3.0.0.dev0" - -[package.extras] -grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status (>=1.33.2,<2.0.dev0)", "grpcio-status (>=1.49.1,<2.0.dev0)"] -grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] -grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] - -[[package]] -name = "google-auth" -version = "2.35.0" -description = "Google Authentication Library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google_auth-2.35.0-py2.py3-none-any.whl", hash = "sha256:25df55f327ef021de8be50bad0dfd4a916ad0de96da86cd05661c9297723ad3f"}, - {file = "google_auth-2.35.0.tar.gz", hash = "sha256:f4c64ed4e01e8e8b646ef34c018f8bf3338df0c8e37d8b3bba40e7f574a3278a"}, -] - -[package.dependencies] -cachetools = ">=2.0.0,<6.0" -pyasn1-modules = ">=0.2.1" -rsa = ">=3.1.4,<5" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] -enterprise-cert = ["cryptography", "pyopenssl"] -pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] -reauth = ["pyu2f (>=0.1.5)"] -requests = ["requests (>=2.20.0,<3.0.0.dev0)"] - -[[package]] -name = "google-auth-oauthlib" -version = "1.2.1" -description = "Google Authentication Library" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "google_auth_oauthlib-1.2.1-py2.py3-none-any.whl", hash = "sha256:2d58a27262d55aa1b87678c3ba7142a080098cbc2024f903c62355deb235d91f"}, - {file = "google_auth_oauthlib-1.2.1.tar.gz", hash = "sha256:afd0cad092a2eaa53cd8e8298557d6de1034c6cb4a740500b5357b648af97263"}, -] - -[package.dependencies] -google-auth = ">=2.15.0" -requests-oauthlib = ">=0.7.0" - -[package.extras] -tool = ["click (>=6.0.0)"] - -[[package]] -name = "google-cloud-appengine-logging" -version = "1.4.5" -description = "Google Cloud Appengine Logging API client library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google_cloud_appengine_logging-1.4.5-py2.py3-none-any.whl", hash = "sha256:344e0244404049b42164e4d6dc718ca2c81b393d066956e7cb85fd9407ed9c48"}, - {file = "google_cloud_appengine_logging-1.4.5.tar.gz", hash = "sha256:de7d766e5d67b19fc5833974b505b32d2a5bbdfb283fd941e320e7cfdae4cb83"}, -] - -[package.dependencies] -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} -google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" -proto-plus = ">=1.22.3,<2.0.0dev" -protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0dev" - -[[package]] -name = "google-cloud-audit-log" -version = "0.3.0" -description = "Google Cloud Audit Protos" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google_cloud_audit_log-0.3.0-py2.py3-none-any.whl", hash = "sha256:8340793120a1d5aa143605def8704ecdcead15106f754ef1381ae3bab533722f"}, - {file = "google_cloud_audit_log-0.3.0.tar.gz", hash = "sha256:901428b257020d8c1d1133e0fa004164a555e5a395c7ca3cdbb8486513df3a65"}, -] - -[package.dependencies] -googleapis-common-protos = ">=1.56.2,<2.0dev" -protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0dev" - -[[package]] -name = "google-cloud-bigquery" -version = "3.26.0" -description = "Google BigQuery API client library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google_cloud_bigquery-3.26.0-py2.py3-none-any.whl", hash = "sha256:e0e9ad28afa67a18696e624cbccab284bf2c0a3f6eeb9eeb0426c69b943793a8"}, - {file = "google_cloud_bigquery-3.26.0.tar.gz", hash = "sha256:edbdc788beea659e04c0af7fe4dcd6d9155344b98951a0d5055bd2f15da4ba23"}, -] - -[package.dependencies] -google-api-core = {version = ">=2.11.1,<3.0.0dev", extras = ["grpc"]} -google-auth = ">=2.14.1,<3.0.0dev" -google-cloud-core = ">=2.4.1,<3.0.0dev" -google-resumable-media = ">=2.0.0,<3.0dev" -packaging = ">=20.0.0" -python-dateutil = ">=2.7.3,<3.0dev" -requests = ">=2.21.0,<3.0.0dev" - -[package.extras] -all = ["Shapely (>=1.8.4,<3.0.0dev)", "bigquery-magics (>=0.1.0)", "db-dtypes (>=0.3.0,<2.0.0dev)", "geopandas (>=0.9.0,<1.0dev)", "google-cloud-bigquery-storage (>=2.6.0,<3.0.0dev)", "grpcio (>=1.47.0,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "importlib-metadata (>=1.0.0)", "ipykernel (>=6.0.0)", "ipywidgets (>=7.7.0)", "opentelemetry-api (>=1.1.0)", "opentelemetry-instrumentation (>=0.20b0)", "opentelemetry-sdk (>=1.1.0)", "pandas (>=1.1.0)", "proto-plus (>=1.22.3,<2.0.0dev)", "protobuf (>=3.20.2,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0dev)", "pyarrow (>=3.0.0)", "tqdm (>=4.7.4,<5.0.0dev)"] -bigquery-v2 = ["proto-plus (>=1.22.3,<2.0.0dev)", "protobuf (>=3.20.2,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0dev)"] -bqstorage = ["google-cloud-bigquery-storage (>=2.6.0,<3.0.0dev)", "grpcio (>=1.47.0,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "pyarrow (>=3.0.0)"] -geopandas = ["Shapely (>=1.8.4,<3.0.0dev)", "geopandas (>=0.9.0,<1.0dev)"] -ipython = ["bigquery-magics (>=0.1.0)"] -ipywidgets = ["ipykernel (>=6.0.0)", "ipywidgets (>=7.7.0)"] -opentelemetry = ["opentelemetry-api (>=1.1.0)", "opentelemetry-instrumentation (>=0.20b0)", "opentelemetry-sdk (>=1.1.0)"] -pandas = ["db-dtypes (>=0.3.0,<2.0.0dev)", "importlib-metadata (>=1.0.0)", "pandas (>=1.1.0)", "pyarrow (>=3.0.0)"] -tqdm = ["tqdm (>=4.7.4,<5.0.0dev)"] - -[[package]] -name = "google-cloud-core" -version = "2.4.1" -description = "Google Cloud API client core library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google-cloud-core-2.4.1.tar.gz", hash = "sha256:9b7749272a812bde58fff28868d0c5e2f585b82f37e09a1f6ed2d4d10f134073"}, - {file = "google_cloud_core-2.4.1-py2.py3-none-any.whl", hash = "sha256:a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61"}, -] - -[package.dependencies] -google-api-core = ">=1.31.6,<2.0.dev0 || >2.3.0,<3.0.0dev" -google-auth = ">=1.25.0,<3.0dev" - -[package.extras] -grpc = ["grpcio (>=1.38.0,<2.0dev)", "grpcio-status (>=1.38.0,<2.0.dev0)"] - -[[package]] -name = "google-cloud-iam" -version = "2.15.2" -description = "Google Cloud Iam API client library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google_cloud_iam-2.15.2-py2.py3-none-any.whl", hash = "sha256:e1b00c63fa932b9f144527915d88e9c94eb4f748795721afb09f97200b49947e"}, - {file = "google_cloud_iam-2.15.2.tar.gz", hash = "sha256:09b135d96ba2cf6f80a7ed8011436e89d2588e8bb23cd6145c476302f4871a82"}, -] - -[package.dependencies] -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} -google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" -grpc-google-iam-v1 = ">=0.12.4,<1.0.0dev" -proto-plus = ">=1.22.3,<2.0.0dev" -protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0dev" - -[[package]] -name = "google-cloud-logging" -version = "3.11.2" -description = "Stackdriver Logging API client library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google_cloud_logging-3.11.2-py2.py3-none-any.whl", hash = "sha256:0a755f04f184fbe77ad608258dc283a032485ebb4d0e2b2501964059ee9c898f"}, - {file = "google_cloud_logging-3.11.2.tar.gz", hash = "sha256:4897441c2b74f6eda9181c23a8817223b6145943314a821d64b729d30766cb2b"}, -] - -[package.dependencies] -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} -google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" -google-cloud-appengine-logging = ">=0.1.3,<2.0.0dev" -google-cloud-audit-log = ">=0.2.4,<1.0.0dev" -google-cloud-core = ">=2.0.0,<3.0.0dev" -grpc-google-iam-v1 = ">=0.12.4,<1.0.0dev" -opentelemetry-api = ">=1.9.0" -proto-plus = {version = ">=1.22.2,<2.0.0dev", markers = "python_version >= \"3.11\""} -protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0dev" - -[[package]] -name = "google-cloud-secret-manager" -version = "2.20.2" -description = "Google Cloud Secret Manager API client library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google_cloud_secret_manager-2.20.2-py2.py3-none-any.whl", hash = "sha256:99b342ff722feef78aa5bad1c05c6be204f8fee01373a2eb6f05dba710b32879"}, - {file = "google_cloud_secret_manager-2.20.2.tar.gz", hash = "sha256:bbe24825e334f9e679e825e70d932118a7ff536e67c1ceb048da44111c87a45c"}, -] - -[package.dependencies] -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} -google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" -grpc-google-iam-v1 = ">=0.12.4,<1.0.0dev" -proto-plus = ">=1.22.3,<2.0.0dev" -protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0dev" - -[[package]] -name = "google-crc32c" -version = "1.6.0" -description = "A python wrapper of the C library 'Google CRC32C'" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "google_crc32c-1.6.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:5bcc90b34df28a4b38653c36bb5ada35671ad105c99cfe915fb5bed7ad6924aa"}, - {file = "google_crc32c-1.6.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:d9e9913f7bd69e093b81da4535ce27af842e7bf371cde42d1ae9e9bd382dc0e9"}, - {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a184243544811e4a50d345838a883733461e67578959ac59964e43cca2c791e7"}, - {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:236c87a46cdf06384f614e9092b82c05f81bd34b80248021f729396a78e55d7e"}, - {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebab974b1687509e5c973b5c4b8b146683e101e102e17a86bd196ecaa4d099fc"}, - {file = "google_crc32c-1.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:50cf2a96da226dcbff8671233ecf37bf6e95de98b2a2ebadbfdf455e6d05df42"}, - {file = "google_crc32c-1.6.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:f7a1fc29803712f80879b0806cb83ab24ce62fc8daf0569f2204a0cfd7f68ed4"}, - {file = "google_crc32c-1.6.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:40b05ab32a5067525670880eb5d169529089a26fe35dce8891127aeddc1950e8"}, - {file = "google_crc32c-1.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e4b426c3702f3cd23b933436487eb34e01e00327fac20c9aebb68ccf34117d"}, - {file = "google_crc32c-1.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51c4f54dd8c6dfeb58d1df5e4f7f97df8abf17a36626a217f169893d1d7f3e9f"}, - {file = "google_crc32c-1.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:bb8b3c75bd157010459b15222c3fd30577042a7060e29d42dabce449c087f2b3"}, - {file = "google_crc32c-1.6.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:ed767bf4ba90104c1216b68111613f0d5926fb3780660ea1198fc469af410e9d"}, - {file = "google_crc32c-1.6.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:62f6d4a29fea082ac4a3c9be5e415218255cf11684ac6ef5488eea0c9132689b"}, - {file = "google_crc32c-1.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c87d98c7c4a69066fd31701c4e10d178a648c2cac3452e62c6b24dc51f9fcc00"}, - {file = "google_crc32c-1.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd5e7d2445d1a958c266bfa5d04c39932dc54093fa391736dbfdb0f1929c1fb3"}, - {file = "google_crc32c-1.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:7aec8e88a3583515f9e0957fe4f5f6d8d4997e36d0f61624e70469771584c760"}, - {file = "google_crc32c-1.6.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:e2806553238cd076f0a55bddab37a532b53580e699ed8e5606d0de1f856b5205"}, - {file = "google_crc32c-1.6.0-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:bb0966e1c50d0ef5bc743312cc730b533491d60585a9a08f897274e57c3f70e0"}, - {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:386122eeaaa76951a8196310432c5b0ef3b53590ef4c317ec7588ec554fec5d2"}, - {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2952396dc604544ea7476b33fe87faedc24d666fb0c2d5ac971a2b9576ab871"}, - {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35834855408429cecf495cac67ccbab802de269e948e27478b1e47dfb6465e57"}, - {file = "google_crc32c-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:d8797406499f28b5ef791f339594b0b5fdedf54e203b5066675c406ba69d705c"}, - {file = "google_crc32c-1.6.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48abd62ca76a2cbe034542ed1b6aee851b6f28aaca4e6551b5599b6f3ef175cc"}, - {file = "google_crc32c-1.6.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18e311c64008f1f1379158158bb3f0c8d72635b9eb4f9545f8cf990c5668e59d"}, - {file = "google_crc32c-1.6.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05e2d8c9a2f853ff116db9706b4a27350587f341eda835f46db3c0a8c8ce2f24"}, - {file = "google_crc32c-1.6.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ca8145b060679ec9176e6de4f89b07363d6805bd4760631ef254905503598d"}, - {file = "google_crc32c-1.6.0.tar.gz", hash = "sha256:6eceb6ad197656a1ff49ebfbbfa870678c75be4344feb35ac1edf694309413dc"}, -] - -[package.extras] -testing = ["pytest"] - -[[package]] -name = "google-resumable-media" -version = "2.7.2" -description = "Utilities for Google Media Downloads and Resumable Uploads" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google_resumable_media-2.7.2-py2.py3-none-any.whl", hash = "sha256:3ce7551e9fe6d99e9a126101d2536612bb73486721951e9562fee0f90c6ababa"}, - {file = "google_resumable_media-2.7.2.tar.gz", hash = "sha256:5280aed4629f2b60b847b0d42f9857fd4935c11af266744df33d8074cae92fe0"}, -] - -[package.dependencies] -google-crc32c = ">=1.0,<2.0dev" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)", "google-auth (>=1.22.0,<2.0dev)"] -requests = ["requests (>=2.18.0,<3.0.0dev)"] - -[[package]] -name = "googleapis-common-protos" -version = "1.65.0" -description = "Common protobufs used in Google APIs" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "googleapis_common_protos-1.65.0-py2.py3-none-any.whl", hash = "sha256:2972e6c496f435b92590fd54045060867f3fe9be2c82ab148fc8885035479a63"}, - {file = "googleapis_common_protos-1.65.0.tar.gz", hash = "sha256:334a29d07cddc3aa01dee4988f9afd9b2916ee2ff49d6b757155dc0d197852c0"}, -] - -[package.dependencies] -grpcio = {version = ">=1.44.0,<2.0.0.dev0", optional = true, markers = "extra == \"grpc\""} -protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" - -[package.extras] -grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] - -[[package]] -name = "gql" -version = "3.5.0" -description = "GraphQL client for Python" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "gql-3.5.0-py2.py3-none-any.whl", hash = "sha256:70dda5694a5b194a8441f077aa5fb70cc94e4ec08016117523f013680901ecb7"}, - {file = "gql-3.5.0.tar.gz", hash = "sha256:ccb9c5db543682b28f577069950488218ed65d4ac70bb03b6929aaadaf636de9"}, -] - -[package.dependencies] -anyio = ">=3.0,<5" -backoff = ">=1.11.1,<3.0" -graphql-core = ">=3.2,<3.3" -httpx = {version = ">=0.23.1,<1", optional = true, markers = "extra == \"httpx\""} -yarl = ">=1.6,<2.0" - -[package.extras] -aiohttp = ["aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)"] -all = ["aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "websockets (>=10,<12)"] -botocore = ["botocore (>=1.21,<2)"] -dev = ["aiofiles", "aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)", "black (==22.3.0)", "botocore (>=1.21,<2)", "check-manifest (>=0.42,<1)", "flake8 (==3.8.1)", "httpx (>=0.23.1,<1)", "isort (==4.3.21)", "mock (==4.0.2)", "mypy (==0.910)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "sphinx (>=5.3.0,<6)", "sphinx-argparse (==0.2.5)", "sphinx-rtd-theme (>=0.4,<1)", "types-aiofiles", "types-mock", "types-requests", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] -httpx = ["httpx (>=0.23.1,<1)"] -requests = ["requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)"] -test = ["aiofiles", "aiohttp (>=3.8.0,<4)", "aiohttp (>=3.9.0b0,<4)", "botocore (>=1.21,<2)", "httpx (>=0.23.1,<1)", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=1.0.0,<2)", "vcrpy (==4.4.0)", "websockets (>=10,<12)"] -test-no-transport = ["aiofiles", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==7.4.2)", "pytest-asyncio (==0.21.1)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "vcrpy (==4.4.0)"] -websockets = ["websockets (>=10,<12)"] - -[[package]] -name = "graphql-core" -version = "3.2.4" -description = "GraphQL implementation for Python, a port of GraphQL.js, the JavaScript reference implementation for GraphQL." -optional = false -python-versions = "<4,>=3.6" -groups = ["main"] -files = [ - {file = "graphql-core-3.2.4.tar.gz", hash = "sha256:acbe2e800980d0e39b4685dd058c2f4042660b89ebca38af83020fd872ff1264"}, - {file = "graphql_core-3.2.4-py3-none-any.whl", hash = "sha256:1604f2042edc5f3114f49cac9d77e25863be51b23a54a61a23245cf32f6476f0"}, -] - -[[package]] -name = "greenlet" -version = "3.1.1" -description = "Lightweight in-process concurrent programming" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\"" -files = [ - {file = "greenlet-3.1.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617"}, - {file = "greenlet-3.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7"}, - {file = "greenlet-3.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6"}, - {file = "greenlet-3.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80"}, - {file = "greenlet-3.1.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a"}, - {file = "greenlet-3.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511"}, - {file = "greenlet-3.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395"}, - {file = "greenlet-3.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39"}, - {file = "greenlet-3.1.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9"}, - {file = "greenlet-3.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0"}, - {file = "greenlet-3.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942"}, - {file = "greenlet-3.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01"}, - {file = "greenlet-3.1.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e"}, - {file = "greenlet-3.1.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1"}, - {file = "greenlet-3.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c"}, - {file = "greenlet-3.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822"}, - {file = "greenlet-3.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01"}, - {file = "greenlet-3.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47da355d8687fd65240c364c90a31569a133b7b60de111c255ef5b606f2ae291"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98884ecf2ffb7d7fe6bd517e8eb99d31ff7855a840fa6d0d63cd07c037f6a981"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1d4aeb8891338e60d1ab6127af1fe45def5259def8094b9c7e34690c8858803"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db32b5348615a04b82240cc67983cb315309e88d444a288934ee6ceaebcad6cc"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dcc62f31eae24de7f8dce72134c8651c58000d3b1868e01392baea7c32c247de"}, - {file = "greenlet-3.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1d3755bcb2e02de341c55b4fca7a745a24a9e7212ac953f6b3a48d117d7257aa"}, - {file = "greenlet-3.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b8da394b34370874b4572676f36acabac172602abf054cbc4ac910219f3340af"}, - {file = "greenlet-3.1.1-cp37-cp37m-win32.whl", hash = "sha256:a0dfc6c143b519113354e780a50381508139b07d2177cb6ad6a08278ec655798"}, - {file = "greenlet-3.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:54558ea205654b50c438029505def3834e80f0869a70fb15b871c29b4575ddef"}, - {file = "greenlet-3.1.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:346bed03fe47414091be4ad44786d1bd8bef0c3fcad6ed3dee074a032ab408a9"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfc59d69fc48664bc693842bd57acfdd490acafda1ab52c7836e3fc75c90a111"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21e10da6ec19b457b82636209cbe2331ff4306b54d06fa04b7c138ba18c8a81"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:37b9de5a96111fc15418819ab4c4432e4f3c2ede61e660b1e33971eba26ef9ba"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ef9ea3f137e5711f0dbe5f9263e8c009b7069d8a1acea822bd5e9dae0ae49c8"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85f3ff71e2e60bd4b4932a043fbbe0f499e263c628390b285cb599154a3b03b1"}, - {file = "greenlet-3.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:95ffcf719966dd7c453f908e208e14cde192e09fde6c7186c8f1896ef778d8cd"}, - {file = "greenlet-3.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7"}, - {file = "greenlet-3.1.1-cp38-cp38-win32.whl", hash = "sha256:8b8b36671f10ba80e159378df9c4f15c14098c4fd73a36b9ad715f057272fbef"}, - {file = "greenlet-3.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:7017b2be767b9d43cc31416aba48aab0d2309ee31b4dbf10a1d38fb7972bdf9d"}, - {file = "greenlet-3.1.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:396979749bd95f018296af156201d6211240e7a23090f50a8d5d18c370084dc3"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca9d0ff5ad43e785350894d97e13633a66e2b50000e8a183a50a88d834752d42"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94ebba31df2aa506d7b14866fed00ac141a867e63143fe5bca82a8e503b36437"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73aaad12ac0ff500f62cebed98d8789198ea0e6f233421059fa68a5aa7220145"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63e4844797b975b9af3a3fb8f7866ff08775f5426925e1e0bbcfe7932059a12c"}, - {file = "greenlet-3.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7939aa3ca7d2a1593596e7ac6d59391ff30281ef280d8632fa03d81f7c5f955e"}, - {file = "greenlet-3.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d0028e725ee18175c6e422797c407874da24381ce0690d6b9396c204c7f7276e"}, - {file = "greenlet-3.1.1-cp39-cp39-win32.whl", hash = "sha256:5e06afd14cbaf9e00899fae69b24a32f2196c19de08fcb9f4779dd4f004e5e7c"}, - {file = "greenlet-3.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22"}, - {file = "greenlet-3.1.1.tar.gz", hash = "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467"}, -] - -[package.extras] -docs = ["Sphinx", "furo"] -test = ["objgraph", "psutil"] - -[[package]] -name = "grpc-google-iam-v1" -version = "0.13.1" -description = "IAM API client library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "grpc-google-iam-v1-0.13.1.tar.gz", hash = "sha256:3ff4b2fd9d990965e410965253c0da6f66205d5a8291c4c31c6ebecca18a9001"}, - {file = "grpc_google_iam_v1-0.13.1-py2.py3-none-any.whl", hash = "sha256:c3e86151a981811f30d5e7330f271cee53e73bb87755e88cc3b6f0c7b5fe374e"}, -] - -[package.dependencies] -googleapis-common-protos = {version = ">=1.56.0,<2.0.0dev", extras = ["grpc"]} -grpcio = ">=1.44.0,<2.0.0dev" -protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0dev" - -[[package]] -name = "grpcio" -version = "1.66.2" -description = "HTTP/2-based RPC framework" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "grpcio-1.66.2-cp310-cp310-linux_armv7l.whl", hash = "sha256:fe96281713168a3270878255983d2cb1a97e034325c8c2c25169a69289d3ecfa"}, - {file = "grpcio-1.66.2-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:73fc8f8b9b5c4a03e802b3cd0c18b2b06b410d3c1dcbef989fdeb943bd44aff7"}, - {file = "grpcio-1.66.2-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:03b0b307ba26fae695e067b94cbb014e27390f8bc5ac7a3a39b7723fed085604"}, - {file = "grpcio-1.66.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d69ce1f324dc2d71e40c9261d3fdbe7d4c9d60f332069ff9b2a4d8a257c7b2b"}, - {file = "grpcio-1.66.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05bc2ceadc2529ab0b227b1310d249d95d9001cd106aa4d31e8871ad3c428d73"}, - {file = "grpcio-1.66.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8ac475e8da31484efa25abb774674d837b343afb78bb3bcdef10f81a93e3d6bf"}, - {file = "grpcio-1.66.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0be4e0490c28da5377283861bed2941d1d20ec017ca397a5df4394d1c31a9b50"}, - {file = "grpcio-1.66.2-cp310-cp310-win32.whl", hash = "sha256:4e504572433f4e72b12394977679161d495c4c9581ba34a88d843eaf0f2fbd39"}, - {file = "grpcio-1.66.2-cp310-cp310-win_amd64.whl", hash = "sha256:2018b053aa15782db2541ca01a7edb56a0bf18c77efed975392583725974b249"}, - {file = "grpcio-1.66.2-cp311-cp311-linux_armv7l.whl", hash = "sha256:2335c58560a9e92ac58ff2bc5649952f9b37d0735608242973c7a8b94a6437d8"}, - {file = "grpcio-1.66.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:45a3d462826f4868b442a6b8fdbe8b87b45eb4f5b5308168c156b21eca43f61c"}, - {file = "grpcio-1.66.2-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:a9539f01cb04950fd4b5ab458e64a15f84c2acc273670072abe49a3f29bbad54"}, - {file = "grpcio-1.66.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce89f5876662f146d4c1f695dda29d4433a5d01c8681fbd2539afff535da14d4"}, - {file = "grpcio-1.66.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d25a14af966438cddf498b2e338f88d1c9706f3493b1d73b93f695c99c5f0e2a"}, - {file = "grpcio-1.66.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6001e575b8bbd89eee11960bb640b6da6ae110cf08113a075f1e2051cc596cae"}, - {file = "grpcio-1.66.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4ea1d062c9230278793820146c95d038dc0f468cbdd172eec3363e42ff1c7d01"}, - {file = "grpcio-1.66.2-cp311-cp311-win32.whl", hash = "sha256:38b68498ff579a3b1ee8f93a05eb48dc2595795f2f62716e797dc24774c1aaa8"}, - {file = "grpcio-1.66.2-cp311-cp311-win_amd64.whl", hash = "sha256:6851de821249340bdb100df5eacfecfc4e6075fa85c6df7ee0eb213170ec8e5d"}, - {file = "grpcio-1.66.2-cp312-cp312-linux_armv7l.whl", hash = "sha256:802d84fd3d50614170649853d121baaaa305de7b65b3e01759247e768d691ddf"}, - {file = "grpcio-1.66.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:80fd702ba7e432994df208f27514280b4b5c6843e12a48759c9255679ad38db8"}, - {file = "grpcio-1.66.2-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:12fda97ffae55e6526825daf25ad0fa37483685952b5d0f910d6405c87e3adb6"}, - {file = "grpcio-1.66.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:950da58d7d80abd0ea68757769c9db0a95b31163e53e5bb60438d263f4bed7b7"}, - {file = "grpcio-1.66.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e636ce23273683b00410f1971d209bf3689238cf5538d960adc3cdfe80dd0dbd"}, - {file = "grpcio-1.66.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a917d26e0fe980b0ac7bfcc1a3c4ad6a9a4612c911d33efb55ed7833c749b0ee"}, - {file = "grpcio-1.66.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49f0ca7ae850f59f828a723a9064cadbed90f1ece179d375966546499b8a2c9c"}, - {file = "grpcio-1.66.2-cp312-cp312-win32.whl", hash = "sha256:31fd163105464797a72d901a06472860845ac157389e10f12631025b3e4d0453"}, - {file = "grpcio-1.66.2-cp312-cp312-win_amd64.whl", hash = "sha256:ff1f7882e56c40b0d33c4922c15dfa30612f05fb785074a012f7cda74d1c3679"}, - {file = "grpcio-1.66.2-cp313-cp313-linux_armv7l.whl", hash = "sha256:3b00efc473b20d8bf83e0e1ae661b98951ca56111feb9b9611df8efc4fe5d55d"}, - {file = "grpcio-1.66.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1caa38fb22a8578ab8393da99d4b8641e3a80abc8fd52646f1ecc92bcb8dee34"}, - {file = "grpcio-1.66.2-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:c408f5ef75cfffa113cacd8b0c0e3611cbfd47701ca3cdc090594109b9fcbaed"}, - {file = "grpcio-1.66.2-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c806852deaedee9ce8280fe98955c9103f62912a5b2d5ee7e3eaa284a6d8d8e7"}, - {file = "grpcio-1.66.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f145cc21836c332c67baa6fc81099d1d27e266401565bf481948010d6ea32d46"}, - {file = "grpcio-1.66.2-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:73e3b425c1e155730273f73e419de3074aa5c5e936771ee0e4af0814631fb30a"}, - {file = "grpcio-1.66.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:9c509a4f78114cbc5f0740eb3d7a74985fd2eff022971bc9bc31f8bc93e66a3b"}, - {file = "grpcio-1.66.2-cp313-cp313-win32.whl", hash = "sha256:20657d6b8cfed7db5e11b62ff7dfe2e12064ea78e93f1434d61888834bc86d75"}, - {file = "grpcio-1.66.2-cp313-cp313-win_amd64.whl", hash = "sha256:fb70487c95786e345af5e854ffec8cb8cc781bcc5df7930c4fbb7feaa72e1cdf"}, - {file = "grpcio-1.66.2-cp38-cp38-linux_armv7l.whl", hash = "sha256:a18e20d8321c6400185b4263e27982488cb5cdd62da69147087a76a24ef4e7e3"}, - {file = "grpcio-1.66.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:02697eb4a5cbe5a9639f57323b4c37bcb3ab2d48cec5da3dc2f13334d72790dd"}, - {file = "grpcio-1.66.2-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:99a641995a6bc4287a6315989ee591ff58507aa1cbe4c2e70d88411c4dcc0839"}, - {file = "grpcio-1.66.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ed71e81782966ffead60268bbda31ea3f725ebf8aa73634d5dda44f2cf3fb9c"}, - {file = "grpcio-1.66.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbd27c24a4cc5e195a7f56cfd9312e366d5d61b86e36d46bbe538457ea6eb8dd"}, - {file = "grpcio-1.66.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d9a9724a156c8ec6a379869b23ba3323b7ea3600851c91489b871e375f710bc8"}, - {file = "grpcio-1.66.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d8d4732cc5052e92cea2f78b233c2e2a52998ac40cd651f40e398893ad0d06ec"}, - {file = "grpcio-1.66.2-cp38-cp38-win32.whl", hash = "sha256:7b2c86457145ce14c38e5bf6bdc19ef88e66c5fee2c3d83285c5aef026ba93b3"}, - {file = "grpcio-1.66.2-cp38-cp38-win_amd64.whl", hash = "sha256:e88264caad6d8d00e7913996030bac8ad5f26b7411495848cc218bd3a9040b6c"}, - {file = "grpcio-1.66.2-cp39-cp39-linux_armv7l.whl", hash = "sha256:c400ba5675b67025c8a9f48aa846f12a39cf0c44df5cd060e23fda5b30e9359d"}, - {file = "grpcio-1.66.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:66a0cd8ba6512b401d7ed46bb03f4ee455839957f28b8d61e7708056a806ba6a"}, - {file = "grpcio-1.66.2-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:06de8ec0bd71be123eec15b0e0d457474931c2c407869b6c349bd9bed4adbac3"}, - {file = "grpcio-1.66.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb57870449dfcfac428afbb5a877829fcb0d6db9d9baa1148705739e9083880e"}, - {file = "grpcio-1.66.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b672abf90a964bfde2d0ecbce30f2329a47498ba75ce6f4da35a2f4532b7acbc"}, - {file = "grpcio-1.66.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ad2efdbe90c73b0434cbe64ed372e12414ad03c06262279b104a029d1889d13e"}, - {file = "grpcio-1.66.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9c3a99c519f4638e700e9e3f83952e27e2ea10873eecd7935823dab0c1c9250e"}, - {file = "grpcio-1.66.2-cp39-cp39-win32.whl", hash = "sha256:78fa51ebc2d9242c0fc5db0feecc57a9943303b46664ad89921f5079e2e4ada7"}, - {file = "grpcio-1.66.2-cp39-cp39-win_amd64.whl", hash = "sha256:728bdf36a186e7f51da73be7f8d09457a03061be848718d0edf000e709418987"}, - {file = "grpcio-1.66.2.tar.gz", hash = "sha256:563588c587b75c34b928bc428548e5b00ea38c46972181a4d8b75ba7e3f24231"}, -] - -[package.extras] -protobuf = ["grpcio-tools (>=1.66.2)"] - -[[package]] -name = "grpcio-status" -version = "1.62.3" -description = "Status proto mapping for gRPC" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "grpcio-status-1.62.3.tar.gz", hash = "sha256:289bdd7b2459794a12cf95dc0cb727bd4a1742c37bd823f760236c937e53a485"}, - {file = "grpcio_status-1.62.3-py3-none-any.whl", hash = "sha256:f9049b762ba8de6b1086789d8315846e094edac2c50beaf462338b301a8fd4b8"}, -] - -[package.dependencies] -googleapis-common-protos = ">=1.5.5" -grpcio = ">=1.62.3" -protobuf = ">=4.21.6" - -[[package]] -name = "h11" -version = "0.14.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, -] - -[[package]] -name = "h2" -version = "4.1.0" -description = "HTTP/2 State-Machine based protocol implementation" -optional = false -python-versions = ">=3.6.1" -groups = ["main"] -files = [ - {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"}, - {file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"}, -] - -[package.dependencies] -hpack = ">=4.0,<5" -hyperframe = ">=6.0,<7" - -[[package]] -name = "hpack" -version = "4.0.0" -description = "Pure-Python HPACK header compression" -optional = false -python-versions = ">=3.6.1" -groups = ["main"] -files = [ - {file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, - {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, -] - -[[package]] -name = "httpcore" -version = "1.0.6" -description = "A minimal low-level HTTP client." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "httpcore-1.0.6-py3-none-any.whl", hash = "sha256:27b59625743b85577a8c0e10e55b50b5368a4f2cfe8cc7bcfa9cf00829c2682f"}, - {file = "httpcore-1.0.6.tar.gz", hash = "sha256:73f6dbd6eb8c21bbf7ef8efad555481853f5f6acdeaff1edb0694289269ee17f"}, -] - -[package.dependencies] -certifi = "*" -h11 = ">=0.13,<0.15" - -[package.extras] -asyncio = ["anyio (>=4.0,<5.0)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<1.0)"] - -[[package]] -name = "httpx" -version = "0.27.2" -description = "The next generation HTTP client." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0"}, - {file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"}, -] - -[package.dependencies] -anyio = "*" -certifi = "*" -httpcore = "==1.*" -idna = "*" -sniffio = "*" - -[package.extras] -brotli = ["brotli", "brotlicffi"] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "hyperframe" -version = "6.0.1" -description = "HTTP/2 framing layer for Python" -optional = false -python-versions = ">=3.6.1" -groups = ["main"] -files = [ - {file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, - {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, -] - -[[package]] -name = "idna" -version = "3.10" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, - {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, -] - -[package.extras] -all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] - -[[package]] -name = "importlib-metadata" -version = "8.4.0" -description = "Read metadata from Python packages" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "importlib_metadata-8.4.0-py3-none-any.whl", hash = "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1"}, - {file = "importlib_metadata-8.4.0.tar.gz", hash = "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5"}, -] - -[package.dependencies] -zipp = ">=0.5" - -[package.extras] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -perf = ["ipython"] -test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - -[[package]] -name = "inquirer" -version = "3.4.0" -description = "Collection of common interactive command line user interfaces, based on Inquirer.js" -optional = false -python-versions = ">=3.8.1" -groups = ["main"] -files = [ - {file = "inquirer-3.4.0-py3-none-any.whl", hash = "sha256:bb0ec93c833e4ce7b51b98b1644b0a4d2bb39755c39787f6a504e4fee7a11b60"}, - {file = "inquirer-3.4.0.tar.gz", hash = "sha256:8edc99c076386ee2d2204e5e3653c2488244e82cb197b2d498b3c1b5ffb25d0b"}, -] - -[package.dependencies] -blessed = ">=1.19.0" -editor = ">=1.6.0" -readchar = ">=4.2.0" - -[[package]] -name = "itsdangerous" -version = "2.2.0" -description = "Safely pass data to untrusted environments and back." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef"}, - {file = "itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"}, -] - -[[package]] -name = "jinja2" -version = "3.1.4" -description = "A very fast and expressive template engine." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, - {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "jinxed" -version = "1.3.0" -description = "Jinxed Terminal Library" -optional = false -python-versions = "*" -groups = ["main"] -markers = "platform_system == \"Windows\"" -files = [ - {file = "jinxed-1.3.0-py2.py3-none-any.whl", hash = "sha256:b993189f39dc2d7504d802152671535b06d380b26d78070559551cbf92df4fc5"}, - {file = "jinxed-1.3.0.tar.gz", hash = "sha256:1593124b18a41b7a3da3b078471442e51dbad3d77b4d4f2b0c26ab6f7d660dbf"}, -] - -[package.dependencies] -ansicon = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "jiter" -version = "0.11.1" -description = "Fast iterable JSON parser." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "jiter-0.11.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:ed58841a491bbbf3f7c55a6b68fff568439ab73b2cce27ace0e169057b5851df"}, - {file = "jiter-0.11.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:499beb9b2d7e51d61095a8de39ebcab1d1778f2a74085f8305a969f6cee9f3e4"}, - {file = "jiter-0.11.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b87b2821795e28cc990939b68ce7a038edea680a24910bd68a79d54ff3f03c02"}, - {file = "jiter-0.11.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:83f6fa494d8bba14ab100417c80e70d32d737e805cb85be2052d771c76fcd1f8"}, - {file = "jiter-0.11.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5fbc6aea1daa2ec6f5ed465f0c5e7b0607175062ceebbea5ca70dd5ddab58083"}, - {file = "jiter-0.11.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:302288e2edc43174bb2db838e94688d724f9aad26c5fb9a74f7a5fb427452a6a"}, - {file = "jiter-0.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85db563fe3b367bb568af5d29dea4d4066d923b8e01f3417d25ebecd958de815"}, - {file = "jiter-0.11.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f1c1ba2b6b22f775444ef53bc2d5778396d3520abc7b2e1da8eb0c27cb3ffb10"}, - {file = "jiter-0.11.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:523be464b14f8fd0cc78da6964b87b5515a056427a2579f9085ce30197a1b54a"}, - {file = "jiter-0.11.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:25b99b3f04cd2a38fefb22e822e35eb203a2cd37d680dbbc0c0ba966918af336"}, - {file = "jiter-0.11.1-cp310-cp310-win32.whl", hash = "sha256:47a79e90545a596bb9104109777894033347b11180d4751a216afef14072dbe7"}, - {file = "jiter-0.11.1-cp310-cp310-win_amd64.whl", hash = "sha256:cace75621ae9bd66878bf69fbd4dfc1a28ef8661e0c2d0eb72d3d6f1268eddf5"}, - {file = "jiter-0.11.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:9b0088ff3c374ce8ce0168523ec8e97122ebb788f950cf7bb8e39c7dc6a876a2"}, - {file = "jiter-0.11.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:74433962dd3c3090655e02e461267095d6c84f0741c7827de11022ef8d7ff661"}, - {file = "jiter-0.11.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d98030e345e6546df2cc2c08309c502466c66c4747b043f1a0d415fada862b8"}, - {file = "jiter-0.11.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1d6db0b2e788db46bec2cf729a88b6dd36959af2abd9fa2312dfba5acdd96dcb"}, - {file = "jiter-0.11.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55678fbbda261eafe7289165dd2ddd0e922df5f9a1ae46d7c79a5a15242bd7d1"}, - {file = "jiter-0.11.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a6b74fae8e40497653b52ce6ca0f1b13457af769af6fb9c1113efc8b5b4d9be"}, - {file = "jiter-0.11.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a55a453f8b035eb4f7852a79a065d616b7971a17f5e37a9296b4b38d3b619e4"}, - {file = "jiter-0.11.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2638148099022e6bdb3f42904289cd2e403609356fb06eb36ddec2d50958bc29"}, - {file = "jiter-0.11.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:252490567a5d990986f83b95a5f1ca1bf205ebd27b3e9e93bb7c2592380e29b9"}, - {file = "jiter-0.11.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d431d52b0ca2436eea6195f0f48528202100c7deda354cb7aac0a302167594d5"}, - {file = "jiter-0.11.1-cp311-cp311-win32.whl", hash = "sha256:db6f41e40f8bae20c86cb574b48c4fd9f28ee1c71cb044e9ec12e78ab757ba3a"}, - {file = "jiter-0.11.1-cp311-cp311-win_amd64.whl", hash = "sha256:0cc407b8e6cdff01b06bb80f61225c8b090c3df108ebade5e0c3c10993735b19"}, - {file = "jiter-0.11.1-cp311-cp311-win_arm64.whl", hash = "sha256:fe04ea475392a91896d1936367854d346724a1045a247e5d1c196410473b8869"}, - {file = "jiter-0.11.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:c92148eec91052538ce6823dfca9525f5cfc8b622d7f07e9891a280f61b8c96c"}, - {file = "jiter-0.11.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ecd4da91b5415f183a6be8f7158d127bdd9e6a3174138293c0d48d6ea2f2009d"}, - {file = "jiter-0.11.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7e3ac25c00b9275684d47aa42febaa90a9958e19fd1726c4ecf755fbe5e553b"}, - {file = "jiter-0.11.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:57d7305c0a841858f866cd459cd9303f73883fb5e097257f3d4a3920722c69d4"}, - {file = "jiter-0.11.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e86fa10e117dce22c547f31dd6d2a9a222707d54853d8de4e9a2279d2c97f239"}, - {file = "jiter-0.11.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ae5ef1d48aec7e01ee8420155d901bb1d192998fa811a65ebb82c043ee186711"}, - {file = "jiter-0.11.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb68e7bf65c990531ad8715e57d50195daf7c8e6f1509e617b4e692af1108939"}, - {file = "jiter-0.11.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43b30c8154ded5845fa454ef954ee67bfccce629b2dea7d01f795b42bc2bda54"}, - {file = "jiter-0.11.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:586cafbd9dd1f3ce6a22b4a085eaa6be578e47ba9b18e198d4333e598a91db2d"}, - {file = "jiter-0.11.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:677cc2517d437a83bb30019fd4cf7cad74b465914c56ecac3440d597ac135250"}, - {file = "jiter-0.11.1-cp312-cp312-win32.whl", hash = "sha256:fa992af648fcee2b850a3286a35f62bbbaeddbb6dbda19a00d8fbc846a947b6e"}, - {file = "jiter-0.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:88b5cae9fa51efeb3d4bd4e52bfd4c85ccc9cac44282e2a9640893a042ba4d87"}, - {file = "jiter-0.11.1-cp312-cp312-win_arm64.whl", hash = "sha256:9a6cae1ab335551917f882f2c3c1efe7617b71b4c02381e4382a8fc80a02588c"}, - {file = "jiter-0.11.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:71b6a920a5550f057d49d0e8bcc60945a8da998019e83f01adf110e226267663"}, - {file = "jiter-0.11.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0b3de72e925388453a5171be83379549300db01284f04d2a6f244d1d8de36f94"}, - {file = "jiter-0.11.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc19dd65a2bd3d9c044c5b4ebf657ca1e6003a97c0fc10f555aa4f7fb9821c00"}, - {file = "jiter-0.11.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d58faaa936743cd1464540562f60b7ce4fd927e695e8bc31b3da5b914baa9abd"}, - {file = "jiter-0.11.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:902640c3103625317291cb73773413b4d71847cdf9383ba65528745ff89f1d14"}, - {file = "jiter-0.11.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:30405f726e4c2ed487b176c09f8b877a957f535d60c1bf194abb8dadedb5836f"}, - {file = "jiter-0.11.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3217f61728b0baadd2551844870f65219ac4a1285d5e1a4abddff3d51fdabe96"}, - {file = "jiter-0.11.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b1364cc90c03a8196f35f396f84029f12abe925415049204446db86598c8b72c"}, - {file = "jiter-0.11.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:53a54bf8e873820ab186b2dca9f6c3303f00d65ae5e7b7d6bda1b95aa472d646"}, - {file = "jiter-0.11.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:7e29aca023627b0e0c2392d4248f6414d566ff3974fa08ff2ac8dbb96dfee92a"}, - {file = "jiter-0.11.1-cp313-cp313-win32.whl", hash = "sha256:f153e31d8bca11363751e875c0a70b3d25160ecbaee7b51e457f14498fb39d8b"}, - {file = "jiter-0.11.1-cp313-cp313-win_amd64.whl", hash = "sha256:f773f84080b667c69c4ea0403fc67bb08b07e2b7ce1ef335dea5868451e60fed"}, - {file = "jiter-0.11.1-cp313-cp313-win_arm64.whl", hash = "sha256:635ecd45c04e4c340d2187bcb1cea204c7cc9d32c1364d251564bf42e0e39c2d"}, - {file = "jiter-0.11.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d892b184da4d94d94ddb4031296931c74ec8b325513a541ebfd6dfb9ae89904b"}, - {file = "jiter-0.11.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa22c223a3041dacb2fcd37c70dfd648b44662b4a48e242592f95bda5ab09d58"}, - {file = "jiter-0.11.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:330e8e6a11ad4980cd66a0f4a3e0e2e0f646c911ce047014f984841924729789"}, - {file = "jiter-0.11.1-cp313-cp313t-win_amd64.whl", hash = "sha256:09e2e386ebf298547ca3a3704b729471f7ec666c2906c5c26c1a915ea24741ec"}, - {file = "jiter-0.11.1-cp313-cp313t-win_arm64.whl", hash = "sha256:fe4a431c291157e11cee7c34627990ea75e8d153894365a3bc84b7a959d23ca8"}, - {file = "jiter-0.11.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:0fa1f70da7a8a9713ff8e5f75ec3f90c0c870be6d526aa95e7c906f6a1c8c676"}, - {file = "jiter-0.11.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:569ee559e5046a42feb6828c55307cf20fe43308e3ae0d8e9e4f8d8634d99944"}, - {file = "jiter-0.11.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f69955fa1d92e81987f092b233f0be49d4c937da107b7f7dcf56306f1d3fcce9"}, - {file = "jiter-0.11.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:090f4c9d4a825e0fcbd0a2647c9a88a0f366b75654d982d95a9590745ff0c48d"}, - {file = "jiter-0.11.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbf3d8cedf9e9d825233e0dcac28ff15c47b7c5512fdfe2e25fd5bbb6e6b0cee"}, - {file = "jiter-0.11.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2aa9b1958f9c30d3d1a558b75f0626733c60eb9b7774a86b34d88060be1e67fe"}, - {file = "jiter-0.11.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e42d1ca16590b768c5e7d723055acd2633908baacb3628dd430842e2e035aa90"}, - {file = "jiter-0.11.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5db4c2486a023820b701a17aec9c5a6173c5ba4393f26662f032f2de9c848b0f"}, - {file = "jiter-0.11.1-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:4573b78777ccfac954859a6eff45cbd9d281d80c8af049d0f1a3d9fc323d5c3a"}, - {file = "jiter-0.11.1-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:7593ac6f40831d7961cb67633c39b9fef6689a211d7919e958f45710504f52d3"}, - {file = "jiter-0.11.1-cp314-cp314-win32.whl", hash = "sha256:87202ec6ff9626ff5f9351507def98fcf0df60e9a146308e8ab221432228f4ea"}, - {file = "jiter-0.11.1-cp314-cp314-win_amd64.whl", hash = "sha256:a5dd268f6531a182c89d0dd9a3f8848e86e92dfff4201b77a18e6b98aa59798c"}, - {file = "jiter-0.11.1-cp314-cp314-win_arm64.whl", hash = "sha256:5d761f863f912a44748a21b5c4979c04252588ded8d1d2760976d2e42cd8d991"}, - {file = "jiter-0.11.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2cc5a3965285ddc33e0cab933e96b640bc9ba5940cea27ebbbf6695e72d6511c"}, - {file = "jiter-0.11.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b572b3636a784c2768b2342f36a23078c8d3aa6d8a30745398b1bab58a6f1a8"}, - {file = "jiter-0.11.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad93e3d67a981f96596d65d2298fe8d1aa649deb5374a2fb6a434410ee11915e"}, - {file = "jiter-0.11.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a83097ce379e202dcc3fe3fc71a16d523d1ee9192c8e4e854158f96b3efe3f2f"}, - {file = "jiter-0.11.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7042c51e7fbeca65631eb0c332f90c0c082eab04334e7ccc28a8588e8e2804d9"}, - {file = "jiter-0.11.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a68d679c0e47649a61df591660507608adc2652442de7ec8276538ac46abe08"}, - {file = "jiter-0.11.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a1b0da75dbf4b6ec0b3c9e604d1ee8beaf15bc046fff7180f7d89e3cdbd3bb51"}, - {file = "jiter-0.11.1-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:69dd514bf0fa31c62147d6002e5ca2b3e7ef5894f5ac6f0a19752385f4e89437"}, - {file = "jiter-0.11.1-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:bb31ac0b339efa24c0ca606febd8b77ef11c58d09af1b5f2be4c99e907b11111"}, - {file = "jiter-0.11.1-cp314-cp314t-win32.whl", hash = "sha256:b2ce0d6156a1d3ad41da3eec63b17e03e296b78b0e0da660876fccfada86d2f7"}, - {file = "jiter-0.11.1-cp314-cp314t-win_amd64.whl", hash = "sha256:f4db07d127b54c4a2d43b4cf05ff0193e4f73e0dd90c74037e16df0b29f666e1"}, - {file = "jiter-0.11.1-cp314-cp314t-win_arm64.whl", hash = "sha256:28e4fdf2d7ebfc935523e50d1efa3970043cfaa161674fe66f9642409d001dfe"}, - {file = "jiter-0.11.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:baa99c8db49467527658bb479857344daf0a14dff909b7f6714579ac439d1253"}, - {file = "jiter-0.11.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:860fe55fa3b01ad0edf2adde1098247ff5c303d0121f9ce028c03d4f88c69502"}, - {file = "jiter-0.11.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:173dd349d99b6feaf5a25a6fbcaf3489a6f947708d808240587a23df711c67db"}, - {file = "jiter-0.11.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:14ac1dca837514cc946a6ac2c4995d9695303ecc754af70a3163d057d1a444ab"}, - {file = "jiter-0.11.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69af47de5f93a231d5b85f7372d3284a5be8edb4cc758f006ec5a1406965ac5e"}, - {file = "jiter-0.11.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:685f8b3abd3bbd3e06e4dfe2429ff87fd5d7a782701151af99b1fcbd80e31b2b"}, - {file = "jiter-0.11.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d04afa2d4e5526e54ae8a58feea953b1844bf6e3526bc589f9de68e86d0ea01"}, - {file = "jiter-0.11.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1e92b927259035b50d8e11a8fdfe0ebd014d883e4552d37881643fa289a4bcf1"}, - {file = "jiter-0.11.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e7bd8be4fad8d4c5558b7801770cd2da6c072919c6f247cc5336edb143f25304"}, - {file = "jiter-0.11.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:121381a77a3c85987f3eba0d30ceaca9116f7463bedeec2fa79b2e7286b89b60"}, - {file = "jiter-0.11.1-cp39-cp39-win32.whl", hash = "sha256:160225407f6dfabdf9be1b44e22f06bc293a78a28ffa4347054698bd712dad06"}, - {file = "jiter-0.11.1-cp39-cp39-win_amd64.whl", hash = "sha256:028e0d59bcdfa1079f8df886cdaefc6f515c27a5288dec956999260c7e4a7cfd"}, - {file = "jiter-0.11.1-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:e642b5270e61dd02265866398707f90e365b5db2eb65a4f30c789d826682e1f6"}, - {file = "jiter-0.11.1-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:464ba6d000585e4e2fd1e891f31f1231f497273414f5019e27c00a4b8f7a24ad"}, - {file = "jiter-0.11.1-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:055568693ab35e0bf3a171b03bb40b2dcb10352359e0ab9b5ed0da2bf1eb6f6f"}, - {file = "jiter-0.11.1-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0c69ea798d08a915ba4478113efa9e694971e410056392f4526d796f136d3fa"}, - {file = "jiter-0.11.1-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:0d4d6993edc83cf75e8c6828a8d6ce40a09ee87e38c7bfba6924f39e1337e21d"}, - {file = "jiter-0.11.1-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:f78d151c83a87a6cf5461d5ee55bc730dd9ae227377ac6f115b922989b95f838"}, - {file = "jiter-0.11.1-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9022974781155cd5521d5cb10997a03ee5e31e8454c9d999dcdccd253f2353f"}, - {file = "jiter-0.11.1-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18c77aaa9117510d5bdc6a946baf21b1f0cfa58ef04d31c8d016f206f2118960"}, - {file = "jiter-0.11.1.tar.gz", hash = "sha256:849dcfc76481c0ea0099391235b7ca97d7279e0fa4c86005457ac7c88e8b76dc"}, -] - -[[package]] -name = "jsonschema" -version = "3.2.0" -description = "An implementation of JSON Schema validation for Python" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, - {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, -] - -[package.dependencies] -attrs = ">=17.4.0" -pyrsistent = ">=0.14.0" -setuptools = "*" -six = ">=1.11.0" - -[package.extras] -format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"] -format-nongpl = ["idna", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "webcolors"] - -[[package]] -name = "kaitaistruct" -version = "0.10" -description = "Kaitai Struct declarative parser generator for binary data: runtime library for Python" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -groups = ["main"] -files = [ - {file = "kaitaistruct-0.10-py2.py3-none-any.whl", hash = "sha256:a97350919adbf37fda881f75e9365e2fb88d04832b7a4e57106ec70119efb235"}, - {file = "kaitaistruct-0.10.tar.gz", hash = "sha256:a044dee29173d6afbacf27bcac39daf89b654dd418cfa009ab82d9178a9ae52a"}, -] - -[[package]] -name = "ldap3" -version = "2.9.1" -description = "A strictly RFC 4510 conforming LDAP V3 pure Python client library" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "ldap3-2.9.1-py2.py3-none-any.whl", hash = "sha256:5869596fc4948797020d3f03b7939da938778a0f9e2009f7a072ccf92b8e8d70"}, - {file = "ldap3-2.9.1.tar.gz", hash = "sha256:f3e7fc4718e3f09dda568b57100095e0ce58633bcabbed8667ce3f8fbaa4229f"}, -] - -[package.dependencies] -pyasn1 = ">=0.4.6" - -[[package]] -name = "markdown-it-py" -version = "3.0.0" -description = "Python port of markdown-it. Markdown parsing, done right!" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, - {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, -] - -[package.dependencies] -mdurl = ">=0.1,<1.0" - -[package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark"] -code-style = ["pre-commit (>=3.0,<4.0)"] -compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] -linkify = ["linkify-it-py (>=1,<3)"] -plugins = ["mdit-py-plugins"] -profiling = ["gprof2dot"] -rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] - -[[package]] -name = "markupsafe" -version = "3.0.1" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "MarkupSafe-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:db842712984e91707437461930e6011e60b39136c7331e971952bb30465bc1a1"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ffb4a8e7d46ed96ae48805746755fadd0909fea2306f93d5d8233ba23dda12a"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67c519635a4f64e495c50e3107d9b4075aec33634272b5db1cde839e07367589"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48488d999ed50ba8d38c581d67e496f955821dc183883550a6fbc7f1aefdc170"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f31ae06f1328595d762c9a2bf29dafd8621c7d3adc130cbb46278079758779ca"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:80fcbf3add8790caddfab6764bde258b5d09aefbe9169c183f88a7410f0f6dea"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3341c043c37d78cc5ae6e3e305e988532b072329639007fd408a476642a89fd6"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cb53e2a99df28eee3b5f4fea166020d3ef9116fdc5764bc5117486e6d1211b25"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-win32.whl", hash = "sha256:db15ce28e1e127a0013dfb8ac243a8e392db8c61eae113337536edb28bdc1f97"}, - {file = "MarkupSafe-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:4ffaaac913c3f7345579db4f33b0020db693f302ca5137f106060316761beea9"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:26627785a54a947f6d7336ce5963569b5d75614619e75193bdb4e06e21d447ad"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b954093679d5750495725ea6f88409946d69cfb25ea7b4c846eef5044194f583"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:973a371a55ce9ed333a3a0f8e0bcfae9e0d637711534bcb11e130af2ab9334e7"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:244dbe463d5fb6d7ce161301a03a6fe744dac9072328ba9fc82289238582697b"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d98e66a24497637dd31ccab090b34392dddb1f2f811c4b4cd80c230205c074a3"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ad91738f14eb8da0ff82f2acd0098b6257621410dcbd4df20aaa5b4233d75a50"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7044312a928a66a4c2a22644147bc61a199c1709712069a344a3fb5cfcf16915"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a4792d3b3a6dfafefdf8e937f14906a51bd27025a36f4b188728a73382231d91"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-win32.whl", hash = "sha256:fa7d686ed9883f3d664d39d5a8e74d3c5f63e603c2e3ff0abcba23eac6542635"}, - {file = "MarkupSafe-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ba25a71ebf05b9bb0e2ae99f8bc08a07ee8e98c612175087112656ca0f5c8bf"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8ae369e84466aa70f3154ee23c1451fda10a8ee1b63923ce76667e3077f2b0c4"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40f1e10d51c92859765522cbd79c5c8989f40f0419614bcdc5015e7b6bf97fc5"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a4cb365cb49b750bdb60b846b0c0bc49ed62e59a76635095a179d440540c346"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee3941769bd2522fe39222206f6dd97ae83c442a94c90f2b7a25d847d40f4729"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62fada2c942702ef8952754abfc1a9f7658a4d5460fabe95ac7ec2cbe0d02abc"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c2d64fdba74ad16138300815cfdc6ab2f4647e23ced81f59e940d7d4a1469d9"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:fb532dd9900381d2e8f48172ddc5a59db4c445a11b9fab40b3b786da40d3b56b"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0f84af7e813784feb4d5e4ff7db633aba6c8ca64a833f61d8e4eade234ef0c38"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-win32.whl", hash = "sha256:cbf445eb5628981a80f54087f9acdbf84f9b7d862756110d172993b9a5ae81aa"}, - {file = "MarkupSafe-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:a10860e00ded1dd0a65b83e717af28845bb7bd16d8ace40fe5531491de76b79f"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e81c52638315ff4ac1b533d427f50bc0afc746deb949210bc85f05d4f15fd772"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:312387403cd40699ab91d50735ea7a507b788091c416dd007eac54434aee51da"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ae99f31f47d849758a687102afdd05bd3d3ff7dbab0a8f1587981b58a76152a"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c97ff7fedf56d86bae92fa0a646ce1a0ec7509a7578e1ed238731ba13aabcd1c"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7420ceda262dbb4b8d839a4ec63d61c261e4e77677ed7c66c99f4e7cb5030dd"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45d42d132cff577c92bfba536aefcfea7e26efb975bd455db4e6602f5c9f45e7"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4c8817557d0de9349109acb38b9dd570b03cc5014e8aabf1cbddc6e81005becd"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a54c43d3ec4cf2a39f4387ad044221c66a376e58c0d0e971d47c475ba79c6b5"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-win32.whl", hash = "sha256:c91b394f7601438ff79a4b93d16be92f216adb57d813a78be4446fe0f6bc2d8c"}, - {file = "MarkupSafe-3.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:fe32482b37b4b00c7a52a07211b479653b7fe4f22b2e481b9a9b099d8a430f2f"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:17b2aea42a7280db02ac644db1d634ad47dcc96faf38ab304fe26ba2680d359a"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:852dc840f6d7c985603e60b5deaae1d89c56cb038b577f6b5b8c808c97580f1d"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0778de17cff1acaeccc3ff30cd99a3fd5c50fc58ad3d6c0e0c4c58092b859396"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:800100d45176652ded796134277ecb13640c1a537cad3b8b53da45aa96330453"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d06b24c686a34c86c8c1fba923181eae6b10565e4d80bdd7bc1c8e2f11247aa4"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:33d1c36b90e570ba7785dacd1faaf091203d9942bc036118fab8110a401eb1a8"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:beeebf760a9c1f4c07ef6a53465e8cfa776ea6a2021eda0d0417ec41043fe984"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:bbde71a705f8e9e4c3e9e33db69341d040c827c7afa6789b14c6e16776074f5a"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-win32.whl", hash = "sha256:82b5dba6eb1bcc29cc305a18a3c5365d2af06ee71b123216416f7e20d2a84e5b"}, - {file = "MarkupSafe-3.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:730d86af59e0e43ce277bb83970530dd223bf7f2a838e086b50affa6ec5f9295"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4935dd7883f1d50e2ffecca0aa33dc1946a94c8f3fdafb8df5c330e48f71b132"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e9393357f19954248b00bed7c56f29a25c930593a77630c719653d51e7669c2a"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40621d60d0e58aa573b68ac5e2d6b20d44392878e0bfc159012a5787c4e35bc8"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f94190df587738280d544971500b9cafc9b950d32efcb1fba9ac10d84e6aa4e6"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6a387d61fe41cdf7ea95b38e9af11cfb1a63499af2759444b99185c4ab33f5b"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8ad4ad1429cd4f315f32ef263c1342166695fad76c100c5d979c45d5570ed58b"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e24bfe89c6ac4c31792793ad9f861b8f6dc4546ac6dc8f1c9083c7c4f2b335cd"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2a4b34a8d14649315c4bc26bbfa352663eb51d146e35eef231dd739d54a5430a"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-win32.whl", hash = "sha256:242d6860f1fd9191aef5fae22b51c5c19767f93fb9ead4d21924e0bcb17619d8"}, - {file = "MarkupSafe-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:93e8248d650e7e9d49e8251f883eed60ecbc0e8ffd6349e18550925e31bd029b"}, - {file = "markupsafe-3.0.1.tar.gz", hash = "sha256:3e683ee4f5d0fa2dde4db77ed8dd8a876686e3fc417655c2ece9a90576905344"}, -] - -[[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, -] - -[[package]] -name = "mitmproxy" -version = "10.3.0" -description = "An interactive, SSL/TLS-capable intercepting proxy for HTTP/1, HTTP/2, and WebSockets." -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "mitmproxy-10.3.0-py3-none-any.whl", hash = "sha256:e9c5330ddad4589bfbe001ba35a9654676c97ab51a7a714990f4a83324eab84c"}, -] - -[package.dependencies] -aioquic = ">=1.0.0,<2.0.0" -asgiref = ">=3.2.10,<3.9" -Brotli = ">=1.0,<1.2" -certifi = ">=2019.9.11" -cryptography = ">=42.0,<42.1" -flask = ">=1.1.1,<3.1" -h11 = ">=0.11,<0.15" -h2 = ">=4.1,<5" -hyperframe = ">=6.0,<7" -kaitaistruct = ">=0.10,<0.11" -ldap3 = ">=2.8,<2.10" -mitmproxy-rs = ">=0.5.1,<0.6" -msgpack = ">=1.0.0,<1.1.0" -passlib = ">=1.6.5,<1.8" -protobuf = ">=3.14,<6" -publicsuffix2 = ">=2.20190812,<3" -pydivert = {version = ">=2.0.3,<2.2", markers = "sys_platform == \"win32\""} -pyOpenSSL = ">=22.1,<24.2" -pyparsing = ">=2.4.2,<3.2" -pyperclip = ">=1.6.0,<1.9" -"ruamel.yaml" = ">=0.16,<0.19" -sortedcontainers = ">=2.3,<2.5" -tornado = ">=6.2,<7" -urwid-mitmproxy = ">=2.1.1,<2.2" -wsproto = ">=1.0,<1.3" -zstandard = ">=0.11,<0.23" - -[package.extras] -dev = ["build (>=0.10.0)", "click (>=7.0,<8.2)", "hypothesis (>=5.8,<7)", "pdoc (>=4.0.0)", "pyinstaller (==6.5.0)", "pytest (>=6.1.0,<9)", "pytest-asyncio (>=0.23,<0.24)", "pytest-cov (>=2.7.1,<5.1)", "pytest-timeout (>=1.3.3,<2.4)", "pytest-xdist (>=2.1.0,<3.6)", "requests (>=2.9.1,<3)", "tox (>=3.5,<5)", "wheel (>=0.36.2,<0.44)"] - -[[package]] -name = "mitmproxy-macos" -version = "0.5.2" -description = "" -optional = false -python-versions = ">=3.10" -groups = ["main"] -markers = "sys_platform == \"darwin\"" -files = [ - {file = "mitmproxy_macos-0.5.2-py3-none-any.whl", hash = "sha256:4aeee54ea4ecf7320b248292ef6dbc668ab14478efbdbf1234ae5ca120a13e63"}, -] - -[[package]] -name = "mitmproxy-rs" -version = "0.5.2" -description = "" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "mitmproxy_rs-0.5.2-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c9e0c7136579adb5f23b3d12c40b392122276133e5cd1b2319ad0e01d1ec8ec0"}, - {file = "mitmproxy_rs-0.5.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45ca572479f32787de94b574dbedec042ab1d34d727d3597812fbdbd2f41922e"}, - {file = "mitmproxy_rs-0.5.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b4624e6b302d67fa94e50858a14a171708437e73146e3372ed042e01a09ca85"}, - {file = "mitmproxy_rs-0.5.2-cp310-abi3-win_amd64.whl", hash = "sha256:5e9f07b86b8a0f6a2c3c86c1fe902070e65868a0cf4d668ca7d1e2a802fe6e3f"}, - {file = "mitmproxy_rs-0.5.2.tar.gz", hash = "sha256:7583bea1ff5ea8e96c5cf12127e1698c52725f1dfdac6802891a4675b7287ba5"}, -] - -[package.dependencies] -mitmproxy_macos = {version = "0.5.2", markers = "sys_platform == \"darwin\""} -mitmproxy_windows = {version = "0.5.2", markers = "os_name == \"nt\""} - -[[package]] -name = "mitmproxy-windows" -version = "0.5.2" -description = "" -optional = false -python-versions = ">=3.10" -groups = ["main"] -markers = "os_name == \"nt\"" -files = [ - {file = "mitmproxy_windows-0.5.2-py3-none-any.whl", hash = "sha256:e7834cd4825a55d703b4aed34d2d7f85a2749ccb86396e328339070e528a3561"}, -] - -[[package]] -name = "msgpack" -version = "1.0.8" -description = "MessagePack serializer" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:505fe3d03856ac7d215dbe005414bc28505d26f0c128906037e66d98c4e95868"}, - {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b7842518a63a9f17107eb176320960ec095a8ee3b4420b5f688e24bf50c53c"}, - {file = "msgpack-1.0.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:376081f471a2ef24828b83a641a02c575d6103a3ad7fd7dade5486cad10ea659"}, - {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e390971d082dba073c05dbd56322427d3280b7cc8b53484c9377adfbae67dc2"}, - {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e073efcba9ea99db5acef3959efa45b52bc67b61b00823d2a1a6944bf45982"}, - {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82d92c773fbc6942a7a8b520d22c11cfc8fd83bba86116bfcf962c2f5c2ecdaa"}, - {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9ee32dcb8e531adae1f1ca568822e9b3a738369b3b686d1477cbc643c4a9c128"}, - {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e3aa7e51d738e0ec0afbed661261513b38b3014754c9459508399baf14ae0c9d"}, - {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69284049d07fce531c17404fcba2bb1df472bc2dcdac642ae71a2d079d950653"}, - {file = "msgpack-1.0.8-cp310-cp310-win32.whl", hash = "sha256:13577ec9e247f8741c84d06b9ece5f654920d8365a4b636ce0e44f15e07ec693"}, - {file = "msgpack-1.0.8-cp310-cp310-win_amd64.whl", hash = "sha256:e532dbd6ddfe13946de050d7474e3f5fb6ec774fbb1a188aaf469b08cf04189a"}, - {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9517004e21664f2b5a5fd6333b0731b9cf0817403a941b393d89a2f1dc2bd836"}, - {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d16a786905034e7e34098634b184a7d81f91d4c3d246edc6bd7aefb2fd8ea6ad"}, - {file = "msgpack-1.0.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2872993e209f7ed04d963e4b4fbae72d034844ec66bc4ca403329db2074377b"}, - {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c330eace3dd100bdb54b5653b966de7f51c26ec4a7d4e87132d9b4f738220ba"}, - {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b5c044f3eff2a6534768ccfd50425939e7a8b5cf9a7261c385de1e20dcfc85"}, - {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1876b0b653a808fcd50123b953af170c535027bf1d053b59790eebb0aeb38950"}, - {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dfe1f0f0ed5785c187144c46a292b8c34c1295c01da12e10ccddfc16def4448a"}, - {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3528807cbbb7f315bb81959d5961855e7ba52aa60a3097151cb21956fbc7502b"}, - {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e2f879ab92ce502a1e65fce390eab619774dda6a6ff719718069ac94084098ce"}, - {file = "msgpack-1.0.8-cp311-cp311-win32.whl", hash = "sha256:26ee97a8261e6e35885c2ecd2fd4a6d38252246f94a2aec23665a4e66d066305"}, - {file = "msgpack-1.0.8-cp311-cp311-win_amd64.whl", hash = "sha256:eadb9f826c138e6cf3c49d6f8de88225a3c0ab181a9b4ba792e006e5292d150e"}, - {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:114be227f5213ef8b215c22dde19532f5da9652e56e8ce969bf0a26d7c419fee"}, - {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d661dc4785affa9d0edfdd1e59ec056a58b3dbb9f196fa43587f3ddac654ac7b"}, - {file = "msgpack-1.0.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d56fd9f1f1cdc8227d7b7918f55091349741904d9520c65f0139a9755952c9e8"}, - {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0726c282d188e204281ebd8de31724b7d749adebc086873a59efb8cf7ae27df3"}, - {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8db8e423192303ed77cff4dce3a4b88dbfaf43979d280181558af5e2c3c71afc"}, - {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99881222f4a8c2f641f25703963a5cefb076adffd959e0558dc9f803a52d6a58"}, - {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b5505774ea2a73a86ea176e8a9a4a7c8bf5d521050f0f6f8426afe798689243f"}, - {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ef254a06bcea461e65ff0373d8a0dd1ed3aa004af48839f002a0c994a6f72d04"}, - {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e1dd7839443592d00e96db831eddb4111a2a81a46b028f0facd60a09ebbdd543"}, - {file = "msgpack-1.0.8-cp312-cp312-win32.whl", hash = "sha256:64d0fcd436c5683fdd7c907eeae5e2cbb5eb872fafbc03a43609d7941840995c"}, - {file = "msgpack-1.0.8-cp312-cp312-win_amd64.whl", hash = "sha256:74398a4cf19de42e1498368c36eed45d9528f5fd0155241e82c4082b7e16cffd"}, - {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ceea77719d45c839fd73abcb190b8390412a890df2f83fb8cf49b2a4b5c2f40"}, - {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ab0bbcd4d1f7b6991ee7c753655b481c50084294218de69365f8f1970d4c151"}, - {file = "msgpack-1.0.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1cce488457370ffd1f953846f82323cb6b2ad2190987cd4d70b2713e17268d24"}, - {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3923a1778f7e5ef31865893fdca12a8d7dc03a44b33e2a5f3295416314c09f5d"}, - {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a22e47578b30a3e199ab067a4d43d790249b3c0587d9a771921f86250c8435db"}, - {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd739c9251d01e0279ce729e37b39d49a08c0420d3fee7f2a4968c0576678f77"}, - {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d3420522057ebab1728b21ad473aa950026d07cb09da41103f8e597dfbfaeb13"}, - {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5845fdf5e5d5b78a49b826fcdc0eb2e2aa7191980e3d2cfd2a30303a74f212e2"}, - {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a0e76621f6e1f908ae52860bdcb58e1ca85231a9b0545e64509c931dd34275a"}, - {file = "msgpack-1.0.8-cp38-cp38-win32.whl", hash = "sha256:374a8e88ddab84b9ada695d255679fb99c53513c0a51778796fcf0944d6c789c"}, - {file = "msgpack-1.0.8-cp38-cp38-win_amd64.whl", hash = "sha256:f3709997b228685fe53e8c433e2df9f0cdb5f4542bd5114ed17ac3c0129b0480"}, - {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f51bab98d52739c50c56658cc303f190785f9a2cd97b823357e7aeae54c8f68a"}, - {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:73ee792784d48aa338bba28063e19a27e8d989344f34aad14ea6e1b9bd83f596"}, - {file = "msgpack-1.0.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f9904e24646570539a8950400602d66d2b2c492b9010ea7e965025cb71d0c86d"}, - {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e75753aeda0ddc4c28dce4c32ba2f6ec30b1b02f6c0b14e547841ba5b24f753f"}, - {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5dbf059fb4b7c240c873c1245ee112505be27497e90f7c6591261c7d3c3a8228"}, - {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4916727e31c28be8beaf11cf117d6f6f188dcc36daae4e851fee88646f5b6b18"}, - {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7938111ed1358f536daf311be244f34df7bf3cdedb3ed883787aca97778b28d8"}, - {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:493c5c5e44b06d6c9268ce21b302c9ca055c1fd3484c25ba41d34476c76ee746"}, - {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"}, - {file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"}, - {file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"}, - {file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"}, -] - -[[package]] -name = "multidict" -version = "6.1.0" -description = "multidict implementation" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, - {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, - {file = "multidict-6.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7"}, - {file = "multidict-6.1.0-cp310-cp310-win32.whl", hash = "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0"}, - {file = "multidict-6.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d"}, - {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6"}, - {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156"}, - {file = "multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753"}, - {file = "multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80"}, - {file = "multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926"}, - {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa"}, - {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436"}, - {file = "multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3"}, - {file = "multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133"}, - {file = "multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1"}, - {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008"}, - {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f"}, - {file = "multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6"}, - {file = "multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81"}, - {file = "multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774"}, - {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392"}, - {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a"}, - {file = "multidict-6.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd"}, - {file = "multidict-6.1.0-cp38-cp38-win32.whl", hash = "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167"}, - {file = "multidict-6.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef"}, - {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c"}, - {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1"}, - {file = "multidict-6.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43"}, - {file = "multidict-6.1.0-cp39-cp39-win32.whl", hash = "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada"}, - {file = "multidict-6.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a"}, - {file = "multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506"}, - {file = "multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a"}, -] - -[[package]] -name = "mypy" -version = "1.11.2" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "mypy-1.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d42a6dd818ffce7be66cce644f1dff482f1d97c53ca70908dff0b9ddc120b77a"}, - {file = "mypy-1.11.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:801780c56d1cdb896eacd5619a83e427ce436d86a3bdf9112527f24a66618fef"}, - {file = "mypy-1.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41ea707d036a5307ac674ea172875f40c9d55c5394f888b168033177fce47383"}, - {file = "mypy-1.11.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6e658bd2d20565ea86da7d91331b0eed6d2eee22dc031579e6297f3e12c758c8"}, - {file = "mypy-1.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:478db5f5036817fe45adb7332d927daa62417159d49783041338921dcf646fc7"}, - {file = "mypy-1.11.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75746e06d5fa1e91bfd5432448d00d34593b52e7e91a187d981d08d1f33d4385"}, - {file = "mypy-1.11.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a976775ab2256aadc6add633d44f100a2517d2388906ec4f13231fafbb0eccca"}, - {file = "mypy-1.11.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd953f221ac1379050a8a646585a29574488974f79d8082cedef62744f0a0104"}, - {file = "mypy-1.11.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:57555a7715c0a34421013144a33d280e73c08df70f3a18a552938587ce9274f4"}, - {file = "mypy-1.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:36383a4fcbad95f2657642a07ba22ff797de26277158f1cc7bd234821468b1b6"}, - {file = "mypy-1.11.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e8960dbbbf36906c5c0b7f4fbf2f0c7ffb20f4898e6a879fcf56a41a08b0d318"}, - {file = "mypy-1.11.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:06d26c277962f3fb50e13044674aa10553981ae514288cb7d0a738f495550b36"}, - {file = "mypy-1.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e7184632d89d677973a14d00ae4d03214c8bc301ceefcdaf5c474866814c987"}, - {file = "mypy-1.11.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3a66169b92452f72117e2da3a576087025449018afc2d8e9bfe5ffab865709ca"}, - {file = "mypy-1.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:969ea3ef09617aff826885a22ece0ddef69d95852cdad2f60c8bb06bf1f71f70"}, - {file = "mypy-1.11.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:37c7fa6121c1cdfcaac97ce3d3b5588e847aa79b580c1e922bb5d5d2902df19b"}, - {file = "mypy-1.11.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a8a53bc3ffbd161b5b2a4fff2f0f1e23a33b0168f1c0778ec70e1a3d66deb86"}, - {file = "mypy-1.11.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ff93107f01968ed834f4256bc1fc4475e2fecf6c661260066a985b52741ddce"}, - {file = "mypy-1.11.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:edb91dded4df17eae4537668b23f0ff6baf3707683734b6a818d5b9d0c0c31a1"}, - {file = "mypy-1.11.2-cp38-cp38-win_amd64.whl", hash = "sha256:ee23de8530d99b6db0573c4ef4bd8f39a2a6f9b60655bf7a1357e585a3486f2b"}, - {file = "mypy-1.11.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:801ca29f43d5acce85f8e999b1e431fb479cb02d0e11deb7d2abb56bdaf24fd6"}, - {file = "mypy-1.11.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af8d155170fcf87a2afb55b35dc1a0ac21df4431e7d96717621962e4b9192e70"}, - {file = "mypy-1.11.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7821776e5c4286b6a13138cc935e2e9b6fde05e081bdebf5cdb2bb97c9df81d"}, - {file = "mypy-1.11.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:539c570477a96a4e6fb718b8d5c3e0c0eba1f485df13f86d2970c91f0673148d"}, - {file = "mypy-1.11.2-cp39-cp39-win_amd64.whl", hash = "sha256:3f14cd3d386ac4d05c5a39a51b84387403dadbd936e17cb35882134d4f8f0d24"}, - {file = "mypy-1.11.2-py3-none-any.whl", hash = "sha256:b499bc07dbdcd3de92b0a8b29fdf592c111276f6a12fe29c30f6c417dd546d12"}, - {file = "mypy-1.11.2.tar.gz", hash = "sha256:7f9993ad3e0ffdc95c2a14b66dee63729f021968bff8ad911867579c65d13a79"}, -] - -[package.dependencies] -mypy-extensions = ">=1.0.0" -typing-extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -groups = ["dev"] -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "numpy" -version = "2.1.2" -description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.10" -groups = ["main", "dev"] -files = [ - {file = "numpy-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:30d53720b726ec36a7f88dc873f0eec8447fbc93d93a8f079dfac2629598d6ee"}, - {file = "numpy-2.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8d3ca0a72dd8846eb6f7dfe8f19088060fcb76931ed592d29128e0219652884"}, - {file = "numpy-2.1.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:fc44e3c68ff00fd991b59092a54350e6e4911152682b4782f68070985aa9e648"}, - {file = "numpy-2.1.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:7c1c60328bd964b53f8b835df69ae8198659e2b9302ff9ebb7de4e5a5994db3d"}, - {file = "numpy-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6cdb606a7478f9ad91c6283e238544451e3a95f30fb5467fbf715964341a8a86"}, - {file = "numpy-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d666cb72687559689e9906197e3bec7b736764df6a2e58ee265e360663e9baf7"}, - {file = "numpy-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c6eef7a2dbd0abfb0d9eaf78b73017dbfd0b54051102ff4e6a7b2980d5ac1a03"}, - {file = "numpy-2.1.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:12edb90831ff481f7ef5f6bc6431a9d74dc0e5ff401559a71e5e4611d4f2d466"}, - {file = "numpy-2.1.2-cp310-cp310-win32.whl", hash = "sha256:a65acfdb9c6ebb8368490dbafe83c03c7e277b37e6857f0caeadbbc56e12f4fb"}, - {file = "numpy-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:860ec6e63e2c5c2ee5e9121808145c7bf86c96cca9ad396c0bd3e0f2798ccbe2"}, - {file = "numpy-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b42a1a511c81cc78cbc4539675713bbcf9d9c3913386243ceff0e9429ca892fe"}, - {file = "numpy-2.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:faa88bc527d0f097abdc2c663cddf37c05a1c2f113716601555249805cf573f1"}, - {file = "numpy-2.1.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:c82af4b2ddd2ee72d1fc0c6695048d457e00b3582ccde72d8a1c991b808bb20f"}, - {file = "numpy-2.1.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:13602b3174432a35b16c4cfb5de9a12d229727c3dd47a6ce35111f2ebdf66ff4"}, - {file = "numpy-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ebec5fd716c5a5b3d8dfcc439be82a8407b7b24b230d0ad28a81b61c2f4659a"}, - {file = "numpy-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2b49c3c0804e8ecb05d59af8386ec2f74877f7ca8fd9c1e00be2672e4d399b1"}, - {file = "numpy-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2cbba4b30bf31ddbe97f1c7205ef976909a93a66bb1583e983adbd155ba72ac2"}, - {file = "numpy-2.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8e00ea6fc82e8a804433d3e9cedaa1051a1422cb6e443011590c14d2dea59146"}, - {file = "numpy-2.1.2-cp311-cp311-win32.whl", hash = "sha256:5006b13a06e0b38d561fab5ccc37581f23c9511879be7693bd33c7cd15ca227c"}, - {file = "numpy-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:f1eb068ead09f4994dec71c24b2844f1e4e4e013b9629f812f292f04bd1510d9"}, - {file = "numpy-2.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7bf0a4f9f15b32b5ba53147369e94296f5fffb783db5aacc1be15b4bf72f43b"}, - {file = "numpy-2.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b1d0fcae4f0949f215d4632be684a539859b295e2d0cb14f78ec231915d644db"}, - {file = "numpy-2.1.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:f751ed0a2f250541e19dfca9f1eafa31a392c71c832b6bb9e113b10d050cb0f1"}, - {file = "numpy-2.1.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:bd33f82e95ba7ad632bc57837ee99dba3d7e006536200c4e9124089e1bf42426"}, - {file = "numpy-2.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b8cde4f11f0a975d1fd59373b32e2f5a562ade7cde4f85b7137f3de8fbb29a0"}, - {file = "numpy-2.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d95f286b8244b3649b477ac066c6906fbb2905f8ac19b170e2175d3d799f4df"}, - {file = "numpy-2.1.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ab4754d432e3ac42d33a269c8567413bdb541689b02d93788af4131018cbf366"}, - {file = "numpy-2.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e585c8ae871fd38ac50598f4763d73ec5497b0de9a0ab4ef5b69f01c6a046142"}, - {file = "numpy-2.1.2-cp312-cp312-win32.whl", hash = "sha256:9c6c754df29ce6a89ed23afb25550d1c2d5fdb9901d9c67a16e0b16eaf7e2550"}, - {file = "numpy-2.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:456e3b11cb79ac9946c822a56346ec80275eaf2950314b249b512896c0d2505e"}, - {file = "numpy-2.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a84498e0d0a1174f2b3ed769b67b656aa5460c92c9554039e11f20a05650f00d"}, - {file = "numpy-2.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4d6ec0d4222e8ffdab1744da2560f07856421b367928026fb540e1945f2eeeaf"}, - {file = "numpy-2.1.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:259ec80d54999cc34cd1eb8ded513cb053c3bf4829152a2e00de2371bd406f5e"}, - {file = "numpy-2.1.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:675c741d4739af2dc20cd6c6a5c4b7355c728167845e3c6b0e824e4e5d36a6c3"}, - {file = "numpy-2.1.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b2d4e667895cc55e3ff2b56077e4c8a5604361fc21a042845ea3ad67465aa8"}, - {file = "numpy-2.1.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43cca367bf94a14aca50b89e9bc2061683116cfe864e56740e083392f533ce7a"}, - {file = "numpy-2.1.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:76322dcdb16fccf2ac56f99048af32259dcc488d9b7e25b51e5eca5147a3fb98"}, - {file = "numpy-2.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:32e16a03138cabe0cb28e1007ee82264296ac0983714094380b408097a418cfe"}, - {file = "numpy-2.1.2-cp313-cp313-win32.whl", hash = "sha256:242b39d00e4944431a3cd2db2f5377e15b5785920421993770cddb89992c3f3a"}, - {file = "numpy-2.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:f2ded8d9b6f68cc26f8425eda5d3877b47343e68ca23d0d0846f4d312ecaa445"}, - {file = "numpy-2.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ffef621c14ebb0188a8633348504a35c13680d6da93ab5cb86f4e54b7e922b5"}, - {file = "numpy-2.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ad369ed238b1959dfbade9018a740fb9392c5ac4f9b5173f420bd4f37ba1f7a0"}, - {file = "numpy-2.1.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d82075752f40c0ddf57e6e02673a17f6cb0f8eb3f587f63ca1eaab5594da5b17"}, - {file = "numpy-2.1.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:1600068c262af1ca9580a527d43dc9d959b0b1d8e56f8a05d830eea39b7c8af6"}, - {file = "numpy-2.1.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a26ae94658d3ba3781d5e103ac07a876b3e9b29db53f68ed7df432fd033358a8"}, - {file = "numpy-2.1.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13311c2db4c5f7609b462bc0f43d3c465424d25c626d95040f073e30f7570e35"}, - {file = "numpy-2.1.2-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:2abbf905a0b568706391ec6fa15161fad0fb5d8b68d73c461b3c1bab6064dd62"}, - {file = "numpy-2.1.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ef444c57d664d35cac4e18c298c47d7b504c66b17c2ea91312e979fcfbdfb08a"}, - {file = "numpy-2.1.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:bdd407c40483463898b84490770199d5714dcc9dd9b792f6c6caccc523c00952"}, - {file = "numpy-2.1.2-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:da65fb46d4cbb75cb417cddf6ba5e7582eb7bb0b47db4b99c9fe5787ce5d91f5"}, - {file = "numpy-2.1.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c193d0b0238638e6fc5f10f1b074a6993cb13b0b431f64079a509d63d3aa8b7"}, - {file = "numpy-2.1.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a7d80b2e904faa63068ead63107189164ca443b42dd1930299e0d1cb041cec2e"}, - {file = "numpy-2.1.2.tar.gz", hash = "sha256:13532a088217fa624c99b843eeb54640de23b3414b14aa66d023805eb731066c"}, -] - -[[package]] -name = "oauthlib" -version = "3.2.2" -description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, - {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, -] - -[package.extras] -rsa = ["cryptography (>=3.0.0)"] -signals = ["blinker (>=1.4.0)"] -signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] - -[[package]] -name = "openai" -version = "1.109.1" -description = "The official Python library for the openai API" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "openai-1.109.1-py3-none-any.whl", hash = "sha256:6bcaf57086cf59159b8e27447e4e7dd019db5d29a438072fbd49c290c7e65315"}, - {file = "openai-1.109.1.tar.gz", hash = "sha256:d173ed8dbca665892a6db099b4a2dfac624f94d20a93f46eb0b56aae940ed869"}, -] - -[package.dependencies] -anyio = ">=3.5.0,<5" -distro = ">=1.7.0,<2" -httpx = ">=0.23.0,<1" -jiter = ">=0.4.0,<1" -pydantic = ">=1.9.0,<3" -sniffio = "*" -tqdm = ">4" -typing-extensions = ">=4.11,<5" - -[package.extras] -aiohttp = ["aiohttp", "httpx-aiohttp (>=0.1.8)"] -datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] -realtime = ["websockets (>=13,<16)"] -voice-helpers = ["numpy (>=2.0.2)", "sounddevice (>=0.5.1)"] - -[[package]] -name = "opentelemetry-api" -version = "1.27.0" -description = "OpenTelemetry Python API" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_api-1.27.0-py3-none-any.whl", hash = "sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7"}, - {file = "opentelemetry_api-1.27.0.tar.gz", hash = "sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342"}, -] - -[package.dependencies] -deprecated = ">=1.2.6" -importlib-metadata = ">=6.0,<=8.4.0" - -[[package]] -name = "opentelemetry-exporter-otlp-proto-common" -version = "1.27.0" -description = "OpenTelemetry Protobuf encoding" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_exporter_otlp_proto_common-1.27.0-py3-none-any.whl", hash = "sha256:675db7fffcb60946f3a5c43e17d1168a3307a94a930ecf8d2ea1f286f3d4f79a"}, - {file = "opentelemetry_exporter_otlp_proto_common-1.27.0.tar.gz", hash = "sha256:159d27cf49f359e3798c4c3eb8da6ef4020e292571bd8c5604a2a573231dd5c8"}, -] - -[package.dependencies] -opentelemetry-proto = "1.27.0" - -[[package]] -name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.27.0" -description = "OpenTelemetry Collector Protobuf over gRPC Exporter" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_exporter_otlp_proto_grpc-1.27.0-py3-none-any.whl", hash = "sha256:56b5bbd5d61aab05e300d9d62a6b3c134827bbd28d0b12f2649c2da368006c9e"}, - {file = "opentelemetry_exporter_otlp_proto_grpc-1.27.0.tar.gz", hash = "sha256:af6f72f76bcf425dfb5ad11c1a6d6eca2863b91e63575f89bb7b4b55099d968f"}, -] - -[package.dependencies] -deprecated = ">=1.2.6" -googleapis-common-protos = ">=1.52,<2.0" -grpcio = ">=1.0.0,<2.0.0" -opentelemetry-api = ">=1.15,<2.0" -opentelemetry-exporter-otlp-proto-common = "1.27.0" -opentelemetry-proto = "1.27.0" -opentelemetry-sdk = ">=1.27.0,<1.28.0" - -[[package]] -name = "opentelemetry-proto" -version = "1.27.0" -description = "OpenTelemetry Python Proto" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_proto-1.27.0-py3-none-any.whl", hash = "sha256:b133873de5581a50063e1e4b29cdcf0c5e253a8c2d8dc1229add20a4c3830ace"}, - {file = "opentelemetry_proto-1.27.0.tar.gz", hash = "sha256:33c9345d91dafd8a74fc3d7576c5a38f18b7fdf8d02983ac67485386132aedd6"}, -] - -[package.dependencies] -protobuf = ">=3.19,<5.0" - -[[package]] -name = "opentelemetry-sdk" -version = "1.27.0" -description = "OpenTelemetry Python SDK" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_sdk-1.27.0-py3-none-any.whl", hash = "sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d"}, - {file = "opentelemetry_sdk-1.27.0.tar.gz", hash = "sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f"}, -] - -[package.dependencies] -opentelemetry-api = "1.27.0" -opentelemetry-semantic-conventions = "0.48b0" -typing-extensions = ">=3.7.4" - -[[package]] -name = "opentelemetry-semantic-conventions" -version = "0.48b0" -description = "OpenTelemetry Semantic Conventions" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "opentelemetry_semantic_conventions-0.48b0-py3-none-any.whl", hash = "sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f"}, - {file = "opentelemetry_semantic_conventions-0.48b0.tar.gz", hash = "sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a"}, -] - -[package.dependencies] -deprecated = ">=1.2.6" -opentelemetry-api = "1.27.0" - -[[package]] -name = "ordered-set" -version = "4.1.0" -description = "An OrderedSet is a custom MutableSet that remembers its order, so that every" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"}, - {file = "ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562"}, -] - -[package.extras] -dev = ["black", "mypy", "pytest"] - -[[package]] -name = "packaging" -version = "23.2" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, - {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, -] - -[[package]] -name = "pandas" -version = "2.2.3" -description = "Powerful data structures for data analysis, time series, and statistics" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5"}, - {file = "pandas-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348"}, - {file = "pandas-2.2.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d9c45366def9a3dd85a6454c0e7908f2b3b8e9c138f5dc38fed7ce720d8453ed"}, - {file = "pandas-2.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57"}, - {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b8661b0238a69d7aafe156b7fa86c44b881387509653fdf857bebc5e4008ad42"}, - {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f"}, - {file = "pandas-2.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645"}, - {file = "pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039"}, - {file = "pandas-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd"}, - {file = "pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698"}, - {file = "pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc"}, - {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3"}, - {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32"}, - {file = "pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5"}, - {file = "pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9"}, - {file = "pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4"}, - {file = "pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3"}, - {file = "pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319"}, - {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8"}, - {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a"}, - {file = "pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13"}, - {file = "pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015"}, - {file = "pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28"}, - {file = "pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0"}, - {file = "pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24"}, - {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659"}, - {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb"}, - {file = "pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d"}, - {file = "pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468"}, - {file = "pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18"}, - {file = "pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2"}, - {file = "pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4"}, - {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d"}, - {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a"}, - {file = "pandas-2.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc6b93f9b966093cb0fd62ff1a7e4c09e6d546ad7c1de191767baffc57628f39"}, - {file = "pandas-2.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5dbca4c1acd72e8eeef4753eeca07de9b1db4f398669d5994086f788a5d7cc30"}, - {file = "pandas-2.2.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8cd6d7cc958a3910f934ea8dbdf17b2364827bb4dafc38ce6eef6bb3d65ff09c"}, - {file = "pandas-2.2.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99df71520d25fade9db7c1076ac94eb994f4d2673ef2aa2e86ee039b6746d20c"}, - {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31d0ced62d4ea3e231a9f228366919a5ea0b07440d9d4dac345376fd8e1477ea"}, - {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7eee9e7cea6adf3e3d24e304ac6b8300646e2a5d1cd3a3c2abed9101b0846761"}, - {file = "pandas-2.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e"}, - {file = "pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667"}, -] - -[package.dependencies] -numpy = {version = ">=1.23.2", markers = "python_version == \"3.11\""} -python-dateutil = ">=2.8.2" -pytz = ">=2020.1" -tzdata = ">=2022.7" - -[package.extras] -all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] -aws = ["s3fs (>=2022.11.0)"] -clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] -compression = ["zstandard (>=0.19.0)"] -computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] -consortium-standard = ["dataframe-api-compat (>=0.1.7)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] -feather = ["pyarrow (>=10.0.1)"] -fss = ["fsspec (>=2022.11.0)"] -gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] -hdf5 = ["tables (>=3.8.0)"] -html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] -mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] -output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] -parquet = ["pyarrow (>=10.0.1)"] -performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] -plot = ["matplotlib (>=3.6.3)"] -postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] -pyarrow = ["pyarrow (>=10.0.1)"] -spss = ["pyreadstat (>=1.2.0)"] -sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] -test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] -xml = ["lxml (>=4.9.2)"] - -[[package]] -name = "pandas-gbq" -version = "0.22.0" -description = "Google BigQuery connector for pandas" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pandas-gbq-0.22.0.tar.gz", hash = "sha256:3fb24010c96e795c22b35d86601ef76f8aed84d5d17ceb8a4396a354c1949ece"}, - {file = "pandas_gbq-0.22.0-py2.py3-none-any.whl", hash = "sha256:e3bc1f9903928e4923dc5ff7f29fad9e9799aa406058567f1c654d934bf41323"}, -] - -[package.dependencies] -db-dtypes = ">=1.0.4,<2.0.0" -google-api-core = ">=2.10.2,<3.0.0dev" -google-auth = ">=2.13.0" -google-auth-oauthlib = ">=0.7.0" -google-cloud-bigquery = ">=3.3.5,<4.0.0dev" -numpy = ">=1.16.6" -packaging = ">=20.0.0" -pandas = ">=1.1.4" -pyarrow = ">=3.0.0" -pydata-google-auth = ">=1.5.0" -setuptools = "*" - -[package.extras] -bqstorage = ["google-cloud-bigquery-storage (>=2.16.2,<3.0.0dev)"] -tqdm = ["tqdm (>=4.23.0)"] - -[[package]] -name = "pandas-stubs" -version = "2.2.2.240909" -description = "Type annotations for pandas" -optional = false -python-versions = ">=3.10" -groups = ["dev"] -files = [ - {file = "pandas_stubs-2.2.2.240909-py3-none-any.whl", hash = "sha256:e230f5fa4065f9417804f4d65cd98f86c002efcc07933e8abcd48c3fad9c30a2"}, - {file = "pandas_stubs-2.2.2.240909.tar.gz", hash = "sha256:3c0951a2c3e45e3475aed9d80b7147ae82f176b9e42e9fb321cfdebf3d411b3d"}, -] - -[package.dependencies] -numpy = ">=1.23.5" -types-pytz = ">=2022.1.1" - -[[package]] -name = "passlib" -version = "1.7.4" -description = "comprehensive password hashing framework supporting over 30 schemes" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"}, - {file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"}, -] - -[package.extras] -argon2 = ["argon2-cffi (>=18.2.0)"] -bcrypt = ["bcrypt (>=3.1.0)"] -build-docs = ["cloud-sptheme (>=1.10.1)", "sphinx (>=1.6)", "sphinxcontrib-fulltoc (>=1.2.0)"] -totp = ["cryptography"] - -[[package]] -name = "pg8000" -version = "1.31.2" -description = "PostgreSQL interface library" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pg8000-1.31.2-py3-none-any.whl", hash = "sha256:436c771ede71af4d4c22ba867a30add0bc5c942d7ab27fadbb6934a487ecc8f6"}, - {file = "pg8000-1.31.2.tar.gz", hash = "sha256:1ea46cf09d8eca07fe7eaadefd7951e37bee7fabe675df164f1a572ffb300876"}, -] - -[package.dependencies] -python-dateutil = ">=2.8.2" -scramp = ">=1.4.5" - -[[package]] -name = "platformdirs" -version = "4.3.6" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, - {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.11.2)"] - -[[package]] -name = "pluggy" -version = "1.5.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "propcache" -version = "0.2.0" -description = "Accelerated property cache" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"}, - {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"}, - {file = "propcache-0.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:33ac8f098df0585c0b53009f039dfd913b38c1d2edafed0cedcc0c32a05aa110"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e48e8875e6c13909c800fa344cd54cc4b2b0db1d5f911f840458a500fde2c2"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388f3217649d6d59292b722d940d4d2e1e6a7003259eb835724092a1cca0203a"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f571aea50ba5623c308aa146eb650eebf7dbe0fd8c5d946e28343cb3b5aad577"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3dfafb44f7bb35c0c06eda6b2ab4bfd58f02729e7c4045e179f9a861b07c9850"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3ebe9a75be7ab0b7da2464a77bb27febcb4fab46a34f9288f39d74833db7f61"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d2f0d0f976985f85dfb5f3d685697ef769faa6b71993b46b295cdbbd6be8cc37"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a3dc1a4b165283bd865e8f8cb5f0c64c05001e0718ed06250d8cac9bec115b48"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e0f07b42d2a50c7dd2d8675d50f7343d998c64008f1da5fef888396b7f84630"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e63e3e1e0271f374ed489ff5ee73d4b6e7c60710e1f76af5f0e1a6117cd26394"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:56bb5c98f058a41bb58eead194b4db8c05b088c93d94d5161728515bd52b052b"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7665f04d0c7f26ff8bb534e1c65068409bf4687aa2534faf7104d7182debb336"}, - {file = "propcache-0.2.0-cp310-cp310-win32.whl", hash = "sha256:7cf18abf9764746b9c8704774d8b06714bcb0a63641518a3a89c7f85cc02c2ad"}, - {file = "propcache-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:cfac69017ef97db2438efb854edf24f5a29fd09a536ff3a992b75990720cdc99"}, - {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:63f13bf09cc3336eb04a837490b8f332e0db41da66995c9fd1ba04552e516354"}, - {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608cce1da6f2672a56b24a015b42db4ac612ee709f3d29f27a00c943d9e851de"}, - {file = "propcache-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:466c219deee4536fbc83c08d09115249db301550625c7fef1c5563a584c9bc87"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6ed8db0a556343d566a5c124ee483ae113acc9a557a807d439bcecc44e7dfbb"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91997d9cb4a325b60d4e3f20967f8eb08dfcb32b22554d5ef78e6fd1dda743a2"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c7dde9e533c0a49d802b4f3f218fa9ad0a1ce21f2c2eb80d5216565202acab4"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:97a58a28bcf63284e8b4d7b460cbee1edaab24634e82059c7b8c09e65284f178"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:945db8ee295d3af9dbdbb698cce9bbc5c59b5c3fe328bbc4387f59a8a35f998d"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39e104da444a34830751715f45ef9fc537475ba21b7f1f5b0f4d71a3b60d7fe2"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c5ecca8f9bab618340c8e848d340baf68bcd8ad90a8ecd7a4524a81c1764b3db"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c436130cc779806bdf5d5fae0d848713105472b8566b75ff70048c47d3961c5b"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:191db28dc6dcd29d1a3e063c3be0b40688ed76434622c53a284e5427565bbd9b"}, - {file = "propcache-0.2.0-cp311-cp311-win32.whl", hash = "sha256:5f2564ec89058ee7c7989a7b719115bdfe2a2fb8e7a4543b8d1c0cc4cf6478c1"}, - {file = "propcache-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e2e54267980349b723cff366d1e29b138b9a60fa376664a157a342689553f71"}, - {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2"}, - {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7"}, - {file = "propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348"}, - {file = "propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5"}, - {file = "propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3"}, - {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7"}, - {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763"}, - {file = "propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544"}, - {file = "propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032"}, - {file = "propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e"}, - {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:53d1bd3f979ed529f0805dd35ddaca330f80a9a6d90bc0121d2ff398f8ed8861"}, - {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:83928404adf8fb3d26793665633ea79b7361efa0287dfbd372a7e74311d51ee6"}, - {file = "propcache-0.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77a86c261679ea5f3896ec060be9dc8e365788248cc1e049632a1be682442063"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:218db2a3c297a3768c11a34812e63b3ac1c3234c3a086def9c0fee50d35add1f"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7735e82e3498c27bcb2d17cb65d62c14f1100b71723b68362872bca7d0913d90"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20a617c776f520c3875cf4511e0d1db847a076d720714ae35ffe0df3e440be68"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b69535c870670c9f9b14a75d28baa32221d06f6b6fa6f77a0a13c5a7b0a5b9"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4569158070180c3855e9c0791c56be3ceeb192defa2cdf6a3f39e54319e56b89"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:db47514ffdbd91ccdc7e6f8407aac4ee94cc871b15b577c1c324236b013ddd04"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:2a60ad3e2553a74168d275a0ef35e8c0a965448ffbc3b300ab3a5bb9956c2162"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:662dd62358bdeaca0aee5761de8727cfd6861432e3bb828dc2a693aa0471a563"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:25a1f88b471b3bc911d18b935ecb7115dff3a192b6fef46f0bfaf71ff4f12418"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:f60f0ac7005b9f5a6091009b09a419ace1610e163fa5deaba5ce3484341840e7"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:74acd6e291f885678631b7ebc85d2d4aec458dd849b8c841b57ef04047833bed"}, - {file = "propcache-0.2.0-cp38-cp38-win32.whl", hash = "sha256:d9b6ddac6408194e934002a69bcaadbc88c10b5f38fb9307779d1c629181815d"}, - {file = "propcache-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:676135dcf3262c9c5081cc8f19ad55c8a64e3f7282a21266d05544450bffc3a5"}, - {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:25c8d773a62ce0451b020c7b29a35cfbc05de8b291163a7a0f3b7904f27253e6"}, - {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:375a12d7556d462dc64d70475a9ee5982465fbb3d2b364f16b86ba9135793638"}, - {file = "propcache-0.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1ec43d76b9677637a89d6ab86e1fef70d739217fefa208c65352ecf0282be957"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45eec587dafd4b2d41ac189c2156461ebd0c1082d2fe7013571598abb8505d1"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc092ba439d91df90aea38168e11f75c655880c12782facf5cf9c00f3d42b562"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:682a7c79a2fbf40f5dbb1eb6bfe2cd865376deeac65acf9beb607505dced9e12"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e40876731f99b6f3c897b66b803c9e1c07a989b366c6b5b475fafd1f7ba3fb8"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:363ea8cd3c5cb6679f1c2f5f1f9669587361c062e4899fce56758efa928728f8"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:140fbf08ab3588b3468932974a9331aff43c0ab8a2ec2c608b6d7d1756dbb6cb"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e70fac33e8b4ac63dfc4c956fd7d85a0b1139adcfc0d964ce288b7c527537fea"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b33d7a286c0dc1a15f5fc864cc48ae92a846df287ceac2dd499926c3801054a6"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f6d5749fdd33d90e34c2efb174c7e236829147a2713334d708746e94c4bde40d"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22aa8f2272d81d9317ff5756bb108021a056805ce63dd3630e27d042c8092798"}, - {file = "propcache-0.2.0-cp39-cp39-win32.whl", hash = "sha256:73e4b40ea0eda421b115248d7e79b59214411109a5bc47d0d48e4c73e3b8fcf9"}, - {file = "propcache-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:9517d5e9e0731957468c29dbfd0f976736a0e55afaea843726e887f36fe017df"}, - {file = "propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036"}, - {file = "propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70"}, -] - -[[package]] -name = "proto-plus" -version = "1.24.0" -description = "Beautiful, Pythonic protocol buffers." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "proto-plus-1.24.0.tar.gz", hash = "sha256:30b72a5ecafe4406b0d339db35b56c4059064e69227b8c3bda7462397f966445"}, - {file = "proto_plus-1.24.0-py3-none-any.whl", hash = "sha256:402576830425e5f6ce4c2a6702400ac79897dab0b4343821aa5188b0fab81a12"}, -] - -[package.dependencies] -protobuf = ">=3.19.0,<6.0.0dev" - -[package.extras] -testing = ["google-api-core (>=1.31.5)"] - -[[package]] -name = "protobuf" -version = "4.25.5" -description = "" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "protobuf-4.25.5-cp310-abi3-win32.whl", hash = "sha256:5e61fd921603f58d2f5acb2806a929b4675f8874ff5f330b7d6f7e2e784bbcd8"}, - {file = "protobuf-4.25.5-cp310-abi3-win_amd64.whl", hash = "sha256:4be0571adcbe712b282a330c6e89eae24281344429ae95c6d85e79e84780f5ea"}, - {file = "protobuf-4.25.5-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:b2fde3d805354df675ea4c7c6338c1aecd254dfc9925e88c6d31a2bcb97eb173"}, - {file = "protobuf-4.25.5-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:919ad92d9b0310070f8356c24b855c98df2b8bd207ebc1c0c6fcc9ab1e007f3d"}, - {file = "protobuf-4.25.5-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:fe14e16c22be926d3abfcb500e60cab068baf10b542b8c858fa27e098123e331"}, - {file = "protobuf-4.25.5-cp38-cp38-win32.whl", hash = "sha256:98d8d8aa50de6a2747efd9cceba361c9034050ecce3e09136f90de37ddba66e1"}, - {file = "protobuf-4.25.5-cp38-cp38-win_amd64.whl", hash = "sha256:b0234dd5a03049e4ddd94b93400b67803c823cfc405689688f59b34e0742381a"}, - {file = "protobuf-4.25.5-cp39-cp39-win32.whl", hash = "sha256:abe32aad8561aa7cc94fc7ba4fdef646e576983edb94a73381b03c53728a626f"}, - {file = "protobuf-4.25.5-cp39-cp39-win_amd64.whl", hash = "sha256:7a183f592dc80aa7c8da7ad9e55091c4ffc9497b3054452d629bb85fa27c2a45"}, - {file = "protobuf-4.25.5-py3-none-any.whl", hash = "sha256:0aebecb809cae990f8129ada5ca273d9d670b76d9bfc9b1809f0a9c02b7dbf41"}, - {file = "protobuf-4.25.5.tar.gz", hash = "sha256:7f8249476b4a9473645db7f8ab42b02fe1488cbe5fb72fddd445e0665afd8584"}, -] - -[[package]] -name = "publicsuffix2" -version = "2.20191221" -description = "Get a public suffix for a domain name using the Public Suffix List. Forked from and using the same API as the publicsuffix package." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "publicsuffix2-2.20191221-py2.py3-none-any.whl", hash = "sha256:786b5e36205b88758bd3518725ec8cfe7a8173f5269354641f581c6b80a99893"}, - {file = "publicsuffix2-2.20191221.tar.gz", hash = "sha256:00f8cc31aa8d0d5592a5ced19cccba7de428ebca985db26ac852d920ddd6fe7b"}, -] - -[[package]] -name = "pyarrow" -version = "17.0.0" -description = "Python library for Apache Arrow" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pyarrow-17.0.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:a5c8b238d47e48812ee577ee20c9a2779e6a5904f1708ae240f53ecbee7c9f07"}, - {file = "pyarrow-17.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db023dc4c6cae1015de9e198d41250688383c3f9af8f565370ab2b4cb5f62655"}, - {file = "pyarrow-17.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da1e060b3876faa11cee287839f9cc7cdc00649f475714b8680a05fd9071d545"}, - {file = "pyarrow-17.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75c06d4624c0ad6674364bb46ef38c3132768139ddec1c56582dbac54f2663e2"}, - {file = "pyarrow-17.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:fa3c246cc58cb5a4a5cb407a18f193354ea47dd0648194e6265bd24177982fe8"}, - {file = "pyarrow-17.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:f7ae2de664e0b158d1607699a16a488de3d008ba99b3a7aa5de1cbc13574d047"}, - {file = "pyarrow-17.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:5984f416552eea15fd9cee03da53542bf4cddaef5afecefb9aa8d1010c335087"}, - {file = "pyarrow-17.0.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:1c8856e2ef09eb87ecf937104aacfa0708f22dfeb039c363ec99735190ffb977"}, - {file = "pyarrow-17.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e19f569567efcbbd42084e87f948778eb371d308e137a0f97afe19bb860ccb3"}, - {file = "pyarrow-17.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b244dc8e08a23b3e352899a006a26ae7b4d0da7bb636872fa8f5884e70acf15"}, - {file = "pyarrow-17.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b72e87fe3e1db343995562f7fff8aee354b55ee83d13afba65400c178ab2597"}, - {file = "pyarrow-17.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:dc5c31c37409dfbc5d014047817cb4ccd8c1ea25d19576acf1a001fe07f5b420"}, - {file = "pyarrow-17.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:e3343cb1e88bc2ea605986d4b94948716edc7a8d14afd4e2c097232f729758b4"}, - {file = "pyarrow-17.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:a27532c38f3de9eb3e90ecab63dfda948a8ca859a66e3a47f5f42d1e403c4d03"}, - {file = "pyarrow-17.0.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:9b8a823cea605221e61f34859dcc03207e52e409ccf6354634143e23af7c8d22"}, - {file = "pyarrow-17.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f1e70de6cb5790a50b01d2b686d54aaf73da01266850b05e3af2a1bc89e16053"}, - {file = "pyarrow-17.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0071ce35788c6f9077ff9ecba4858108eebe2ea5a3f7cf2cf55ebc1dbc6ee24a"}, - {file = "pyarrow-17.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:757074882f844411fcca735e39aae74248a1531367a7c80799b4266390ae51cc"}, - {file = "pyarrow-17.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:9ba11c4f16976e89146781a83833df7f82077cdab7dc6232c897789343f7891a"}, - {file = "pyarrow-17.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b0c6ac301093b42d34410b187bba560b17c0330f64907bfa4f7f7f2444b0cf9b"}, - {file = "pyarrow-17.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:392bc9feabc647338e6c89267635e111d71edad5fcffba204425a7c8d13610d7"}, - {file = "pyarrow-17.0.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:af5ff82a04b2171415f1410cff7ebb79861afc5dae50be73ce06d6e870615204"}, - {file = "pyarrow-17.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:edca18eaca89cd6382dfbcff3dd2d87633433043650c07375d095cd3517561d8"}, - {file = "pyarrow-17.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c7916bff914ac5d4a8fe25b7a25e432ff921e72f6f2b7547d1e325c1ad9d155"}, - {file = "pyarrow-17.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f553ca691b9e94b202ff741bdd40f6ccb70cdd5fbf65c187af132f1317de6145"}, - {file = "pyarrow-17.0.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:0cdb0e627c86c373205a2f94a510ac4376fdc523f8bb36beab2e7f204416163c"}, - {file = "pyarrow-17.0.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:d7d192305d9d8bc9082d10f361fc70a73590a4c65cf31c3e6926cd72b76bc35c"}, - {file = "pyarrow-17.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:02dae06ce212d8b3244dd3e7d12d9c4d3046945a5933d28026598e9dbbda1fca"}, - {file = "pyarrow-17.0.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:13d7a460b412f31e4c0efa1148e1d29bdf18ad1411eb6757d38f8fbdcc8645fb"}, - {file = "pyarrow-17.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9b564a51fbccfab5a04a80453e5ac6c9954a9c5ef2890d1bcf63741909c3f8df"}, - {file = "pyarrow-17.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32503827abbc5aadedfa235f5ece8c4f8f8b0a3cf01066bc8d29de7539532687"}, - {file = "pyarrow-17.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a155acc7f154b9ffcc85497509bcd0d43efb80d6f733b0dc3bb14e281f131c8b"}, - {file = "pyarrow-17.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:dec8d129254d0188a49f8a1fc99e0560dc1b85f60af729f47de4046015f9b0a5"}, - {file = "pyarrow-17.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:a48ddf5c3c6a6c505904545c25a4ae13646ae1f8ba703c4df4a1bfe4f4006bda"}, - {file = "pyarrow-17.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:42bf93249a083aca230ba7e2786c5f673507fa97bbd9725a1e2754715151a204"}, - {file = "pyarrow-17.0.0.tar.gz", hash = "sha256:4beca9521ed2c0921c1023e68d097d0299b62c362639ea315572a58f3f50fd28"}, -] - -[package.dependencies] -numpy = ">=1.16.6" - -[package.extras] -test = ["cffi", "hypothesis", "pandas", "pytest", "pytz"] - -[[package]] -name = "pyasn1" -version = "0.6.1" -description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"}, - {file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"}, -] - -[[package]] -name = "pyasn1-modules" -version = "0.4.1" -description = "A collection of ASN.1-based protocols modules" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd"}, - {file = "pyasn1_modules-0.4.1.tar.gz", hash = "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c"}, -] - -[package.dependencies] -pyasn1 = ">=0.4.6,<0.7.0" - -[[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, -] - -[[package]] -name = "pydantic" -version = "1.10.18" -description = "Data validation and settings management using python type hints" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "pydantic-1.10.18-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e405ffcc1254d76bb0e760db101ee8916b620893e6edfbfee563b3c6f7a67c02"}, - {file = "pydantic-1.10.18-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e306e280ebebc65040034bff1a0a81fd86b2f4f05daac0131f29541cafd80b80"}, - {file = "pydantic-1.10.18-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11d9d9b87b50338b1b7de4ebf34fd29fdb0d219dc07ade29effc74d3d2609c62"}, - {file = "pydantic-1.10.18-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b661ce52c7b5e5f600c0c3c5839e71918346af2ef20062705ae76b5c16914cab"}, - {file = "pydantic-1.10.18-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c20f682defc9ef81cd7eaa485879ab29a86a0ba58acf669a78ed868e72bb89e0"}, - {file = "pydantic-1.10.18-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c5ae6b7c8483b1e0bf59e5f1843e4fd8fd405e11df7de217ee65b98eb5462861"}, - {file = "pydantic-1.10.18-cp310-cp310-win_amd64.whl", hash = "sha256:74fe19dda960b193b0eb82c1f4d2c8e5e26918d9cda858cbf3f41dd28549cb70"}, - {file = "pydantic-1.10.18-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:72fa46abace0a7743cc697dbb830a41ee84c9db8456e8d77a46d79b537efd7ec"}, - {file = "pydantic-1.10.18-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ef0fe7ad7cbdb5f372463d42e6ed4ca9c443a52ce544472d8842a0576d830da5"}, - {file = "pydantic-1.10.18-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a00e63104346145389b8e8f500bc6a241e729feaf0559b88b8aa513dd2065481"}, - {file = "pydantic-1.10.18-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae6fa2008e1443c46b7b3a5eb03800121868d5ab6bc7cda20b5df3e133cde8b3"}, - {file = "pydantic-1.10.18-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9f463abafdc92635da4b38807f5b9972276be7c8c5121989768549fceb8d2588"}, - {file = "pydantic-1.10.18-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3445426da503c7e40baccefb2b2989a0c5ce6b163679dd75f55493b460f05a8f"}, - {file = "pydantic-1.10.18-cp311-cp311-win_amd64.whl", hash = "sha256:467a14ee2183bc9c902579bb2f04c3d3dac00eff52e252850509a562255b2a33"}, - {file = "pydantic-1.10.18-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:efbc8a7f9cb5fe26122acba1852d8dcd1e125e723727c59dcd244da7bdaa54f2"}, - {file = "pydantic-1.10.18-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:24a4a159d0f7a8e26bf6463b0d3d60871d6a52eac5bb6a07a7df85c806f4c048"}, - {file = "pydantic-1.10.18-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b74be007703547dc52e3c37344d130a7bfacca7df112a9e5ceeb840a9ce195c7"}, - {file = "pydantic-1.10.18-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcb20d4cb355195c75000a49bb4a31d75e4295200df620f454bbc6bdf60ca890"}, - {file = "pydantic-1.10.18-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:46f379b8cb8a3585e3f61bf9ae7d606c70d133943f339d38b76e041ec234953f"}, - {file = "pydantic-1.10.18-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cbfbca662ed3729204090c4d09ee4beeecc1a7ecba5a159a94b5a4eb24e3759a"}, - {file = "pydantic-1.10.18-cp312-cp312-win_amd64.whl", hash = "sha256:c6d0a9f9eccaf7f438671a64acf654ef0d045466e63f9f68a579e2383b63f357"}, - {file = "pydantic-1.10.18-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3d5492dbf953d7d849751917e3b2433fb26010d977aa7a0765c37425a4026ff1"}, - {file = "pydantic-1.10.18-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe734914977eed33033b70bfc097e1baaffb589517863955430bf2e0846ac30f"}, - {file = "pydantic-1.10.18-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15fdbe568beaca9aacfccd5ceadfb5f1a235087a127e8af5e48df9d8a45ae85c"}, - {file = "pydantic-1.10.18-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c3e742f62198c9eb9201781fbebe64533a3bbf6a76a91b8d438d62b813079dbc"}, - {file = "pydantic-1.10.18-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:19a3bd00b9dafc2cd7250d94d5b578edf7a0bd7daf102617153ff9a8fa37871c"}, - {file = "pydantic-1.10.18-cp37-cp37m-win_amd64.whl", hash = "sha256:2ce3fcf75b2bae99aa31bd4968de0474ebe8c8258a0110903478bd83dfee4e3b"}, - {file = "pydantic-1.10.18-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:335a32d72c51a313b33fa3a9b0fe283503272ef6467910338e123f90925f0f03"}, - {file = "pydantic-1.10.18-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:34a3613c7edb8c6fa578e58e9abe3c0f5e7430e0fc34a65a415a1683b9c32d9a"}, - {file = "pydantic-1.10.18-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9ee4e6ca1d9616797fa2e9c0bfb8815912c7d67aca96f77428e316741082a1b"}, - {file = "pydantic-1.10.18-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23e8ec1ce4e57b4f441fc91e3c12adba023fedd06868445a5b5f1d48f0ab3682"}, - {file = "pydantic-1.10.18-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:44ae8a3e35a54d2e8fa88ed65e1b08967a9ef8c320819a969bfa09ce5528fafe"}, - {file = "pydantic-1.10.18-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5389eb3b48a72da28c6e061a247ab224381435256eb541e175798483368fdd3"}, - {file = "pydantic-1.10.18-cp38-cp38-win_amd64.whl", hash = "sha256:069b9c9fc645474d5ea3653788b544a9e0ccd3dca3ad8c900c4c6eac844b4620"}, - {file = "pydantic-1.10.18-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:80b982d42515632eb51f60fa1d217dfe0729f008e81a82d1544cc392e0a50ddf"}, - {file = "pydantic-1.10.18-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:aad8771ec8dbf9139b01b56f66386537c6fe4e76c8f7a47c10261b69ad25c2c9"}, - {file = "pydantic-1.10.18-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941a2eb0a1509bd7f31e355912eb33b698eb0051730b2eaf9e70e2e1589cae1d"}, - {file = "pydantic-1.10.18-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65f7361a09b07915a98efd17fdec23103307a54db2000bb92095457ca758d485"}, - {file = "pydantic-1.10.18-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6951f3f47cb5ca4da536ab161ac0163cab31417d20c54c6de5ddcab8bc813c3f"}, - {file = "pydantic-1.10.18-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7a4c5eec138a9b52c67f664c7d51d4c7234c5ad65dd8aacd919fb47445a62c86"}, - {file = "pydantic-1.10.18-cp39-cp39-win_amd64.whl", hash = "sha256:49e26c51ca854286bffc22b69787a8d4063a62bf7d83dc21d44d2ff426108518"}, - {file = "pydantic-1.10.18-py3-none-any.whl", hash = "sha256:06a189b81ffc52746ec9c8c007f16e5167c8b0a696e1a726369327e3db7b2a82"}, - {file = "pydantic-1.10.18.tar.gz", hash = "sha256:baebdff1907d1d96a139c25136a9bb7d17e118f133a76a2ef3b845e831e3403a"}, -] - -[package.dependencies] -typing-extensions = ">=4.2.0" - -[package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] - -[[package]] -name = "pydash" -version = "7.0.7" -description = "The kitchen sink of Python utility libraries for doing \"stuff\" in a functional way. Based on the Lo-Dash Javascript library." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pydash-7.0.7-py3-none-any.whl", hash = "sha256:c3c5b54eec0a562e0080d6f82a14ad4d5090229847b7e554235b5c1558c745e1"}, - {file = "pydash-7.0.7.tar.gz", hash = "sha256:cc935d5ac72dd41fb4515bdf982e7c864c8b5eeea16caffbab1936b849aaa49a"}, -] - -[package.dependencies] -typing-extensions = ">=3.10,<4.6.0 || >4.6.0" - -[package.extras] -dev = ["black", "build", "coverage", "docformatter", "flake8", "flake8-black", "flake8-bugbear", "flake8-isort", "furo", "invoke", "isort", "mypy", "pylint", "pytest", "pytest-cov", "pytest-mypy-testing", "sphinx", "sphinx-autodoc-typehints", "tox", "twine", "wheel"] - -[[package]] -name = "pydata-google-auth" -version = "1.8.2" -description = "PyData helpers for authenticating to Google APIs" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "pydata-google-auth-1.8.2.tar.gz", hash = "sha256:547b6c0fbea657dcecd50887c5db8640ebec062a59a2b88e8ff8e53a04818303"}, - {file = "pydata_google_auth-1.8.2-py2.py3-none-any.whl", hash = "sha256:a9dce59af4a170ea60c4b2ebbc83ee1f74d34255a4f97b2469ae9a4a0dc98e99"}, -] - -[package.dependencies] -google-auth = {version = ">=1.25.0,<3.0dev", markers = "python_version >= \"3.6\""} -google-auth-oauthlib = {version = ">=0.4.0", markers = "python_version >= \"3.6\""} -setuptools = "*" - -[[package]] -name = "pydivert" -version = "2.1.0" -description = "Python binding to windivert driver" -optional = false -python-versions = "*" -groups = ["main"] -markers = "sys_platform == \"win32\"" -files = [ - {file = "pydivert-2.1.0-py2.py3-none-any.whl", hash = "sha256:382db488e3c37c03ec9ec94e061a0b24334d78dbaeebb7d4e4d32ce4355d9da1"}, - {file = "pydivert-2.1.0.tar.gz", hash = "sha256:f0e150f4ff591b78e35f514e319561dadff7f24a82186a171dd4d465483de5b4"}, -] - -[package.extras] -docs = ["sphinx (>=1.4.8)"] -test = ["codecov (>=2.0.5)", "hypothesis (>=3.5.3)", "mock (>=1.0.1)", "pytest (>=3.0.3)", "pytest-cov (>=2.2.1)", "pytest-faulthandler (>=1.3.0,<2)", "pytest-timeout (>=1.0.0,<2)", "wheel (>=0.29)"] - -[[package]] -name = "pygments" -version = "2.18.0" -description = "Pygments is a syntax highlighting package written in Python." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, - {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, -] - -[package.extras] -windows-terminal = ["colorama (>=0.4.6)"] - -[[package]] -name = "pyjwt" -version = "2.9.0" -description = "JSON Web Token implementation in Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850"}, - {file = "pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"}, -] - -[package.extras] -crypto = ["cryptography (>=3.4.0)"] -dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"] -docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] - -[[package]] -name = "pylsqpack" -version = "0.3.18" -description = "Python wrapper for the ls-qpack QPACK library" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pylsqpack-0.3.18-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:1f415d2e03c779261ac7ed421a009a4c752eef6f1ef7b5a34c4a463a5e17fbad"}, - {file = "pylsqpack-0.3.18-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c84e6d4dcb708d766a50bfd16579d8a0bff4eb4e5f5dff9f3df4018454d4013b"}, - {file = "pylsqpack-0.3.18-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bac5f2dc255ae70e5a14033e769769b38bd4c980b365dacd88665610f245e36f"}, - {file = "pylsqpack-0.3.18-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75042b442a0a7a283b5adc21045e6583f3c817d40ccec769837bf2f90b79c494"}, - {file = "pylsqpack-0.3.18-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8b5fd04bb27180286811f8e1659974e6e5e854a882de3f2aba8caefc1bb9ab81"}, - {file = "pylsqpack-0.3.18-cp38-abi3-win32.whl", hash = "sha256:a2798e1c08bd36875f77a1ebec0f130fdf9e27eebdb0499a764201d55ef78770"}, - {file = "pylsqpack-0.3.18-cp38-abi3-win_amd64.whl", hash = "sha256:40465d025b946bca195bdaed74b3b79fe3f7f419ab1d4bc4109dca34ba9881d7"}, - {file = "pylsqpack-0.3.18-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ae628cd359ecb466dd85f151ea1ad53de3114e5a9ae0f0ac1408fb43a4318032"}, - {file = "pylsqpack-0.3.18-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a248be29d9ca1fa2ebd7ef4b8ac166d17df0d8d4631b4499c8c566e221d4e5b"}, - {file = "pylsqpack-0.3.18-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:005ddce84bdcbf5c3cf99f764504208e1aa0a91a8331bf47108f2708f2a315e6"}, - {file = "pylsqpack-0.3.18-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3dd664354422d4cd51c189febb5f5d22bf3d8c453cc25517c04ce01a57478060"}, - {file = "pylsqpack-0.3.18-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:c003eb882f41e4dbd093243c67b97c8634209b4d5ba7edd16163b1ff37306254"}, - {file = "pylsqpack-0.3.18-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8ea75152e8cb8b8c7cfef11c3aa5ebe5b226bd850889f56ff70a688e9680acbf"}, - {file = "pylsqpack-0.3.18-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c4cccfd91afd589994f844fd1dbae0acdb58a8ab929d8edeadb25339deb6590"}, - {file = "pylsqpack-0.3.18-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06e1bbe47514b83cd03158e5558ef8cc44f578169c1820098be9f3cc4137f16a"}, - {file = "pylsqpack-0.3.18-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1054b0b44f6141a99e84a9aa6a27c9df028e9223747b893e8e37cdc95b602f1"}, - {file = "pylsqpack-0.3.18-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:711f3aa645f72a928e22606c1f026cde905de23efc07028fe1bc7429f73ec8ee"}, - {file = "pylsqpack-0.3.18.tar.gz", hash = "sha256:45ae55e721877505f4d5ccd49591d69353f2a548a8673dfafb251d385b3c097f"}, -] - -[[package]] -name = "pyopenssl" -version = "24.1.0" -description = "Python wrapper module around the OpenSSL library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "pyOpenSSL-24.1.0-py3-none-any.whl", hash = "sha256:17ed5be5936449c5418d1cd269a1a9e9081bc54c17aed272b45856a3d3dc86ad"}, - {file = "pyOpenSSL-24.1.0.tar.gz", hash = "sha256:cabed4bfaa5df9f1a16c0ef64a0cb65318b5cd077a7eda7d6970131ca2f41a6f"}, -] - -[package.dependencies] -cryptography = ">=41.0.5,<43" - -[package.extras] -docs = ["sphinx (!=5.2.0,!=5.2.0.post0,!=7.2.5)", "sphinx-rtd-theme"] -test = ["pretend", "pytest (>=3.0.1)", "pytest-rerunfailures"] - -[[package]] -name = "pyparsing" -version = "3.1.4" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -optional = false -python-versions = ">=3.6.8" -groups = ["main"] -files = [ - {file = "pyparsing-3.1.4-py3-none-any.whl", hash = "sha256:a6a7ee4235a3f944aa1fa2249307708f893fe5717dc603503c6c7969c070fb7c"}, - {file = "pyparsing-3.1.4.tar.gz", hash = "sha256:f86ec8d1a83f11977c9a6ea7598e8c27fc5cddfa5b07ea2241edbbde1d7bc032"}, -] - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - -[[package]] -name = "pyperclip" -version = "1.8.2" -description = "A cross-platform clipboard module for Python. (Only handles plain text for now.)" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "pyperclip-1.8.2.tar.gz", hash = "sha256:105254a8b04934f0bc84e9c24eb360a591aaf6535c9def5f29d92af107a9bf57"}, -] - -[[package]] -name = "pyrsistent" -version = "0.20.0" -description = "Persistent/Functional/Immutable data structures" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pyrsistent-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c3aba3e01235221e5b229a6c05f585f344734bd1ad42a8ac51493d74722bbce"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1beb78af5423b879edaf23c5591ff292cf7c33979734c99aa66d5914ead880f"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21cc459636983764e692b9eba7144cdd54fdec23ccdb1e8ba392a63666c60c34"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5ac696f02b3fc01a710427585c855f65cd9c640e14f52abe52020722bb4906b"}, - {file = "pyrsistent-0.20.0-cp310-cp310-win32.whl", hash = "sha256:0724c506cd8b63c69c7f883cc233aac948c1ea946ea95996ad8b1380c25e1d3f"}, - {file = "pyrsistent-0.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:8441cf9616d642c475684d6cf2520dd24812e996ba9af15e606df5f6fd9d04a7"}, - {file = "pyrsistent-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0f3b1bcaa1f0629c978b355a7c37acd58907390149b7311b5db1b37648eb6958"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cdd7ef1ea7a491ae70d826b6cc64868de09a1d5ff9ef8d574250d0940e275b8"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cae40a9e3ce178415040a0383f00e8d68b569e97f31928a3a8ad37e3fde6df6a"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6288b3fa6622ad8a91e6eb759cfc48ff3089e7c17fb1d4c59a919769314af224"}, - {file = "pyrsistent-0.20.0-cp311-cp311-win32.whl", hash = "sha256:7d29c23bdf6e5438c755b941cef867ec2a4a172ceb9f50553b6ed70d50dfd656"}, - {file = "pyrsistent-0.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:59a89bccd615551391f3237e00006a26bcf98a4d18623a19909a2c48b8e986ee"}, - {file = "pyrsistent-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:09848306523a3aba463c4b49493a760e7a6ca52e4826aa100ee99d8d39b7ad1e"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a14798c3005ec892bbada26485c2eea3b54109cb2533713e355c806891f63c5e"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b14decb628fac50db5e02ee5a35a9c0772d20277824cfe845c8a8b717c15daa3"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e2c116cc804d9b09ce9814d17df5edf1df0c624aba3b43bc1ad90411487036d"}, - {file = "pyrsistent-0.20.0-cp312-cp312-win32.whl", hash = "sha256:e78d0c7c1e99a4a45c99143900ea0546025e41bb59ebc10182e947cf1ece9174"}, - {file = "pyrsistent-0.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:4021a7f963d88ccd15b523787d18ed5e5269ce57aa4037146a2377ff607ae87d"}, - {file = "pyrsistent-0.20.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:79ed12ba79935adaac1664fd7e0e585a22caa539dfc9b7c7c6d5ebf91fb89054"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f920385a11207dc372a028b3f1e1038bb244b3ec38d448e6d8e43c6b3ba20e98"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f5c2d012671b7391803263419e31b5c7c21e7c95c8760d7fc35602353dee714"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef3992833fbd686ee783590639f4b8343a57f1f75de8633749d984dc0eb16c86"}, - {file = "pyrsistent-0.20.0-cp38-cp38-win32.whl", hash = "sha256:881bbea27bbd32d37eb24dd320a5e745a2a5b092a17f6debc1349252fac85423"}, - {file = "pyrsistent-0.20.0-cp38-cp38-win_amd64.whl", hash = "sha256:6d270ec9dd33cdb13f4d62c95c1a5a50e6b7cdd86302b494217137f760495b9d"}, - {file = "pyrsistent-0.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ca52d1ceae015859d16aded12584c59eb3825f7b50c6cfd621d4231a6cc624ce"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b318ca24db0f0518630e8b6f3831e9cba78f099ed5c1d65ffe3e023003043ba0"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed2c3216a605dc9a6ea50c7e84c82906e3684c4e80d2908208f662a6cbf9022"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e14c95c16211d166f59c6611533d0dacce2e25de0f76e4c140fde250997b3ca"}, - {file = "pyrsistent-0.20.0-cp39-cp39-win32.whl", hash = "sha256:f058a615031eea4ef94ead6456f5ec2026c19fb5bd6bfe86e9665c4158cf802f"}, - {file = "pyrsistent-0.20.0-cp39-cp39-win_amd64.whl", hash = "sha256:58b8f6366e152092194ae68fefe18b9f0b4f89227dfd86a07770c3d86097aebf"}, - {file = "pyrsistent-0.20.0-py3-none-any.whl", hash = "sha256:c55acc4733aad6560a7f5f818466631f07efc001fd023f34a6c203f8b6df0f0b"}, - {file = "pyrsistent-0.20.0.tar.gz", hash = "sha256:4c48f78f62ab596c679086084d0dd13254ae4f3d6c72a83ffdf5ebdef8f265a4"}, -] - -[[package]] -name = "pytest" -version = "8.3.3" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, - {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=1.5,<2" - -[package.extras] -dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "pytest-asyncio" -version = "0.23.8" -description = "Pytest support for asyncio" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pytest_asyncio-0.23.8-py3-none-any.whl", hash = "sha256:50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2"}, - {file = "pytest_asyncio-0.23.8.tar.gz", hash = "sha256:759b10b33a6dc61cce40a8bd5205e302978bbbcc00e279a8b61d9a6a3c82e4d3"}, -] - -[package.dependencies] -pytest = ">=7.0.0,<9" - -[package.extras] -docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] -testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] - -[[package]] -name = "pytest-sugar" -version = "1.0.0" -description = "pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly)." -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "pytest-sugar-1.0.0.tar.gz", hash = "sha256:6422e83258f5b0c04ce7c632176c7732cab5fdb909cb39cca5c9139f81276c0a"}, - {file = "pytest_sugar-1.0.0-py3-none-any.whl", hash = "sha256:70ebcd8fc5795dc457ff8b69d266a4e2e8a74ae0c3edc749381c64b5246c8dfd"}, -] - -[package.dependencies] -packaging = ">=21.3" -pytest = ">=6.2.0" -termcolor = ">=2.1.0" - -[package.extras] -dev = ["black", "flake8", "pre-commit"] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main"] -files = [ - {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, - {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "python-dotenv" -version = "1.0.1" -description = "Read key-value pairs from a .env file and set them as environment variables" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, - {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, -] - -[package.extras] -cli = ["click (>=5.0)"] - -[[package]] -name = "python-slugify" -version = "8.0.4" -description = "A Python slugify application that also handles Unicode" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856"}, - {file = "python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8"}, -] - -[package.dependencies] -text-unidecode = ">=1.3" - -[package.extras] -unidecode = ["Unidecode (>=1.1.1)"] - -[[package]] -name = "pytz" -version = "2024.1" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, - {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, -] - -[[package]] -name = "pywin32" -version = "307" -description = "Python for Window Extensions" -optional = false -python-versions = "*" -groups = ["main"] -markers = "sys_platform == \"win32\"" -files = [ - {file = "pywin32-307-cp310-cp310-win32.whl", hash = "sha256:f8f25d893c1e1ce2d685ef6d0a481e87c6f510d0f3f117932781f412e0eba31b"}, - {file = "pywin32-307-cp310-cp310-win_amd64.whl", hash = "sha256:36e650c5e5e6b29b5d317385b02d20803ddbac5d1031e1f88d20d76676dd103d"}, - {file = "pywin32-307-cp310-cp310-win_arm64.whl", hash = "sha256:0c12d61e0274e0c62acee79e3e503c312426ddd0e8d4899c626cddc1cafe0ff4"}, - {file = "pywin32-307-cp311-cp311-win32.whl", hash = "sha256:fec5d27cc893178fab299de911b8e4d12c5954e1baf83e8a664311e56a272b75"}, - {file = "pywin32-307-cp311-cp311-win_amd64.whl", hash = "sha256:987a86971753ed7fdd52a7fb5747aba955b2c7fbbc3d8b76ec850358c1cc28c3"}, - {file = "pywin32-307-cp311-cp311-win_arm64.whl", hash = "sha256:fd436897c186a2e693cd0437386ed79f989f4d13d6f353f8787ecbb0ae719398"}, - {file = "pywin32-307-cp312-cp312-win32.whl", hash = "sha256:07649ec6b01712f36debf39fc94f3d696a46579e852f60157a729ac039df0815"}, - {file = "pywin32-307-cp312-cp312-win_amd64.whl", hash = "sha256:00d047992bb5dcf79f8b9b7c81f72e0130f9fe4b22df613f755ab1cc021d8347"}, - {file = "pywin32-307-cp312-cp312-win_arm64.whl", hash = "sha256:b53658acbfc6a8241d72cc09e9d1d666be4e6c99376bc59e26cdb6223c4554d2"}, - {file = "pywin32-307-cp313-cp313-win32.whl", hash = "sha256:ea4d56e48dc1ab2aa0a5e3c0741ad6e926529510516db7a3b6981a1ae74405e5"}, - {file = "pywin32-307-cp313-cp313-win_amd64.whl", hash = "sha256:576d09813eaf4c8168d0bfd66fb7cb3b15a61041cf41598c2db4a4583bf832d2"}, - {file = "pywin32-307-cp313-cp313-win_arm64.whl", hash = "sha256:b30c9bdbffda6a260beb2919f918daced23d32c79109412c2085cbc513338a0a"}, - {file = "pywin32-307-cp37-cp37m-win32.whl", hash = "sha256:5101472f5180c647d4525a0ed289ec723a26231550dbfd369ec19d5faf60e511"}, - {file = "pywin32-307-cp37-cp37m-win_amd64.whl", hash = "sha256:05de55a7c110478dc4b202230e98af5e0720855360d2b31a44bb4e296d795fba"}, - {file = "pywin32-307-cp38-cp38-win32.whl", hash = "sha256:13d059fb7f10792542082f5731d5d3d9645320fc38814759313e5ee97c3fac01"}, - {file = "pywin32-307-cp38-cp38-win_amd64.whl", hash = "sha256:7e0b2f93769d450a98ac7a31a087e07b126b6d571e8b4386a5762eb85325270b"}, - {file = "pywin32-307-cp39-cp39-win32.whl", hash = "sha256:55ee87f2f8c294e72ad9d4261ca423022310a6e79fb314a8ca76ab3f493854c6"}, - {file = "pywin32-307-cp39-cp39-win_amd64.whl", hash = "sha256:e9d5202922e74985b037c9ef46778335c102b74b95cec70f629453dbe7235d87"}, -] - -[[package]] -name = "pyyaml" -version = "6.0.2" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, - {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, - {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, - {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, - {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, - {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, - {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, - {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, - {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, - {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, - {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, - {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, - {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, - {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, - {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, - {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, - {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, -] - -[[package]] -name = "readchar" -version = "4.2.0" -description = "Library to easily read single chars and key strokes" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "readchar-4.2.0-py3-none-any.whl", hash = "sha256:2a587a27c981e6d25a518730ad4c88c429c315439baa6fda55d7a8b3ac4cb62a"}, - {file = "readchar-4.2.0.tar.gz", hash = "sha256:44807cbbe377b72079fea6cba8aa91c809982d7d727b2f0dbb2d1a8084914faa"}, -] - -[[package]] -name = "requests" -version = "2.31.0" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "requests-oauthlib" -version = "2.0.0" -description = "OAuthlib authentication support for Requests." -optional = false -python-versions = ">=3.4" -groups = ["main"] -files = [ - {file = "requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9"}, - {file = "requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36"}, -] - -[package.dependencies] -oauthlib = ">=3.0.0" -requests = ">=2.0.0" - -[package.extras] -rsa = ["oauthlib[signedtoken] (>=3.0.0)"] - -[[package]] -name = "rich" -version = "13.9.2" -description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -optional = false -python-versions = ">=3.8.0" -groups = ["main"] -files = [ - {file = "rich-13.9.2-py3-none-any.whl", hash = "sha256:8c82a3d3f8dcfe9e734771313e606b39d8247bb6b826e196f4914b333b743cf1"}, - {file = "rich-13.9.2.tar.gz", hash = "sha256:51a2c62057461aaf7152b4d611168f93a9fc73068f8ded2790f29fe2b5366d0c"}, -] - -[package.dependencies] -markdown-it-py = ">=2.2.0" -pygments = ">=2.13.0,<3.0.0" - -[package.extras] -jupyter = ["ipywidgets (>=7.5.1,<9)"] - -[[package]] -name = "rsa" -version = "4.9" -description = "Pure-Python RSA implementation" -optional = false -python-versions = ">=3.6,<4" -groups = ["main"] -files = [ - {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, - {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, -] - -[package.dependencies] -pyasn1 = ">=0.1.3" - -[[package]] -name = "ruamel-yaml" -version = "0.18.6" -description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "ruamel.yaml-0.18.6-py3-none-any.whl", hash = "sha256:57b53ba33def16c4f3d807c0ccbc00f8a6081827e81ba2491691b76882d0c636"}, - {file = "ruamel.yaml-0.18.6.tar.gz", hash = "sha256:8b27e6a217e786c6fbe5634d8f3f11bc63e0f80f6a5890f28863d9c45aac311b"}, -] - -[package.dependencies] -"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.13\""} - -[package.extras] -docs = ["mercurial (>5.7)", "ryd"] -jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] - -[[package]] -name = "ruamel-yaml-clib" -version = "0.2.8" -description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" -optional = false -python-versions = ">=3.6" -groups = ["main"] -markers = "platform_python_implementation == \"CPython\"" -files = [ - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win32.whl", hash = "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_24_aarch64.whl", hash = "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win32.whl", hash = "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win_amd64.whl", hash = "sha256:1758ce7d8e1a29d23de54a16ae867abd370f01b5a69e1a3ba75223eaa3ca1a1b"}, - {file = "ruamel.yaml.clib-0.2.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:77159f5d5b5c14f7c34073862a6b7d34944075d9f93e681638f6d753606c6ce6"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4ecbf9c3e19f9562c7fdd462e8d18dd902a47ca046a2e64dba80699f0b6c09b7"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:87ea5ff66d8064301a154b3933ae406b0863402a799b16e4a1d24d9fbbcbe0d3"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win32.whl", hash = "sha256:75e1ed13e1f9de23c5607fe6bd1aeaae21e523b32d83bb33918245361e9cc51b"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win32.whl", hash = "sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win_amd64.whl", hash = "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win32.whl", hash = "sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win_amd64.whl", hash = "sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15"}, - {file = "ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512"}, -] - -[[package]] -name = "ruff" -version = "0.6.9" -description = "An extremely fast Python linter and code formatter, written in Rust." -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "ruff-0.6.9-py3-none-linux_armv6l.whl", hash = "sha256:064df58d84ccc0ac0fcd63bc3090b251d90e2a372558c0f057c3f75ed73e1ccd"}, - {file = "ruff-0.6.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:140d4b5c9f5fc7a7b074908a78ab8d384dd7f6510402267bc76c37195c02a7ec"}, - {file = "ruff-0.6.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:53fd8ca5e82bdee8da7f506d7b03a261f24cd43d090ea9db9a1dc59d9313914c"}, - {file = "ruff-0.6.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645d7d8761f915e48a00d4ecc3686969761df69fb561dd914a773c1a8266e14e"}, - {file = "ruff-0.6.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eae02b700763e3847595b9d2891488989cac00214da7f845f4bcf2989007d577"}, - {file = "ruff-0.6.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d5ccc9e58112441de8ad4b29dcb7a86dc25c5f770e3c06a9d57e0e5eba48829"}, - {file = "ruff-0.6.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:417b81aa1c9b60b2f8edc463c58363075412866ae4e2b9ab0f690dc1e87ac1b5"}, - {file = "ruff-0.6.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c866b631f5fbce896a74a6e4383407ba7507b815ccc52bcedabb6810fdb3ef7"}, - {file = "ruff-0.6.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b118afbb3202f5911486ad52da86d1d52305b59e7ef2031cea3425142b97d6f"}, - {file = "ruff-0.6.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a67267654edc23c97335586774790cde402fb6bbdb3c2314f1fc087dee320bfa"}, - {file = "ruff-0.6.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3ef0cc774b00fec123f635ce5c547dac263f6ee9fb9cc83437c5904183b55ceb"}, - {file = "ruff-0.6.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:12edd2af0c60fa61ff31cefb90aef4288ac4d372b4962c2864aeea3a1a2460c0"}, - {file = "ruff-0.6.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:55bb01caeaf3a60b2b2bba07308a02fca6ab56233302406ed5245180a05c5625"}, - {file = "ruff-0.6.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:925d26471fa24b0ce5a6cdfab1bb526fb4159952385f386bdcc643813d472039"}, - {file = "ruff-0.6.9-py3-none-win32.whl", hash = "sha256:eb61ec9bdb2506cffd492e05ac40e5bc6284873aceb605503d8494180d6fc84d"}, - {file = "ruff-0.6.9-py3-none-win_amd64.whl", hash = "sha256:785d31851c1ae91f45b3d8fe23b8ae4b5170089021fbb42402d811135f0b7117"}, - {file = "ruff-0.6.9-py3-none-win_arm64.whl", hash = "sha256:a9641e31476d601f83cd602608739a0840e348bda93fec9f1ee816f8b6798b93"}, - {file = "ruff-0.6.9.tar.gz", hash = "sha256:b076ef717a8e5bc819514ee1d602bbdca5b4420ae13a9cf61a0c0a4f53a2baa2"}, -] - -[[package]] -name = "runs" -version = "1.2.2" -description = "🏃 Run a block of text as a subprocess 🏃" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "runs-1.2.2-py3-none-any.whl", hash = "sha256:0980dcbc25aba1505f307ac4f0e9e92cbd0be2a15a1e983ee86c24c87b839dfd"}, - {file = "runs-1.2.2.tar.gz", hash = "sha256:9dc1815e2895cfb3a48317b173b9f1eac9ba5549b36a847b5cc60c3bf82ecef1"}, -] - -[package.dependencies] -xmod = "*" - -[[package]] -name = "scramp" -version = "1.4.5" -description = "An implementation of the SCRAM protocol." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "scramp-1.4.5-py3-none-any.whl", hash = "sha256:50e37c464fc67f37994e35bee4151e3d8f9320e9c204fca83a5d313c121bbbe7"}, - {file = "scramp-1.4.5.tar.gz", hash = "sha256:be3fbe774ca577a7a658117dca014e5d254d158cecae3dd60332dfe33ce6d78e"}, -] - -[package.dependencies] -asn1crypto = ">=1.5.1" - -[[package]] -name = "segment-analytics-python" -version = "2.3.3" -description = "The hassle-free way to integrate analytics into any python application." -optional = false -python-versions = ">=3.6.0" -groups = ["main"] -files = [ - {file = "segment-analytics-python-2.3.3.tar.gz", hash = "sha256:ce6b3b4387ec9ebc5b55842c44d7dd63b4d4b0b8188e268c4492f909e5eeeed8"}, - {file = "segment_analytics_python-2.3.3-py2.py3-none-any.whl", hash = "sha256:769251706d71f4c96d2039391d119222dbd9faf00308400f7b314ec9fb86cfc7"}, -] - -[package.dependencies] -backoff = ">=2.1,<3.0" -PyJWT = ">=2.8,<3.0" -python-dateutil = ">=2.2,<3.0" -requests = ">=2.7,<3.0" - -[package.extras] -test = ["flake8 (==3.7.9)", "mock (==2.0.0)", "pylint (==2.8.0)"] - -[[package]] -name = "service-identity" -version = "24.1.0" -description = "Service identity verification for pyOpenSSL & cryptography." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "service_identity-24.1.0-py3-none-any.whl", hash = "sha256:a28caf8130c8a5c1c7a6f5293faaf239bbfb7751e4862436920ee6f2616f568a"}, - {file = "service_identity-24.1.0.tar.gz", hash = "sha256:6829c9d62fb832c2e1c435629b0a8c476e1929881f28bee4d20bc24161009221"}, -] - -[package.dependencies] -attrs = ">=19.1.0" -cryptography = "*" -pyasn1 = "*" -pyasn1-modules = "*" - -[package.extras] -dev = ["pyopenssl", "service-identity[idna,mypy,tests]"] -docs = ["furo", "myst-parser", "pyopenssl", "sphinx", "sphinx-notfound-page"] -idna = ["idna"] -mypy = ["idna", "mypy", "types-pyopenssl"] -tests = ["coverage[toml] (>=5.0.2)", "pytest"] - -[[package]] -name = "setuptools" -version = "75.1.0" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "setuptools-75.1.0-py3-none-any.whl", hash = "sha256:35ab7fd3bcd95e6b7fd704e4a1539513edad446c097797f2985e0e4b960772f2"}, - {file = "setuptools-75.1.0.tar.gz", hash = "sha256:d59a21b17a275fb872a9c3dae73963160ae079f1049ed956880cd7c09b120538"}, -] - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] -core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11.*)", "pytest-mypy"] - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -groups = ["main"] -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] - -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - -[[package]] -name = "sortedcontainers" -version = "2.4.0" -description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, - {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, -] - -[[package]] -name = "soupsieve" -version = "2.8" -description = "A modern CSS selector implementation for Beautiful Soup." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c"}, - {file = "soupsieve-2.8.tar.gz", hash = "sha256:e2dd4a40a628cb5f28f6d4b0db8800b8f581b65bb380b97de22ba5ca8d72572f"}, -] - -[[package]] -name = "sqlalchemy" -version = "2.0.35" -description = "Database Abstraction Library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "SQLAlchemy-2.0.35-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:67219632be22f14750f0d1c70e62f204ba69d28f62fd6432ba05ab295853de9b"}, - {file = "SQLAlchemy-2.0.35-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4668bd8faf7e5b71c0319407b608f278f279668f358857dbfd10ef1954ac9f90"}, - {file = "SQLAlchemy-2.0.35-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb8bea573863762bbf45d1e13f87c2d2fd32cee2dbd50d050f83f87429c9e1ea"}, - {file = "SQLAlchemy-2.0.35-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f552023710d4b93d8fb29a91fadf97de89c5926c6bd758897875435f2a939f33"}, - {file = "SQLAlchemy-2.0.35-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:016b2e665f778f13d3c438651dd4de244214b527a275e0acf1d44c05bc6026a9"}, - {file = "SQLAlchemy-2.0.35-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7befc148de64b6060937231cbff8d01ccf0bfd75aa26383ffdf8d82b12ec04ff"}, - {file = "SQLAlchemy-2.0.35-cp310-cp310-win32.whl", hash = "sha256:22b83aed390e3099584b839b93f80a0f4a95ee7f48270c97c90acd40ee646f0b"}, - {file = "SQLAlchemy-2.0.35-cp310-cp310-win_amd64.whl", hash = "sha256:a29762cd3d116585278ffb2e5b8cc311fb095ea278b96feef28d0b423154858e"}, - {file = "SQLAlchemy-2.0.35-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e21f66748ab725ade40fa7af8ec8b5019c68ab00b929f6643e1b1af461eddb60"}, - {file = "SQLAlchemy-2.0.35-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8a6219108a15fc6d24de499d0d515c7235c617b2540d97116b663dade1a54d62"}, - {file = "SQLAlchemy-2.0.35-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:042622a5306c23b972192283f4e22372da3b8ddf5f7aac1cc5d9c9b222ab3ff6"}, - {file = "SQLAlchemy-2.0.35-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:627dee0c280eea91aed87b20a1f849e9ae2fe719d52cbf847c0e0ea34464b3f7"}, - {file = "SQLAlchemy-2.0.35-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4fdcd72a789c1c31ed242fd8c1bcd9ea186a98ee8e5408a50e610edfef980d71"}, - {file = "SQLAlchemy-2.0.35-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:89b64cd8898a3a6f642db4eb7b26d1b28a497d4022eccd7717ca066823e9fb01"}, - {file = "SQLAlchemy-2.0.35-cp311-cp311-win32.whl", hash = "sha256:6a93c5a0dfe8d34951e8a6f499a9479ffb9258123551fa007fc708ae2ac2bc5e"}, - {file = "SQLAlchemy-2.0.35-cp311-cp311-win_amd64.whl", hash = "sha256:c68fe3fcde03920c46697585620135b4ecfdfc1ed23e75cc2c2ae9f8502c10b8"}, - {file = "SQLAlchemy-2.0.35-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:eb60b026d8ad0c97917cb81d3662d0b39b8ff1335e3fabb24984c6acd0c900a2"}, - {file = "SQLAlchemy-2.0.35-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6921ee01caf375363be5e9ae70d08ce7ca9d7e0e8983183080211a062d299468"}, - {file = "SQLAlchemy-2.0.35-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8cdf1a0dbe5ced887a9b127da4ffd7354e9c1a3b9bb330dce84df6b70ccb3a8d"}, - {file = "SQLAlchemy-2.0.35-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93a71c8601e823236ac0e5d087e4f397874a421017b3318fd92c0b14acf2b6db"}, - {file = "SQLAlchemy-2.0.35-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e04b622bb8a88f10e439084486f2f6349bf4d50605ac3e445869c7ea5cf0fa8c"}, - {file = "SQLAlchemy-2.0.35-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1b56961e2d31389aaadf4906d453859f35302b4eb818d34a26fab72596076bb8"}, - {file = "SQLAlchemy-2.0.35-cp312-cp312-win32.whl", hash = "sha256:0f9f3f9a3763b9c4deb8c5d09c4cc52ffe49f9876af41cc1b2ad0138878453cf"}, - {file = "SQLAlchemy-2.0.35-cp312-cp312-win_amd64.whl", hash = "sha256:25b0f63e7fcc2a6290cb5f7f5b4fc4047843504983a28856ce9b35d8f7de03cc"}, - {file = "SQLAlchemy-2.0.35-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f021d334f2ca692523aaf7bbf7592ceff70c8594fad853416a81d66b35e3abf9"}, - {file = "SQLAlchemy-2.0.35-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05c3f58cf91683102f2f0265c0db3bd3892e9eedabe059720492dbaa4f922da1"}, - {file = "SQLAlchemy-2.0.35-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:032d979ce77a6c2432653322ba4cbeabf5a6837f704d16fa38b5a05d8e21fa00"}, - {file = "SQLAlchemy-2.0.35-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:2e795c2f7d7249b75bb5f479b432a51b59041580d20599d4e112b5f2046437a3"}, - {file = "SQLAlchemy-2.0.35-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:cc32b2990fc34380ec2f6195f33a76b6cdaa9eecf09f0c9404b74fc120aef36f"}, - {file = "SQLAlchemy-2.0.35-cp37-cp37m-win32.whl", hash = "sha256:9509c4123491d0e63fb5e16199e09f8e262066e58903e84615c301dde8fa2e87"}, - {file = "SQLAlchemy-2.0.35-cp37-cp37m-win_amd64.whl", hash = "sha256:3655af10ebcc0f1e4e06c5900bb33e080d6a1fa4228f502121f28a3b1753cde5"}, - {file = "SQLAlchemy-2.0.35-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4c31943b61ed8fdd63dfd12ccc919f2bf95eefca133767db6fbbd15da62078ec"}, - {file = "SQLAlchemy-2.0.35-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a62dd5d7cc8626a3634208df458c5fe4f21200d96a74d122c83bc2015b333bc1"}, - {file = "SQLAlchemy-2.0.35-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0630774b0977804fba4b6bbea6852ab56c14965a2b0c7fc7282c5f7d90a1ae72"}, - {file = "SQLAlchemy-2.0.35-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d625eddf7efeba2abfd9c014a22c0f6b3796e0ffb48f5d5ab106568ef01ff5a"}, - {file = "SQLAlchemy-2.0.35-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ada603db10bb865bbe591939de854faf2c60f43c9b763e90f653224138f910d9"}, - {file = "SQLAlchemy-2.0.35-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c41411e192f8d3ea39ea70e0fae48762cd11a2244e03751a98bd3c0ca9a4e936"}, - {file = "SQLAlchemy-2.0.35-cp38-cp38-win32.whl", hash = "sha256:d299797d75cd747e7797b1b41817111406b8b10a4f88b6e8fe5b5e59598b43b0"}, - {file = "SQLAlchemy-2.0.35-cp38-cp38-win_amd64.whl", hash = "sha256:0375a141e1c0878103eb3d719eb6d5aa444b490c96f3fedab8471c7f6ffe70ee"}, - {file = "SQLAlchemy-2.0.35-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ccae5de2a0140d8be6838c331604f91d6fafd0735dbdcee1ac78fc8fbaba76b4"}, - {file = "SQLAlchemy-2.0.35-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2a275a806f73e849e1c309ac11108ea1a14cd7058577aba962cd7190e27c9e3c"}, - {file = "SQLAlchemy-2.0.35-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:732e026240cdd1c1b2e3ac515c7a23820430ed94292ce33806a95869c46bd139"}, - {file = "SQLAlchemy-2.0.35-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:890da8cd1941fa3dab28c5bac3b9da8502e7e366f895b3b8e500896f12f94d11"}, - {file = "SQLAlchemy-2.0.35-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c0d8326269dbf944b9201911b0d9f3dc524d64779a07518199a58384c3d37a44"}, - {file = "SQLAlchemy-2.0.35-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b76d63495b0508ab9fc23f8152bac63205d2a704cd009a2b0722f4c8e0cba8e0"}, - {file = "SQLAlchemy-2.0.35-cp39-cp39-win32.whl", hash = "sha256:69683e02e8a9de37f17985905a5eca18ad651bf592314b4d3d799029797d0eb3"}, - {file = "SQLAlchemy-2.0.35-cp39-cp39-win_amd64.whl", hash = "sha256:aee110e4ef3c528f3abbc3c2018c121e708938adeeff9006428dd7c8555e9b3f"}, - {file = "SQLAlchemy-2.0.35-py3-none-any.whl", hash = "sha256:2ab3f0336c0387662ce6221ad30ab3a5e6499aab01b9790879b6578fd9b8faa1"}, - {file = "sqlalchemy-2.0.35.tar.gz", hash = "sha256:e11d7ea4d24f0a262bccf9a7cd6284c976c5369dac21db237cff59586045ab9f"}, -] - -[package.dependencies] -greenlet = {version = "!=0.4.17", markers = "python_version < \"3.13\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"} -typing-extensions = ">=4.6.0" - -[package.extras] -aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] -aioodbc = ["aioodbc", "greenlet (!=0.4.17)"] -aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"] -asyncio = ["greenlet (!=0.4.17)"] -asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] -mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] -mssql = ["pyodbc"] -mssql-pymssql = ["pymssql"] -mssql-pyodbc = ["pyodbc"] -mypy = ["mypy (>=0.910)"] -mysql = ["mysqlclient (>=1.4.0)"] -mysql-connector = ["mysql-connector-python"] -oracle = ["cx_oracle (>=8)"] -oracle-oracledb = ["oracledb (>=1.0.1)"] -postgresql = ["psycopg2 (>=2.7)"] -postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] -postgresql-pg8000 = ["pg8000 (>=1.29.1)"] -postgresql-psycopg = ["psycopg (>=3.0.7)"] -postgresql-psycopg2binary = ["psycopg2-binary"] -postgresql-psycopg2cffi = ["psycopg2cffi"] -postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] -pymysql = ["pymysql"] -sqlcipher = ["sqlcipher3_binary"] - -[[package]] -name = "termcolor" -version = "2.5.0" -description = "ANSI color formatting for output in terminal" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "termcolor-2.5.0-py3-none-any.whl", hash = "sha256:37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8"}, - {file = "termcolor-2.5.0.tar.gz", hash = "sha256:998d8d27da6d48442e8e1f016119076b690d962507531df4890fcd2db2ef8a6f"}, -] - -[package.extras] -tests = ["pytest", "pytest-cov"] - -[[package]] -name = "text-unidecode" -version = "1.3" -description = "The most basic Text::Unidecode port" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, - {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, -] - -[[package]] -name = "tornado" -version = "6.4.1" -description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "tornado-6.4.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:163b0aafc8e23d8cdc3c9dfb24c5368af84a81e3364745ccb4427669bf84aec8"}, - {file = "tornado-6.4.1-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14"}, - {file = "tornado-6.4.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4"}, - {file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ae50a504a740365267b2a8d1a90c9fbc86b780a39170feca9bcc1787ff80842"}, - {file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3"}, - {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25486eb223babe3eed4b8aecbac33b37e3dd6d776bc730ca14e1bf93888b979f"}, - {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:454db8a7ecfcf2ff6042dde58404164d969b6f5d58b926da15e6b23817950fc4"}, - {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a02a08cc7a9314b006f653ce40483b9b3c12cda222d6a46d4ac63bb6c9057698"}, - {file = "tornado-6.4.1-cp38-abi3-win32.whl", hash = "sha256:d9a566c40b89757c9aa8e6f032bcdb8ca8795d7c1a9762910c722b1635c9de4d"}, - {file = "tornado-6.4.1-cp38-abi3-win_amd64.whl", hash = "sha256:b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7"}, - {file = "tornado-6.4.1.tar.gz", hash = "sha256:92d3ab53183d8c50f8204a51e6f91d18a15d5ef261e84d452800d4ff6fc504e9"}, -] - -[[package]] -name = "tqdm" -version = "4.66.5" -description = "Fast, Extensible Progress Meter" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "tqdm-4.66.5-py3-none-any.whl", hash = "sha256:90279a3770753eafc9194a0364852159802111925aa30eb3f9d85b0e805ac7cd"}, - {file = "tqdm-4.66.5.tar.gz", hash = "sha256:e1020aef2e5096702d8a025ac7d16b1577279c9d63f8375b63083e9a5f0fcbad"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] -notebook = ["ipywidgets (>=6)"] -slack = ["slack-sdk"] -telegram = ["requests"] - -[[package]] -name = "types-cachetools" -version = "5.5.0.20240820" -description = "Typing stubs for cachetools" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "types-cachetools-5.5.0.20240820.tar.gz", hash = "sha256:b888ab5c1a48116f7799cd5004b18474cd82b5463acb5ffb2db2fc9c7b053bc0"}, - {file = "types_cachetools-5.5.0.20240820-py3-none-any.whl", hash = "sha256:efb2ed8bf27a4b9d3ed70d33849f536362603a90b8090a328acf0cd42fda82e2"}, -] - -[[package]] -name = "types-pytz" -version = "2024.2.0.20241003" -description = "Typing stubs for pytz" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "types-pytz-2024.2.0.20241003.tar.gz", hash = "sha256:575dc38f385a922a212bac00a7d6d2e16e141132a3c955078f4a4fd13ed6cb44"}, - {file = "types_pytz-2024.2.0.20241003-py3-none-any.whl", hash = "sha256:3e22df1336c0c6ad1d29163c8fda82736909eb977281cb823c57f8bae07118b7"}, -] - -[[package]] -name = "types-pyyaml" -version = "6.0.12.20240917" -description = "Typing stubs for PyYAML" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "types-PyYAML-6.0.12.20240917.tar.gz", hash = "sha256:d1405a86f9576682234ef83bcb4e6fff7c9305c8b1fbad5e0bcd4f7dbdc9c587"}, - {file = "types_PyYAML-6.0.12.20240917-py3-none-any.whl", hash = "sha256:392b267f1c0fe6022952462bf5d6523f31e37f6cea49b14cee7ad634b6301570"}, -] - -[[package]] -name = "types-requests" -version = "2.32.0.20240914" -description = "Typing stubs for requests" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "types-requests-2.32.0.20240914.tar.gz", hash = "sha256:2850e178db3919d9bf809e434eef65ba49d0e7e33ac92d588f4a5e295fffd405"}, - {file = "types_requests-2.32.0.20240914-py3-none-any.whl", hash = "sha256:59c2f673eb55f32a99b2894faf6020e1a9f4a402ad0f192bfee0b64469054310"}, -] - -[package.dependencies] -urllib3 = ">=2" - -[[package]] -name = "typing-extensions" -version = "4.12.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, -] - -[[package]] -name = "tzdata" -version = "2024.2" -description = "Provider of IANA time zone data" -optional = false -python-versions = ">=2" -groups = ["main"] -files = [ - {file = "tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd"}, - {file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"}, -] - -[[package]] -name = "urllib3" -version = "2.2.3" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, - {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "urwid-mitmproxy" -version = "2.1.2.1" -description = "A full-featured console (xterm et al.) user interface library" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "urwid-mitmproxy-2.1.2.1.tar.gz", hash = "sha256:be6238e587acb92bdd43b241af0a10dc23798e8cf3eddef834164eb637686cda"}, - {file = "urwid_mitmproxy-2.1.2.1-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:29c62a593235d2b69ba4557648588c54420ef030794b9d28e65f50bffdde85c3"}, - {file = "urwid_mitmproxy-2.1.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:d93bdc87cbb329cd262f8ada586e954a95ca4cc7249eca5b348b87f47ef1adb5"}, - {file = "urwid_mitmproxy-2.1.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8cb7eb42fcc426ea02c321159631d396ec0cd6ebebabb310f3a4493579ff2e09"}, - {file = "urwid_mitmproxy-2.1.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:66c40dcead7fedbb312516e18574d216b0e7c728bf5cd0e240eee53737234b45"}, - {file = "urwid_mitmproxy-2.1.2.1-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:7a8a95460a519e0388d91a198acb31836dce40d14e599a0b9c24ba70fa4ec64b"}, - {file = "urwid_mitmproxy-2.1.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:d2d536ad412022365b5e1974cde9029b86cfc30f3960ae073f959630f0c27c21"}, -] - -[[package]] -name = "wcwidth" -version = "0.2.13" -description = "Measures the displayed width of unicode strings in a terminal" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, - {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, -] - -[[package]] -name = "websocket-client" -version = "1.8.0" -description = "WebSocket client for Python with low level API options" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, - {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, -] - -[package.extras] -docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"] -optional = ["python-socks", "wsaccel"] -test = ["websockets"] - -[[package]] -name = "werkzeug" -version = "3.0.4" -description = "The comprehensive WSGI web application library." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "werkzeug-3.0.4-py3-none-any.whl", hash = "sha256:02c9eb92b7d6c06f31a782811505d2157837cea66aaede3e217c7c27c039476c"}, - {file = "werkzeug-3.0.4.tar.gz", hash = "sha256:34f2371506b250df4d4f84bfe7b0921e4762525762bbd936614909fe25cd7306"}, -] - -[package.dependencies] -MarkupSafe = ">=2.1.1" - -[package.extras] -watchdog = ["watchdog (>=2.3)"] - -[[package]] -name = "wrapt" -version = "1.16.0" -description = "Module for decorators, wrappers and monkey patching." -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, - {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, - {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, - {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, - {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, - {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, - {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, - {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, - {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, - {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, - {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, - {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, - {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, - {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, - {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, - {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, - {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, - {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, - {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, - {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, - {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, - {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, - {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, - {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, - {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, - {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, - {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, - {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, -] - -[[package]] -name = "wsproto" -version = "1.2.0" -description = "WebSockets state-machine based protocol implementation" -optional = false -python-versions = ">=3.7.0" -groups = ["main"] -files = [ - {file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"}, - {file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065"}, -] - -[package.dependencies] -h11 = ">=0.9.0,<1" - -[[package]] -name = "xmod" -version = "1.8.1" -description = "🌱 Turn any object into a module 🌱" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "xmod-1.8.1-py3-none-any.whl", hash = "sha256:a24e9458a4853489042522bdca9e50ee2eac5ab75c809a91150a8a7f40670d48"}, - {file = "xmod-1.8.1.tar.gz", hash = "sha256:38c76486b9d672c546d57d8035df0beb7f4a9b088bc3fb2de5431ae821444377"}, -] - -[[package]] -name = "yarl" -version = "1.14.0" -description = "Yet another URL library" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "yarl-1.14.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1bfc25aa6a7c99cf86564210f79a0b7d4484159c67e01232b116e445b3036547"}, - {file = "yarl-1.14.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0cf21f46a15d445417de8fc89f2568852cf57fe8ca1ab3d19ddb24d45c0383ae"}, - {file = "yarl-1.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1dda53508df0de87b6e6b0a52d6718ff6c62a5aca8f5552748404963df639269"}, - {file = "yarl-1.14.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:587c3cc59bc148a9b1c07a019346eda2549bc9f468acd2f9824d185749acf0a6"}, - {file = "yarl-1.14.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3007a5b75cb50140708420fe688c393e71139324df599434633019314ceb8b59"}, - {file = "yarl-1.14.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:06ff23462398333c78b6f4f8d3d70410d657a471c2c5bbe6086133be43fc8f1a"}, - {file = "yarl-1.14.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:689a99a42ee4583fcb0d3a67a0204664aa1539684aed72bdafcbd505197a91c4"}, - {file = "yarl-1.14.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0547ab1e9345dc468cac8368d88ea4c5bd473ebc1d8d755347d7401982b5dd8"}, - {file = "yarl-1.14.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:742aef0a99844faaac200564ea6f5e08facb285d37ea18bd1a5acf2771f3255a"}, - {file = "yarl-1.14.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:176110bff341b6730f64a1eb3a7070e12b373cf1c910a9337e7c3240497db76f"}, - {file = "yarl-1.14.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:46a9772a1efa93f9cd170ad33101c1817c77e0e9914d4fe33e2da299d7cf0f9b"}, - {file = "yarl-1.14.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:ee2c68e4f2dd1b1c15b849ba1c96fac105fca6ffdb7c1e8be51da6fabbdeafb9"}, - {file = "yarl-1.14.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:047b258e00b99091b6f90355521f026238c63bd76dcf996d93527bb13320eefd"}, - {file = "yarl-1.14.0-cp310-cp310-win32.whl", hash = "sha256:0aa92e3e30a04f9462a25077db689c4ac5ea9ab6cc68a2e563881b987d42f16d"}, - {file = "yarl-1.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:d9baec588f015d0ee564057aa7574313c53a530662ffad930b7886becc85abdf"}, - {file = "yarl-1.14.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:07f9eaf57719d6721ab15805d85f4b01a5b509a0868d7320134371bcb652152d"}, - {file = "yarl-1.14.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c14b504a74e58e2deb0378b3eca10f3d076635c100f45b113c18c770b4a47a50"}, - {file = "yarl-1.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:16a682a127930f3fc4e42583becca6049e1d7214bcad23520c590edd741d2114"}, - {file = "yarl-1.14.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:73bedd2be05f48af19f0f2e9e1353921ce0c83f4a1c9e8556ecdcf1f1eae4892"}, - {file = "yarl-1.14.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3ab950f8814f3b7b5e3eebc117986f817ec933676f68f0a6c5b2137dd7c9c69"}, - {file = "yarl-1.14.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b693c63e7e64b524f54aa4888403c680342d1ad0d97be1707c531584d6aeeb4f"}, - {file = "yarl-1.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85cb3e40eaa98489f1e2e8b29f5ad02ee1ee40d6ce6b88d50cf0f205de1d9d2c"}, - {file = "yarl-1.14.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f24f08b6c9b9818fd80612c97857d28f9779f0d1211653ece9844fc7b414df2"}, - {file = "yarl-1.14.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:29a84a46ec3ebae7a1c024c055612b11e9363a8a23238b3e905552d77a2bc51b"}, - {file = "yarl-1.14.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5cd5dad8366e0168e0fd23d10705a603790484a6dbb9eb272b33673b8f2cce72"}, - {file = "yarl-1.14.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a152751af7ef7b5d5fa6d215756e508dd05eb07d0cf2ba51f3e740076aa74373"}, - {file = "yarl-1.14.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:3d569f877ed9a708e4c71a2d13d2940cb0791da309f70bd970ac1a5c088a0a92"}, - {file = "yarl-1.14.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6a615cad11ec3428020fb3c5a88d85ce1b5c69fd66e9fcb91a7daa5e855325dd"}, - {file = "yarl-1.14.0-cp311-cp311-win32.whl", hash = "sha256:bab03192091681d54e8225c53f270b0517637915d9297028409a2a5114ff4634"}, - {file = "yarl-1.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:985623575e5c4ea763056ffe0e2d63836f771a8c294b3de06d09480538316b13"}, - {file = "yarl-1.14.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fc2c80bc87fba076e6cbb926216c27fba274dae7100a7b9a0983b53132dd99f2"}, - {file = "yarl-1.14.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:55c144d363ad4626ca744556c049c94e2b95096041ac87098bb363dcc8635e8d"}, - {file = "yarl-1.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b03384eed107dbeb5f625a99dc3a7de8be04fc8480c9ad42fccbc73434170b20"}, - {file = "yarl-1.14.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f72a0d746d38cb299b79ce3d4d60ba0892c84bbc905d0d49c13df5bace1b65f8"}, - {file = "yarl-1.14.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8648180b34faaea4aa5b5ca7e871d9eb1277033fa439693855cf0ea9195f85f1"}, - {file = "yarl-1.14.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9557c9322aaa33174d285b0c1961fb32499d65ad1866155b7845edc876c3c835"}, - {file = "yarl-1.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f50eb3837012a937a2b649ec872b66ba9541ad9d6f103ddcafb8231cfcafd22"}, - {file = "yarl-1.14.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8892fa575ac9b1b25fae7b221bc4792a273877b9b56a99ee2d8d03eeb3dbb1d2"}, - {file = "yarl-1.14.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e6a2c5c5bb2556dfbfffffc2bcfb9c235fd2b566d5006dfb2a37afc7e3278a07"}, - {file = "yarl-1.14.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ab3abc0b78a5dfaa4795a6afbe7b282b6aa88d81cf8c1bb5e394993d7cae3457"}, - {file = "yarl-1.14.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:47eede5d11d669ab3759b63afb70d28d5328c14744b8edba3323e27dc52d298d"}, - {file = "yarl-1.14.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fe4d2536c827f508348d7b40c08767e8c7071614250927233bf0c92170451c0a"}, - {file = "yarl-1.14.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0fd7b941dd1b00b5f0acb97455fea2c4b7aac2dd31ea43fb9d155e9bc7b78664"}, - {file = "yarl-1.14.0-cp312-cp312-win32.whl", hash = "sha256:99ff3744f5fe48288be6bc402533b38e89749623a43208e1d57091fc96b783b9"}, - {file = "yarl-1.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:1ca3894e9e9f72da93544f64988d9c052254a338a9f855165f37f51edb6591de"}, - {file = "yarl-1.14.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5d02d700705d67e09e1f57681f758f0b9d4412eeb70b2eb8d96ca6200b486db3"}, - {file = "yarl-1.14.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:30600ba5db60f7c0820ef38a2568bb7379e1418ecc947a0f76fd8b2ff4257a97"}, - {file = "yarl-1.14.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e85d86527baebb41a214cc3b45c17177177d900a2ad5783dbe6f291642d4906f"}, - {file = "yarl-1.14.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37001e5d4621cef710c8dc1429ca04e189e572f128ab12312eab4e04cf007132"}, - {file = "yarl-1.14.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f4f4547944d4f5cfcdc03f3f097d6f05bbbc915eaaf80a2ee120d0e756de377d"}, - {file = "yarl-1.14.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75ff4c819757f9bdb35de049a509814d6ce851fe26f06eb95a392a5640052482"}, - {file = "yarl-1.14.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68ac1a09392ed6e3fd14be880d39b951d7b981fd135416db7d18a6208c536561"}, - {file = "yarl-1.14.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96952f642ac69075e44c7d0284528938fdff39422a1d90d3e45ce40b72e5e2d9"}, - {file = "yarl-1.14.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a56fbe3d7f3bce1d060ea18d2413a2ca9ca814eea7cedc4d247b5f338d54844e"}, - {file = "yarl-1.14.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7e2637d75e92763d1322cb5041573279ec43a80c0f7fbbd2d64f5aee98447b17"}, - {file = "yarl-1.14.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:9abe80ae2c9d37c17599557b712e6515f4100a80efb2cda15f5f070306477cd2"}, - {file = "yarl-1.14.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:217a782020b875538eebf3948fac3a7f9bbbd0fd9bf8538f7c2ad7489e80f4e8"}, - {file = "yarl-1.14.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9cfef3f14f75bf6aba73a76caf61f9d00865912a04a4393c468a7ce0981b519"}, - {file = "yarl-1.14.0-cp313-cp313-win32.whl", hash = "sha256:d8361c7d04e6a264481f0b802e395f647cd3f8bbe27acfa7c12049efea675bd1"}, - {file = "yarl-1.14.0-cp313-cp313-win_amd64.whl", hash = "sha256:bc24f968b82455f336b79bf37dbb243b7d76cd40897489888d663d4e028f5069"}, - {file = "yarl-1.14.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:91d875f75fabf76b3018c5f196bf3d308ed2b49ddcb46c1576d6b075754a1393"}, - {file = "yarl-1.14.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4009def9be3a7e5175db20aa2d7307ecd00bbf50f7f0f989300710eee1d0b0b9"}, - {file = "yarl-1.14.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:582cedde49603f139be572252a318b30dc41039bc0b8165f070f279e5d12187f"}, - {file = "yarl-1.14.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbd9ff43a04f8ffe8a959a944c2dca10d22f5f99fc6a459f49c3ebfb409309d9"}, - {file = "yarl-1.14.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9f805e37ed16cc212fdc538a608422d7517e7faf539bedea4fe69425bc55d76"}, - {file = "yarl-1.14.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:95e16e9eaa2d7f5d87421b8fe694dd71606aa61d74b824c8d17fc85cc51983d1"}, - {file = "yarl-1.14.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:816d24f584edefcc5ca63428f0b38fee00b39fe64e3c5e558f895a18983efe96"}, - {file = "yarl-1.14.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd2660c01367eb3ef081b8fa0a5da7fe767f9427aa82023a961a5f28f0d4af6c"}, - {file = "yarl-1.14.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:94b2bb9bcfd5be9d27004ea4398fb640373dd0c1a9e219084f42c08f77a720ab"}, - {file = "yarl-1.14.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:c2089a9afef887664115f7fa6d3c0edd6454adaca5488dba836ca91f60401075"}, - {file = "yarl-1.14.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:2192f718db4a8509f63dd6d950f143279211fa7e6a2c612edc17d85bf043d36e"}, - {file = "yarl-1.14.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:8385ab36bf812e9d37cf7613999a87715f27ef67a53f0687d28c44b819df7cb0"}, - {file = "yarl-1.14.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:b4c1ecba93e7826dc71ddba75fb7740cdb52e7bd0be9f03136b83f54e6a1f511"}, - {file = "yarl-1.14.0-cp38-cp38-win32.whl", hash = "sha256:e749af6c912a7bb441d105c50c1a3da720474e8acb91c89350080dd600228f0e"}, - {file = "yarl-1.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:147e36331f6f63e08a14640acf12369e041e0751bb70d9362df68c2d9dcf0c87"}, - {file = "yarl-1.14.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a9f917966d27f7ce30039fe8d900f913c5304134096554fd9bea0774bcda6d1"}, - {file = "yarl-1.14.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a2f8fb7f944bcdfecd4e8d855f84c703804a594da5123dd206f75036e536d4d"}, - {file = "yarl-1.14.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f4e475f29a9122f908d0f1f706e1f2fc3656536ffd21014ff8a6f2e1b14d1d8"}, - {file = "yarl-1.14.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8089d4634d8fa2b1806ce44fefa4979b1ab2c12c0bc7ef3dfa45c8a374811348"}, - {file = "yarl-1.14.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b16f6c75cffc2dc0616ea295abb0e1967601bd1fb1e0af6a1de1c6c887f3439"}, - {file = "yarl-1.14.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:498b3c55087b9d762636bca9b45f60d37e51d24341786dc01b81253f9552a607"}, - {file = "yarl-1.14.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3f8bfc1db82589ef965ed234b87de30d140db8b6dc50ada9e33951ccd8ec07a"}, - {file = "yarl-1.14.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:625f207b1799e95e7c823f42f473c1e9dbfb6192bd56bba8695656d92be4535f"}, - {file = "yarl-1.14.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:781e2495e408a81e4eaeedeb41ba32b63b1980dddf8b60dbbeff6036bcd35049"}, - {file = "yarl-1.14.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:659603d26d40dd4463200df9bfbc339fbfaed3fe32e5c432fe1dc2b5d4aa94b4"}, - {file = "yarl-1.14.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:4e0d45ebf975634468682c8bec021618b3ad52c37619e5c938f8f831fa1ac5c0"}, - {file = "yarl-1.14.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:a2e4725a08cb2b4794db09e350c86dee18202bb8286527210e13a1514dc9a59a"}, - {file = "yarl-1.14.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:19268b4fec1d7760134f2de46ef2608c2920134fb1fa61e451f679e41356dc55"}, - {file = "yarl-1.14.0-cp39-cp39-win32.whl", hash = "sha256:337912bcdcf193ade64b9aae5a4017a0a1950caf8ca140362e361543c6773f21"}, - {file = "yarl-1.14.0-cp39-cp39-win_amd64.whl", hash = "sha256:b6d0147574ce2e7b812c989e50fa72bbc5338045411a836bd066ce5fc8ac0bce"}, - {file = "yarl-1.14.0-py3-none-any.whl", hash = "sha256:c8ed4034f0765f8861620c1f2f2364d2e58520ea288497084dae880424fc0d9f"}, - {file = "yarl-1.14.0.tar.gz", hash = "sha256:88c7d9d58aab0724b979ab5617330acb1c7030b79379c8138c1c8c94e121d1b3"}, -] - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" -propcache = ">=0.2.0" - -[[package]] -name = "zipp" -version = "3.20.2" -description = "Backport of pathlib-compatible object wrapper for zip files" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"}, - {file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"}, -] - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] -type = ["pytest-mypy"] - -[[package]] -name = "zstandard" -version = "0.22.0" -description = "Zstandard bindings for Python" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "zstandard-0.22.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:275df437ab03f8c033b8a2c181e51716c32d831082d93ce48002a5227ec93019"}, - {file = "zstandard-0.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ac9957bc6d2403c4772c890916bf181b2653640da98f32e04b96e4d6fb3252a"}, - {file = "zstandard-0.22.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe3390c538f12437b859d815040763abc728955a52ca6ff9c5d4ac707c4ad98e"}, - {file = "zstandard-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1958100b8a1cc3f27fa21071a55cb2ed32e9e5df4c3c6e661c193437f171cba2"}, - {file = "zstandard-0.22.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93e1856c8313bc688d5df069e106a4bc962eef3d13372020cc6e3ebf5e045202"}, - {file = "zstandard-0.22.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1a90ba9a4c9c884bb876a14be2b1d216609385efb180393df40e5172e7ecf356"}, - {file = "zstandard-0.22.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3db41c5e49ef73641d5111554e1d1d3af106410a6c1fb52cf68912ba7a343a0d"}, - {file = "zstandard-0.22.0-cp310-cp310-win32.whl", hash = "sha256:d8593f8464fb64d58e8cb0b905b272d40184eac9a18d83cf8c10749c3eafcd7e"}, - {file = "zstandard-0.22.0-cp310-cp310-win_amd64.whl", hash = "sha256:f1a4b358947a65b94e2501ce3e078bbc929b039ede4679ddb0460829b12f7375"}, - {file = "zstandard-0.22.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:589402548251056878d2e7c8859286eb91bd841af117dbe4ab000e6450987e08"}, - {file = "zstandard-0.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a97079b955b00b732c6f280d5023e0eefe359045e8b83b08cf0333af9ec78f26"}, - {file = "zstandard-0.22.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:445b47bc32de69d990ad0f34da0e20f535914623d1e506e74d6bc5c9dc40bb09"}, - {file = "zstandard-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33591d59f4956c9812f8063eff2e2c0065bc02050837f152574069f5f9f17775"}, - {file = "zstandard-0.22.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:888196c9c8893a1e8ff5e89b8f894e7f4f0e64a5af4d8f3c410f0319128bb2f8"}, - {file = "zstandard-0.22.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:53866a9d8ab363271c9e80c7c2e9441814961d47f88c9bc3b248142c32141d94"}, - {file = "zstandard-0.22.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4ac59d5d6910b220141c1737b79d4a5aa9e57466e7469a012ed42ce2d3995e88"}, - {file = "zstandard-0.22.0-cp311-cp311-win32.whl", hash = "sha256:2b11ea433db22e720758cba584c9d661077121fcf60ab43351950ded20283440"}, - {file = "zstandard-0.22.0-cp311-cp311-win_amd64.whl", hash = "sha256:11f0d1aab9516a497137b41e3d3ed4bbf7b2ee2abc79e5c8b010ad286d7464bd"}, - {file = "zstandard-0.22.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6c25b8eb733d4e741246151d895dd0308137532737f337411160ff69ca24f93a"}, - {file = "zstandard-0.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f9b2cde1cd1b2a10246dbc143ba49d942d14fb3d2b4bccf4618d475c65464912"}, - {file = "zstandard-0.22.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a88b7df61a292603e7cd662d92565d915796b094ffb3d206579aaebac6b85d5f"}, - {file = "zstandard-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:466e6ad8caefb589ed281c076deb6f0cd330e8bc13c5035854ffb9c2014b118c"}, - {file = "zstandard-0.22.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a1d67d0d53d2a138f9e29d8acdabe11310c185e36f0a848efa104d4e40b808e4"}, - {file = "zstandard-0.22.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:39b2853efc9403927f9065cc48c9980649462acbdf81cd4f0cb773af2fd734bc"}, - {file = "zstandard-0.22.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8a1b2effa96a5f019e72874969394edd393e2fbd6414a8208fea363a22803b45"}, - {file = "zstandard-0.22.0-cp312-cp312-win32.whl", hash = "sha256:88c5b4b47a8a138338a07fc94e2ba3b1535f69247670abfe422de4e0b344aae2"}, - {file = "zstandard-0.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:de20a212ef3d00d609d0b22eb7cc798d5a69035e81839f549b538eff4105d01c"}, - {file = "zstandard-0.22.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d75f693bb4e92c335e0645e8845e553cd09dc91616412d1d4650da835b5449df"}, - {file = "zstandard-0.22.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:36a47636c3de227cd765e25a21dc5dace00539b82ddd99ee36abae38178eff9e"}, - {file = "zstandard-0.22.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68953dc84b244b053c0d5f137a21ae8287ecf51b20872eccf8eaac0302d3e3b0"}, - {file = "zstandard-0.22.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2612e9bb4977381184bb2463150336d0f7e014d6bb5d4a370f9a372d21916f69"}, - {file = "zstandard-0.22.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23d2b3c2b8e7e5a6cb7922f7c27d73a9a615f0a5ab5d0e03dd533c477de23004"}, - {file = "zstandard-0.22.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d43501f5f31e22baf822720d82b5547f8a08f5386a883b32584a185675c8fbf"}, - {file = "zstandard-0.22.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a493d470183ee620a3df1e6e55b3e4de8143c0ba1b16f3ded83208ea8ddfd91d"}, - {file = "zstandard-0.22.0-cp38-cp38-win32.whl", hash = "sha256:7034d381789f45576ec3f1fa0e15d741828146439228dc3f7c59856c5bcd3292"}, - {file = "zstandard-0.22.0-cp38-cp38-win_amd64.whl", hash = "sha256:d8fff0f0c1d8bc5d866762ae95bd99d53282337af1be9dc0d88506b340e74b73"}, - {file = "zstandard-0.22.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2fdd53b806786bd6112d97c1f1e7841e5e4daa06810ab4b284026a1a0e484c0b"}, - {file = "zstandard-0.22.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:73a1d6bd01961e9fd447162e137ed949c01bdb830dfca487c4a14e9742dccc93"}, - {file = "zstandard-0.22.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9501f36fac6b875c124243a379267d879262480bf85b1dbda61f5ad4d01b75a3"}, - {file = "zstandard-0.22.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48f260e4c7294ef275744210a4010f116048e0c95857befb7462e033f09442fe"}, - {file = "zstandard-0.22.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:959665072bd60f45c5b6b5d711f15bdefc9849dd5da9fb6c873e35f5d34d8cfb"}, - {file = "zstandard-0.22.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d22fdef58976457c65e2796e6730a3ea4a254f3ba83777ecfc8592ff8d77d303"}, - {file = "zstandard-0.22.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a7ccf5825fd71d4542c8ab28d4d482aace885f5ebe4b40faaa290eed8e095a4c"}, - {file = "zstandard-0.22.0-cp39-cp39-win32.whl", hash = "sha256:f058a77ef0ece4e210bb0450e68408d4223f728b109764676e1a13537d056bb0"}, - {file = "zstandard-0.22.0-cp39-cp39-win_amd64.whl", hash = "sha256:e9e9d4e2e336c529d4c435baad846a181e39a982f823f7e4495ec0b0ec8538d2"}, - {file = "zstandard-0.22.0.tar.gz", hash = "sha256:8226a33c542bcb54cd6bd0a366067b610b41713b64c9abec1bc4533d69f51e70"}, -] - -[package.dependencies] -cffi = {version = ">=1.11", markers = "platform_python_implementation == \"PyPy\""} - -[package.extras] -cffi = ["cffi (>=1.11)"] - -[metadata] -lock-version = "2.1" -python-versions = "^3.11,<3.12" -content-hash = "d6f93822b88fad4aaf0ae5d60932e0e93d9e95aa79fdddc44f9f6045387d3b4c" diff --git a/airbyte-ci/connectors/live-tests/pyproject.toml b/airbyte-ci/connectors/live-tests/pyproject.toml deleted file mode 100644 index 6f1a882b0590..000000000000 --- a/airbyte-ci/connectors/live-tests/pyproject.toml +++ /dev/null @@ -1,75 +0,0 @@ -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" - -[tool.poetry] -name = "live-tests" -version = "0.21.4" -description = "Contains utilities for testing connectors against live data." -authors = ["Airbyte "] -license = "MIT" -homepage = "https://github.com/airbytehq/airbyte" -readme = "README.md" -packages = [ - { include = "live_tests", from = "src" }, -] - -[tool.poetry.dependencies] -python = "^3.11,<3.12" -airbyte-protocol-models = "<1.0.0" -cachetools = "~=5.3.3" -dagger-io = "==0.13.3" -decorator = ">=5.1.1" -deepdiff = "6.7.1" -jsonschema = "*" -pydantic = "*" -pytest-asyncio = "~=0.23.5" -pytest = "^8.1.1" -pydash = "~=7.0.7" -docker = ">=6,<7" -asyncclick = "^8.1.7.1" -connection-retriever = {git = "git@github.com:airbytehq/airbyte-platform-internal", subdirectory = "tools/connection-retriever"} -duckdb = "<=0.10.1" # Pinned due to this issue https://github.com/duckdb/duckdb/issues/11152 -pandas = "^2.2.1" -pytest-sugar = "^1.0.0" -asyncer = "^0.0.5" -rich = "^13.7.1" -mitmproxy = "^10.2.4" -requests = "<=2.31.1" # Pinned due to this issue https://github.com/docker/docker-py/issues/3256#issuecomment-2127688011 -pyyaml = "~=6.0.1" -dpath = "^2.1.6" -genson = "^1.3.0" -segment-analytics-python = "^2.3.2" -python-slugify = ">=8.0.4" -beautifulsoup4 = "^4.12.0" -openai = "^1.0.0" - - -[tool.poetry.group.dev.dependencies] -ruff = "^0.6" -mypy = "^1.8.0" -types-cachetools = "^5.3.0.7" -pandas-stubs = "^2.2.0.240218" -types-requests = "^2.31.0.20240311" -types-pyyaml = "^6.0.12.20240311" - -[tool.ruff] -target-version = "py311" -line-length = 140 - -[tool.ruff.lint] -select = ["I", "F"] - -[tool.ruff.lint.isort] -known-first-party = ["connection-retriever"] - -[tool.poe.tasks] -test = "pytest tests" -type_check = "mypy src --disallow-untyped-defs" -pre-push = [] - -[tool.airbyte_ci] -python_versions = ["3.11"] -optional_poetry_groups = ["dev"] -poe_tasks = [] -required_environment_variables = ["DOCKER_HUB_USERNAME", "DOCKER_HUB_PASSWORD"] diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/__init__.py b/airbyte-ci/connectors/live-tests/src/live_tests/__init__.py deleted file mode 100644 index 51502a263eae..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/__init__.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/__init__.py deleted file mode 100644 index f70ecfc3a89e..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/__init__.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/__init__.py deleted file mode 100644 index 62501987fb84..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -from .base_backend import BaseBackend -from .duckdb_backend import DuckDbBackend -from .file_backend import FileBackend - -__all__ = ["BaseBackend", "FileBackend", "DuckDbBackend"] diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/base_backend.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/base_backend.py deleted file mode 100644 index 303799e245eb..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/base_backend.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -from abc import ABC, abstractmethod -from collections.abc import Iterable - -from airbyte_protocol.models import AirbyteMessage # type: ignore - - -class BaseBackend(ABC): - """ - Interface to be shared between the file backend and the database backend(s) - """ - - @abstractmethod - def write(self, airbyte_messages: Iterable[AirbyteMessage]) -> None: ... diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/duckdb_backend.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/duckdb_backend.py deleted file mode 100644 index d5bfa0fdff27..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/duckdb_backend.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -import logging -import re -from collections.abc import Iterable -from pathlib import Path -from typing import Optional - -import duckdb -from airbyte_protocol.models import AirbyteMessage # type: ignore - -from live_tests.commons.backends.file_backend import FileBackend - - -class DuckDbBackend(FileBackend): - SAMPLE_SIZE = -1 - - def __init__( - self, - output_directory: Path, - duckdb_path: Path, - schema: Optional[Iterable[str]] = None, - ): - super().__init__(output_directory) - self.duckdb_path = duckdb_path - self.schema = schema - - @property - def jsonl_files_to_insert(self) -> Iterable[Path]: - return [ - self.jsonl_catalogs_path, - self.jsonl_connection_status_path, - self.jsonl_specs_path, - self.jsonl_states_path, - self.jsonl_traces_path, - self.jsonl_logs_path, - self.jsonl_controls_path, - self.jsonl_records_path, - ] - - @staticmethod - def sanitize_table_name(table_name: str) -> str: - sanitized = str(table_name).replace(" ", "_") - sanitized = re.sub(r"[^\w\s]", "", sanitized) - if sanitized and sanitized[0].isdigit(): - sanitized = "_" + sanitized - return sanitized - - def write(self, airbyte_messages: Iterable[AirbyteMessage]) -> None: - # Use the FileBackend to write the messages to disk as jsonl files - super().write(airbyte_messages) - duck_db_conn = duckdb.connect(str(self.duckdb_path)) - - if self.schema: - sanitized_schema_name = "_".join([self.sanitize_table_name(s) for s in self.schema]) - duck_db_conn.sql(f"CREATE SCHEMA IF NOT EXISTS {sanitized_schema_name}") - duck_db_conn.sql(f"USE {sanitized_schema_name}") - logging.info(f"Using schema {sanitized_schema_name}") - - for json_file in self.jsonl_files_to_insert: - if json_file.exists(): - table_name = self.sanitize_table_name(json_file.stem) - logging.info(f"Creating table {table_name} from {json_file} in schema {sanitized_schema_name}") - duck_db_conn.sql( - f"CREATE TABLE {table_name} AS SELECT * FROM read_json_auto('{json_file}', sample_size = {self.SAMPLE_SIZE}, format = 'newline_delimited')" - ) - logging.info(f"Table {table_name} created in schema {sanitized_schema_name}") - - for json_file in self.record_per_stream_paths_data_only.values(): - if json_file.exists(): - table_name = self.sanitize_table_name(f"records_{json_file.stem}") - logging.info( - f"Creating table {table_name} from {json_file} in schema {sanitized_schema_name} to store stream records with the data field only" - ) - duck_db_conn.sql( - f"CREATE TABLE {self.sanitize_table_name(table_name)} AS SELECT * FROM read_json_auto('{json_file}', sample_size = {self.SAMPLE_SIZE}, format = 'newline_delimited')" - ) - logging.info(f"Table {table_name} created in schema {sanitized_schema_name}") - duck_db_conn.close() diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/file_backend.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/file_backend.py deleted file mode 100644 index ae3e68c228f8..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/backends/file_backend.py +++ /dev/null @@ -1,152 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -import json -import logging -from collections.abc import Iterable -from pathlib import Path -from typing import Any, TextIO - -from airbyte_protocol.models import AirbyteMessage # type: ignore -from airbyte_protocol.models import Type as AirbyteMessageType -from cachetools import LRUCache, cached - -from live_tests.commons.backends.base_backend import BaseBackend -from live_tests.commons.utils import sanitize_stream_name - - -class FileDescriptorLRUCache(LRUCache): - def popitem(self) -> tuple[Any, Any]: - filepath, fd = LRUCache.popitem(self) - fd.close() # type: ignore # Close the file descriptor when it's evicted from the cache - return filepath, fd - - -class FileBackend(BaseBackend): - RELATIVE_CATALOGS_PATH = "catalog.jsonl" - RELATIVE_CONNECTION_STATUS_PATH = "connection_status.jsonl" - RELATIVE_RECORDS_PATH = "records.jsonl" - RELATIVE_SPECS_PATH = "spec.jsonl" - RELATIVE_STATES_PATH = "states.jsonl" - RELATIVE_TRACES_PATH = "traces.jsonl" - RELATIVE_LOGS_PATH = "logs.jsonl" - RELATIVE_CONTROLS_PATH = "controls.jsonl" - CACHE = FileDescriptorLRUCache(maxsize=250) - - def __init__(self, output_directory: Path): - self._output_directory = output_directory - self.record_per_stream_directory = self._output_directory / "records_per_stream" - self.record_per_stream_directory.mkdir(exist_ok=True, parents=True) - self.record_per_stream_paths: dict[str, Path] = {} - self.record_per_stream_paths_data_only: dict[str, Path] = {} - - @property - def jsonl_specs_path(self) -> Path: - return (self._output_directory / self.RELATIVE_SPECS_PATH).resolve() - - @property - def jsonl_catalogs_path(self) -> Path: - return (self._output_directory / self.RELATIVE_CATALOGS_PATH).resolve() - - @property - def jsonl_connection_status_path(self) -> Path: - return (self._output_directory / self.RELATIVE_CONNECTION_STATUS_PATH).resolve() - - @property - def jsonl_records_path(self) -> Path: - return (self._output_directory / self.RELATIVE_RECORDS_PATH).resolve() - - @property - def jsonl_states_path(self) -> Path: - return (self._output_directory / self.RELATIVE_STATES_PATH).resolve() - - @property - def jsonl_traces_path(self) -> Path: - return (self._output_directory / self.RELATIVE_TRACES_PATH).resolve() - - @property - def jsonl_logs_path(self) -> Path: - return (self._output_directory / self.RELATIVE_LOGS_PATH).resolve() - - @property - def jsonl_controls_path(self) -> Path: - return (self._output_directory / self.RELATIVE_CONTROLS_PATH).resolve() - - @property - def jsonl_files(self) -> Iterable[Path]: - return [ - self.jsonl_catalogs_path, - self.jsonl_connection_status_path, - self.jsonl_records_path, - self.jsonl_specs_path, - self.jsonl_states_path, - self.jsonl_traces_path, - self.jsonl_logs_path, - self.jsonl_controls_path, - ] - - def write(self, airbyte_messages: Iterable[AirbyteMessage]) -> None: - """ - Write AirbyteMessages to the appropriate file. - - We use an LRU cache here to manage open file objects, in order to limit the number of concurrently open file - descriptors. This mitigates the risk of hitting limits on the number of open file descriptors, particularly for - connections with a high number of streams. The cache is designed to automatically close files upon eviction. - """ - - @cached(cache=self.CACHE) - def _open_file(path: Path) -> TextIO: - return open(path, "a") - - try: - logging.info("Writing airbyte messages to disk") - for _message in airbyte_messages: - if not isinstance(_message, AirbyteMessage): - continue - filepaths, messages = self._get_filepaths_and_messages(_message) - for filepath, message in zip(filepaths, messages, strict=False): - _open_file(self._output_directory / filepath).write(f"{message}\n") - logging.info("Finished writing airbyte messages to disk") - finally: - for f in self.CACHE.values(): - f.close() - - def _get_filepaths_and_messages(self, message: AirbyteMessage) -> tuple[tuple[str, ...], tuple[str, ...]]: - if message.type == AirbyteMessageType.CATALOG: - return (self.RELATIVE_CATALOGS_PATH,), (message.catalog.json(),) - - elif message.type == AirbyteMessageType.CONNECTION_STATUS: - return (self.RELATIVE_CONNECTION_STATUS_PATH,), (message.connectionStatus.json(),) - - elif message.type == AirbyteMessageType.RECORD: - stream_name = message.record.stream - stream_file_path = self.record_per_stream_directory / f"{sanitize_stream_name(stream_name)}.jsonl" - stream_file_path_data_only = self.record_per_stream_directory / f"{sanitize_stream_name(stream_name)}_data_only.jsonl" - self.record_per_stream_paths[stream_name] = stream_file_path - self.record_per_stream_paths_data_only[stream_name] = stream_file_path_data_only - return ( - self.RELATIVE_RECORDS_PATH, - str(stream_file_path), - str(stream_file_path_data_only), - ), ( - message.json(sort_keys=True), - message.json(sort_keys=True), - json.dumps(message.record.data, sort_keys=True), - ) - - elif message.type == AirbyteMessageType.SPEC: - return (self.RELATIVE_SPECS_PATH,), (message.spec.json(),) - - elif message.type == AirbyteMessageType.STATE: - return (self.RELATIVE_STATES_PATH,), (message.state.json(),) - - elif message.type == AirbyteMessageType.TRACE: - return (self.RELATIVE_TRACES_PATH,), (message.trace.json(),) - - elif message.type == AirbyteMessageType.LOG: - return (self.RELATIVE_LOGS_PATH,), (message.log.json(),) - - elif message.type == AirbyteMessageType.CONTROL: - return (self.RELATIVE_CONTROLS_PATH,), (message.control.json(),) - - raise NotImplementedError(f"No handling for AirbyteMessage type {message.type} has been implemented. This is unexpected.") diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/connection_objects_retrieval.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/connection_objects_retrieval.py deleted file mode 100644 index b531e3425be8..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/connection_objects_retrieval.py +++ /dev/null @@ -1,316 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -import json -import os -import textwrap -from pathlib import Path -from typing import Dict, List, Optional, Set, Tuple - -import rich -from connection_retriever import ConnectionObject, retrieve_objects # type: ignore -from connection_retriever.retrieval import TestingCandidate, retrieve_testing_candidates - -from live_tests.commons import hacks -from live_tests.commons.models import ConnectionSubset -from live_tests.commons.utils import build_connection_url - -from .models import AirbyteCatalog, Command, ConfiguredAirbyteCatalog, ConnectionObjects, SecretDict - -console = rich.get_console() - - -class InvalidConnectionError(Exception): - pass - - -def parse_config(config: dict | str | None) -> Optional[SecretDict]: - if not config: - return None - if isinstance(config, str): - return SecretDict(json.loads(config)) - else: - return SecretDict(config) - - -def parse_catalog(catalog: dict | str | None) -> Optional[AirbyteCatalog]: - if not catalog: - return None - if isinstance(catalog, str): - return AirbyteCatalog.parse_obj(json.loads(catalog)) - else: - return AirbyteCatalog.parse_obj(catalog) - - -def parse_configured_catalog( - configured_catalog: dict | str | None, selected_streams: set[str] | None = None -) -> Optional[ConfiguredAirbyteCatalog]: - if not configured_catalog: - return None - if isinstance(configured_catalog, str): - configured_catalog = json.loads(configured_catalog) - patched_catalog = hacks.patch_configured_catalog(configured_catalog) - catalog = ConfiguredAirbyteCatalog.parse_obj(patched_catalog) - if selected_streams: - return ConfiguredAirbyteCatalog(streams=[stream for stream in catalog.streams if stream.stream.name in selected_streams]) - return catalog - - -def parse_state(state: dict | str | None) -> Optional[dict]: - if not state: - return None - if isinstance(state, str): - return json.loads(state) - else: - return state - - -def get_connector_config_from_path(config_path: Path) -> Optional[SecretDict]: - return parse_config(config_path.read_text()) - - -def get_state_from_path(state_path: Path) -> Optional[dict]: - return parse_state(state_path.read_text()) - - -def get_configured_catalog_from_path(path: Path, selected_streams: Optional[set[str]] = None) -> Optional[ConfiguredAirbyteCatalog]: - return parse_configured_catalog(path.read_text(), selected_streams) - - -COMMAND_TO_REQUIRED_OBJECT_TYPES = { - Command.SPEC: set(), - Command.CHECK: {ConnectionObject.SOURCE_CONFIG}, - Command.DISCOVER: {ConnectionObject.SOURCE_CONFIG}, - Command.READ: {ConnectionObject.SOURCE_CONFIG, ConnectionObject.CONFIGURED_CATALOG}, - Command.READ_WITH_STATE: { - ConnectionObject.SOURCE_CONFIG, - ConnectionObject.CONFIGURED_CATALOG, - ConnectionObject.STATE, - }, -} - - -def get_connection_objects( - requested_objects: set[ConnectionObject], - connection_id: Optional[str], - custom_config_path: Optional[Path], - custom_configured_catalog_path: Optional[Path], - custom_state_path: Optional[Path], - retrieval_reason: Optional[str], - connector_image: Optional[str] = None, - connector_version: Optional[str] = None, - auto_select_connections: bool = False, - selected_streams: Optional[set[str]] = None, - connection_subset: ConnectionSubset = ConnectionSubset.SANDBOXES, - max_connections: Optional[int] = None, -) -> List[ConnectionObjects]: - """This function retrieves the connection objects values. - It checks that the required objects are available and raises a UsageError if they are not. - If a connection_id is provided, it retrieves the connection objects from the connection. - If custom objects are provided, it overrides the retrieved objects with them. - - Args: - requested_objects (Set[ConnectionObject]): The set of requested connection objects. - connection_id (Optional[str]): The connection id to retrieve the connection objects for. - custom_config_path (Optional[Path]): The local path to the custom config to use. - custom_configured_catalog_path (Optional[Path]): The local path to the custom catalog to use. - custom_state_path (Optional[Path]): The local path to the custom state to use. - retrieval_reason (Optional[str]): The reason to access the connection objects. - fail_if_missing_objects (bool, optional): Whether to raise a ValueError if a required object is missing. Defaults to True. - connector_image (Optional[str]): The image name for the connector under test. - connector_version (Optional[str]): The version for the connector under test. - auto_select_connections (bool, optional): Whether to automatically select connections if no connection id is passed. Defaults to False. - selected_streams (Optional[Set[str]]): The set of selected streams to use when auto selecting a connection. - connection_subset (ConnectionSubset): The subset of connections to select from. - max_connections (Optional[int]): The maximum number of connections to retrieve. - Raises: - click.UsageError: If a required object is missing for the command. - click.UsageError: If a retrieval reason is missing when passing a connection id. - Returns: - List[ConnectionObjects]: List of connection objects. - """ - if connection_id and auto_select_connections: - raise ValueError("Cannot set both `connection_id` and `auto_select_connections`.") - if auto_select_connections and not connector_image: - raise ValueError("A connector image must be provided when using auto_select_connections.") - - custom_config = get_connector_config_from_path(custom_config_path) if custom_config_path else None - custom_configured_catalog = ( - get_configured_catalog_from_path(custom_configured_catalog_path, selected_streams) if custom_configured_catalog_path else None - ) - custom_state = get_state_from_path(custom_state_path) if custom_state_path else None - is_ci = os.getenv("CI", False) - - if connection_id: - if not retrieval_reason: - raise ValueError("A retrieval reason is required to access the connection objects when passing a connection id.") - - connection_objects = _get_connection_objects_from_retrieved_objects( - requested_objects, - retrieval_reason=retrieval_reason, - source_docker_repository=connector_image, - source_docker_image_tag=connector_version, - selected_streams=selected_streams, - connection_id=connection_id, - custom_config=custom_config, - custom_configured_catalog=custom_configured_catalog, - custom_state=custom_state, - connection_subset=connection_subset, - max_connections=max_connections, - ) - - else: - if auto_select_connections: - connection_objects = _get_connection_objects_from_retrieved_objects( - requested_objects, - retrieval_reason=retrieval_reason, - source_docker_repository=connector_image, - source_docker_image_tag=connector_version, - selected_streams=selected_streams, - custom_config=custom_config, - custom_configured_catalog=custom_configured_catalog, - custom_state=custom_state, - connection_subset=connection_subset, - max_connections=max_connections, - ) - - else: - # We don't make any requests to the connection-retriever; it is expected that config/catalog/state have been provided if needed for the commands being run. - connection_objects = [ - ConnectionObjects( - source_config=custom_config, - destination_config=custom_config, - catalog=None, - configured_catalog=custom_configured_catalog, - state=custom_state, - workspace_id=None, - source_id=None, - destination_id=None, - connection_id=None, - source_docker_image=None, - ) - ] - if not connection_objects: - raise ValueError("No connection objects could be fetched.") - - all_connection_ids = [connection_object.connection_id for connection_object in connection_objects] - assert len(set(all_connection_ids)) == len(all_connection_ids), "Connection IDs must be unique." - return connection_objects - - -def _find_best_candidates_subset(candidates: List[TestingCandidate]) -> List[Tuple[TestingCandidate, List[str]]]: - """ - This function reduces the list of candidates to the best subset of candidates. - The best subset is the one which maximizes the number of streams tested and minimizes the number of candidates. - """ - candidates_sorted_by_duration = sorted(candidates, key=lambda x: x.last_attempt_duration_in_microseconds) - - tested_streams = set() - candidates_and_streams_to_test = [] - - for candidate in candidates_sorted_by_duration: - candidate_streams_to_test = [] - for stream in candidate.streams_with_data: - # The candidate is selected if one of its streams has not been tested yet - if stream not in tested_streams: - candidate_streams_to_test.append(stream) - tested_streams.add(stream) - if candidate_streams_to_test: - candidates_and_streams_to_test.append((candidate, candidate_streams_to_test)) - return candidates_and_streams_to_test - - -def _get_connection_objects_from_retrieved_objects( - requested_objects: Set[ConnectionObject], - retrieval_reason: str, - source_docker_repository: str, - source_docker_image_tag: str, - selected_streams: Optional[Set[str]], - connection_id: Optional[str] = None, - custom_config: Optional[Dict] = None, - custom_configured_catalog: Optional[ConfiguredAirbyteCatalog] = None, - custom_state: Optional[Dict] = None, - connection_subset: ConnectionSubset = ConnectionSubset.SANDBOXES, - max_connections: Optional[int] = None, -): - console.log( - textwrap.dedent( - """ - Retrieving connection objects from the database. - We will build a subset of candidates to test. - This subset should minimize the number of candidates and sync duration while maximizing the number of streams tested. - We patch configured catalogs to only test streams once. - If the max_connections parameter is set, we will only keep the top connections with the most streams to test. - """ - ) - ) - try: - candidates = retrieve_testing_candidates( - source_docker_repository=source_docker_repository, - source_docker_image_tag=source_docker_image_tag, - with_streams=selected_streams, - connection_subset=connection_subset, - ) - except IndexError: - raise InvalidConnectionError( - f"No candidates were found for the provided source docker image ({source_docker_repository}:{source_docker_image_tag})." - ) - # If the connection_id is provided, we filter the candidates to only keep the ones with the same connection_id - if connection_id: - candidates = [candidate for candidate in candidates if candidate.connection_id == connection_id] - - candidates_and_streams_to_test = _find_best_candidates_subset(candidates) - candidates_and_streams_to_test = sorted(candidates_and_streams_to_test, key=lambda x: len(x[1]), reverse=True) - if max_connections: - candidates_and_streams_to_test = candidates_and_streams_to_test[:max_connections] - - number_of_streams_tested = sum([len(streams_to_test) for _, streams_to_test in candidates_and_streams_to_test]) - console.log(f"Selected {len(candidates_and_streams_to_test)} candidates to test {number_of_streams_tested} streams.") - - all_connection_objects = [] - for candidate, streams_to_test in candidates_and_streams_to_test: - retrieved_objects = retrieve_objects( - requested_objects, - retrieval_reason=retrieval_reason, - source_docker_repository=source_docker_repository, - source_docker_image_tag=source_docker_image_tag, - connection_id=candidate.connection_id, - connection_subset=connection_subset, - ) - retrieved_objects = retrieved_objects[0] - retrieved_source_config = parse_config(retrieved_objects.source_config) - retrieved_destination_config = parse_config(retrieved_objects.destination_config) - retrieved_catalog = parse_catalog(retrieved_objects.catalog) - retrieved_configured_catalog = parse_configured_catalog(retrieved_objects.configured_catalog, selected_streams) - retrieved_state = parse_state(retrieved_objects.state) - - retrieved_source_docker_image = retrieved_objects.source_docker_image - connection_url = build_connection_url(retrieved_objects.workspace_id, retrieved_objects.connection_id) - if retrieved_source_docker_image is None: - raise InvalidConnectionError( - f"No docker image was found for connection ID {retrieved_objects.connection_id}. Please double check that the latest job run used version {source_docker_image_tag}. Connection URL: {connection_url}" - ) - elif retrieved_source_docker_image.split(":")[0] != source_docker_repository: - raise InvalidConnectionError( - f"The provided docker image ({source_docker_repository}) does not match the image for connection ID {retrieved_objects.connection_id}. Please double check that this connection is using the correct image. Connection URL: {connection_url}" - ) - elif retrieved_source_docker_image.split(":")[1] != source_docker_image_tag: - raise InvalidConnectionError( - f"The provided docker image tag ({source_docker_image_tag}) does not match the image tag for connection ID {retrieved_objects.connection_id}. Please double check that this connection is using the correct image tag and the latest job ran using this version. Connection URL: {connection_url}" - ) - - all_connection_objects.append( - ConnectionObjects( - source_config=custom_config if custom_config else retrieved_source_config, - destination_config=custom_config if custom_config else retrieved_destination_config, - catalog=retrieved_catalog, - configured_catalog=custom_configured_catalog if custom_configured_catalog else retrieved_configured_catalog, - state=custom_state if custom_state else retrieved_state, - workspace_id=retrieved_objects.workspace_id, - source_id=retrieved_objects.source_id, - destination_id=retrieved_objects.destination_id, - source_docker_image=retrieved_source_docker_image, - connection_id=retrieved_objects.connection_id, - ) - ) - return all_connection_objects diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/connector_runner.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/connector_runner.py deleted file mode 100644 index a2bd441efab3..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/connector_runner.py +++ /dev/null @@ -1,220 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from __future__ import annotations - -import datetime -import json -import logging -import os -import subprocess -import uuid -from pathlib import Path - -import anyio -import asyncer -import dagger - -from live_tests.commons import errors -from live_tests.commons.models import Command, ExecutionInputs, ExecutionResult -from live_tests.commons.proxy import Proxy - - -class ConnectorRunner: - DATA_DIR = "/airbyte/data" - IN_CONTAINER_CONFIG_PATH = f"{DATA_DIR}/config.json" - IN_CONTAINER_CONFIGURED_CATALOG_PATH = f"{DATA_DIR}/catalog.json" - IN_CONTAINER_STATE_PATH = f"{DATA_DIR}/state.json" - IN_CONTAINER_OUTPUT_PATH = f"{DATA_DIR}/output.txt" - IN_CONTAINER_OBFUSCATOR_PATH = "/user/local/bin/record_obfuscator.py" - - def __init__( - self, - dagger_client: dagger.Client, - execution_inputs: ExecutionInputs, - is_airbyte_ci: bool, - http_proxy: Proxy | None = None, - ): - self.connector_under_test = execution_inputs.connector_under_test - self.command = execution_inputs.command - self.output_dir = execution_inputs.output_dir - self.config = execution_inputs.config - self.configured_catalog = execution_inputs.configured_catalog - self.state = execution_inputs.state - self.duckdb_path = execution_inputs.duckdb_path - self.actor_id = execution_inputs.actor_id - self.hashed_connection_id = execution_inputs.hashed_connection_id - self.environment_variables = execution_inputs.environment_variables if execution_inputs.environment_variables else {} - - self.full_command: list[str] = self._get_full_command(execution_inputs.command) - self.completion_event = anyio.Event() - self.http_proxy = http_proxy - self.logger = logging.getLogger(f"{self.connector_under_test.name}-{self.connector_under_test.version}") - self.dagger_client = dagger_client - if is_airbyte_ci: - self.host_obfuscator_path = "/tmp/record_obfuscator.py" - else: - repo_root = Path(subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).strip().decode()) - self.host_obfuscator_path = f"{repo_root}/tools/bin/record_obfuscator.py" - - @property - def _connector_under_test_container(self) -> dagger.Container: - return self.connector_under_test.container - - @property - def stdout_file_path(self) -> Path: - return (self.output_dir / "stdout.log").resolve() - - @property - def stderr_file_path(self) -> Path: - return (self.output_dir / "stderr.log").resolve() - - def _get_full_command(self, command: Command) -> list[str]: - """Returns a list with a full Airbyte command invocation and all it's arguments and options.""" - if command is Command.SPEC: - return ["spec"] - elif command is Command.CHECK: - return ["check", "--config", self.IN_CONTAINER_CONFIG_PATH] - elif command is Command.DISCOVER: - return ["discover", "--config", self.IN_CONTAINER_CONFIG_PATH] - elif command is Command.READ: - return [ - "read", - "--config", - self.IN_CONTAINER_CONFIG_PATH, - "--catalog", - self.IN_CONTAINER_CONFIGURED_CATALOG_PATH, - ] - elif command is Command.READ_WITH_STATE: - return [ - "read", - "--config", - self.IN_CONTAINER_CONFIG_PATH, - "--catalog", - self.IN_CONTAINER_CONFIGURED_CATALOG_PATH, - "--state", - self.IN_CONTAINER_STATE_PATH, - ] - else: - raise NotImplementedError(f"The connector runner does not support the {command} command") - - async def get_container_env_variable_value(self, name: str) -> str | None: - return await self._connector_under_test_container.env_variable(name) - - async def get_container_label(self, label: str) -> str | None: - return await self._connector_under_test_container.label(label) - - async def get_container_entrypoint(self) -> str: - entrypoint = await self._connector_under_test_container.entrypoint() - assert entrypoint, "The connector container has no entrypoint" - return " ".join(entrypoint) - - async def run(self) -> ExecutionResult: - async with asyncer.create_task_group() as task_group: - soon_result = task_group.soonify(self._run)() - task_group.soonify(self._log_progress)() - return soon_result.value - - async def _run( - self, - ) -> ExecutionResult: - container = self._connector_under_test_container - current_user = (await container.with_exec(["whoami"]).stdout()).strip() - container = container.with_user(current_user) - container = container.with_exec(["mkdir", "-p", self.DATA_DIR]) - # Do not cache downstream dagger layers - container = container.with_env_variable("CACHEBUSTER", str(uuid.uuid4())) - - # When running locally, it's likely that record_obfuscator is within the user's home directory, so we expand it. - expanded_host_executable_path = os.path.expanduser(self.host_obfuscator_path) - container = container.with_file( - self.IN_CONTAINER_OBFUSCATOR_PATH, - self.dagger_client.host().file(expanded_host_executable_path), - ) - - for env_var_name, env_var_value in self.environment_variables.items(): - container = container.with_env_variable(env_var_name, env_var_value) - if self.config: - container = container.with_new_file(self.IN_CONTAINER_CONFIG_PATH, contents=json.dumps(dict(self.config)), owner=current_user) - if self.state: - container = container.with_new_file(self.IN_CONTAINER_STATE_PATH, contents=json.dumps(self.state), owner=current_user) - if self.configured_catalog: - container = container.with_new_file( - self.IN_CONTAINER_CONFIGURED_CATALOG_PATH, - contents=self.configured_catalog.json(), - owner=current_user, - ) - if self.http_proxy: - container = await self.http_proxy.bind_container(container) - - self.logger.info(f"⏳ Start running {self.command.value} command") - - try: - entrypoint = await container.entrypoint() - assert entrypoint, "The connector container has no entrypoint" - airbyte_command = entrypoint + self.full_command - - container = container.with_exec( - [ - "sh", - "-c", - " ".join(airbyte_command) - + f"| {self.IN_CONTAINER_OBFUSCATOR_PATH} > {self.IN_CONTAINER_OUTPUT_PATH} 2>&1 | tee -a {self.IN_CONTAINER_OUTPUT_PATH}", - ] - ) - executed_container = await container.sync() - # We exporting to disk as we can't read .stdout() or await file.contents() as it might blow up the memory - stdout_exported = await executed_container.file(self.IN_CONTAINER_OUTPUT_PATH).export(str(self.stdout_file_path)) - if not stdout_exported: - raise errors.ExportError(f"Failed to export {self.IN_CONTAINER_OUTPUT_PATH}") - - stderr = await executed_container.stderr() - self.stderr_file_path.write_text(stderr) - success = True - except dagger.ExecError as e: - self.stderr_file_path.write_text(e.stderr) - self.stdout_file_path.write_text(e.stdout) - executed_container = None - success = False - - self.completion_event.set() - if not success: - self.logger.error(f"❌ Failed to run {self.command.value} command") - else: - self.logger.info(f"⌛ Finished running {self.command.value} command") - - execution_result = await ExecutionResult.load( - command=self.command, - connector_under_test=self.connector_under_test, - actor_id=self.actor_id, - hashed_connection_id=self.hashed_connection_id, - configured_catalog=self.configured_catalog, - stdout_file_path=self.stdout_file_path, - stderr_file_path=self.stderr_file_path, - success=success, - http_dump=await self.http_proxy.retrieve_http_dump() if self.http_proxy else None, - executed_container=executed_container, - config=self.config, - ) - await execution_result.save_artifacts(self.output_dir, self.duckdb_path) - return execution_result - - async def _log_progress(self) -> None: - start_time = datetime.datetime.utcnow() - message = f"⏳ Still running {self.command.value} command" - while not self.completion_event.is_set(): - duration = datetime.datetime.utcnow() - start_time - elapsed_seconds = duration.total_seconds() - if elapsed_seconds > 10 and round(elapsed_seconds) % 10 == 0: - self.logger.info(f"{message} (duration: {self.format_duration(duration)})") - await anyio.sleep(1) - - @staticmethod - def format_duration(time_delta: datetime.timedelta) -> str: - total_seconds = time_delta.total_seconds() - if total_seconds < 60: - return f"{total_seconds:.2f}s" - minutes = int(total_seconds // 60) - seconds = int(total_seconds % 60) - return f"{minutes:02d}mn{seconds:02d}s" diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/errors.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/errors.py deleted file mode 100644 index cb13b4ab629e..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/errors.py +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -from __future__ import annotations - - -class ExportError(Exception): - def __init__(self, message: str): - super().__init__(message) diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/evaluation_modes.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/evaluation_modes.py deleted file mode 100644 index 2edf391d1568..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/evaluation_modes.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -from enum import Enum - - -class TestEvaluationMode(Enum): - """ - Tests may be run in "diagnostic" mode or "strict" mode. - - When run in "diagnostic" mode, `AssertionError`s won't fail the test, but we will continue to surface - any errors to the test report. - - In "strict" mode, tests pass/fail as usual. - - In live tests, diagnostic mode is used for tests that don't affect the overall functionality of the - connector but that test an ideal state of the connector. Currently this is applicable to validation - tests only. - - The diagnostic mode can be made available to a test using the @pytest.mark.allow_diagnostic_mode decorator, - and passing in the --test-evaluation-mode=diagnostic flag. - """ - - DIAGNOSTIC = "diagnostic" - STRICT = "strict" diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/hacks.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/hacks.py deleted file mode 100644 index 77c2adbd8d7a..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/hacks.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -import copy - -import rich - -console = rich.get_console() - - -def patch_configured_catalog(configured_catalog: dict) -> dict: - """ - The configured catalog extracted from the platform can be incompatible with the airbyte-protocol. - This leads to validation error when we serialize the configured catalog into a ConfiguredAirbyteCatalog object. - This functions is a best effort to patch the configured catalog to make it compatible with the airbyte-protocol. - """ - patched_catalog = copy.deepcopy(configured_catalog) - for stream in patched_catalog["streams"]: - if stream.get("destination_sync_mode") == "overwrite_dedup": - stream["destination_sync_mode"] = "overwrite" - console.log( - f"Stream {stream['stream']['name']} destination_sync_mode has been patched from 'overwrite_dedup' to 'overwrite' to guarantee compatibility with the airbyte-protocol." - ) - return patched_catalog diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/json_schema_helper.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/json_schema_helper.py deleted file mode 100644 index 5ad60c2a14f9..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/json_schema_helper.py +++ /dev/null @@ -1,367 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -from enum import Enum -from functools import reduce, total_ordering -from typing import Any, Dict, List, Mapping, Optional, Set, Text, Union - -import dpath.util -import pendulum -from jsonref import JsonRef - - -class CatalogField: - """Field class to represent cursor/pk fields. - It eases the read of values from records according to schema definition. - """ - - def __init__(self, schema: Mapping[str, Any], path: List[str]): - self.schema = schema - self.path = path - self.formats = self._detect_formats() - - def _detect_formats(self) -> Set[str]: - """Extract set of formats/types for this field""" - format_ = [] - try: - format_ = self.schema.get("format", self.schema["type"]) - if not isinstance(format_, List): - format_ = [format_] - except KeyError: - pass - return set(format_) - - def _parse_value(self, value: Any) -> Any: - """Do actual parsing of the serialized value""" - if self.formats.intersection({"datetime", "date-time", "date"}): - if value is None and "null" not in self.formats: - raise ValueError(f"Invalid field format. Value: {value}. Format: {self.formats}") - # handle beautiful MySQL datetime, i.e. NULL datetime - if value.startswith("0000-00-00"): - value = value.replace("0000-00-00", "0001-01-01") - return pendulum.parse(value) - return value - - def parse(self, record: Mapping[str, Any], path: Optional[List[Union[int, str]]] = None) -> Any: - """Extract field value from the record and cast it to native type""" - path = path or self.path - value = reduce(lambda data, key: data[key], path, record) - return self._parse_value(value) - - -@total_ordering -class ComparableType(Enum): - NULL = 0 - BOOLEAN = 1 - INTEGER = 2 - NUMBER = 3 - STRING = 4 - OBJECT = 5 - - def __lt__(self, other: Any) -> bool: - if self.__class__ is other.__class__: - return self.value < other.value # type: ignore - else: - return NotImplemented - - -class JsonSchemaHelper: - """Helper class to simplify schema validation and read of records according to their schema.""" - - def __init__(self, schema): - self._schema = schema - - def get_ref(self, path: str) -> Any: - """Resolve reference - - :param path: reference (#/definitions/SomeClass, etc) - :return: part of schema that is definition of the reference - :raises KeyError: in case path can't be followed - """ - node = self._schema - for segment in path.split("/")[1:]: - node = node[segment] - return node - - def get_property(self, path: List[str]) -> Mapping[str, Any]: - """Get any part of schema according to provided path, resolves $refs if necessary - - schema = { - "properties": { - "field1": { - "properties": { - "nested_field": { - - } - } - }, - "field2": ... - } - } - - helper = JsonSchemaHelper(schema) - helper.get_property(["field1", "nested_field"]) == - - :param path: list of fields in the order of navigation - :return: discovered part of schema - :raises KeyError: in case path can't be followed - """ - node = self._schema - for segment in path: - if "$ref" in node: - node = self.get_ref(node["$ref"]) - node = node["properties"][segment] - return node - - def field(self, path: List[str]) -> CatalogField: - """Get schema property and wrap it into CatalogField. - - CatalogField is a helper to ease the read of values from records according to schema definition. - - :param path: list of fields in the order of navigation - :return: discovered part of schema wrapped in CatalogField - :raises KeyError: in case path can't be followed - """ - return CatalogField(schema=self.get_property(path), path=path) - - def get_node(self, path: List[Union[str, int]]) -> Any: - """Return part of schema by specified path - - :param path: list of fields in the order of navigation - """ - - node = self._schema - for segment in path: - if "$ref" in node: - node = self.get_ref(node["$ref"]) - node = node[segment] - return node - - def get_parent_path(self, path: str, separator="/") -> Any: - """ - Returns the parent path of the supplied path - """ - absolute_path = f"{separator}{path}" if not path.startswith(separator) else path - parent_path, _ = absolute_path.rsplit(sep=separator, maxsplit=1) - return parent_path - - def get_parent(self, path: str, separator="/") -> Any: - """ - Returns the parent dict of a given path within the `obj` dict - """ - parent_path = self.get_parent_path(path, separator=separator) - if parent_path == "": - return self._schema - return dpath.util.get(self._schema, parent_path, separator=separator) - - def find_nodes(self, keys: List[str]) -> List[List[Union[str, int]]]: - """Find all paths that lead to nodes with the specified keys. - - :param keys: list of keys - :return: list of json object paths - """ - variant_paths = [] - - def traverse_schema(_schema: Union[Dict[Text, Any], List], path=None): - path = path or [] - if path and path[-1] in keys: - variant_paths.append(path) - if isinstance(_schema, dict): - for item in _schema: - traverse_schema(_schema[item], [*path, item]) - elif isinstance(_schema, list): - for i, item in enumerate(_schema): - traverse_schema(_schema[i], [*path, i]) - - traverse_schema(self._schema) - return variant_paths - - -def get_object_structure(obj: dict) -> List[str]: - """ - Traverse through object structure and compose a list of property keys including nested one. - This list reflects object's structure with list of all obj property key - paths. In case if object is nested inside array we assume that it has same - structure as first element. - :param obj: data object to get its structure - :returns list of object property keys paths - """ - paths = [] - - def _traverse_obj_and_get_path(obj, path=""): - if path: - paths.append(path) - if isinstance(obj, dict): - return {k: _traverse_obj_and_get_path(v, path + "/" + k) for k, v in obj.items()} - elif isinstance(obj, list) and len(obj) > 0: - return [_traverse_obj_and_get_path(obj[0], path + "/[]")] - - _traverse_obj_and_get_path(obj) - - return paths - - -def get_expected_schema_structure(schema: dict, annotate_one_of: bool = False) -> List[str]: - """ - Traverse through json schema and compose list of property keys that object expected to have. - :param annotate_one_of: Generate one_of index in path - :param schema: jsonschema to get expected paths - :returns list of object property keys paths - """ - paths = [] - if "$ref" in schema: - """ - JsonRef doesnt work correctly with schemas that has refenreces in root e.g. - { - "$ref": "#/definitions/ref" - "definitions": { - "ref": ... - } - } - Considering this schema already processed by resolver so it should - contain only references to definitions section, replace root reference - manually before processing it with JsonRef library. - """ - ref = schema["$ref"].split("/")[-1] - schema.update(schema["definitions"][ref]) - schema.pop("$ref") - # Resolve all references to simplify schema processing. - schema = JsonRef.replace_refs(schema) - - def _scan_schema(subschema, path=""): - if "oneOf" in subschema or "anyOf" in subschema: - if annotate_one_of: - return [ - _scan_schema({"type": "object", **s}, path + f"({num})") - for num, s in enumerate(subschema.get("oneOf") or subschema.get("anyOf")) - ] - return [_scan_schema({"type": "object", **s}, path) for s in subschema.get("oneOf") or subschema.get("anyOf")] - schema_type = subschema.get("type", ["object", "null"]) - if not isinstance(schema_type, list): - schema_type = [schema_type] - if "object" in schema_type: - props = subschema.get("properties") - if not props: - # Handle objects with arbitrary properties: - # {"type": "object", "additionalProperties": {"type": "string"}} - if path: - paths.append(path) - return - return {k: _scan_schema(v, path + "/" + k) for k, v in props.items()} - elif "array" in schema_type: - items = subschema.get("items", {}) - return [_scan_schema(items, path + "/[]")] - paths.append(path) - - _scan_schema(schema) - return paths - - -def flatten_tuples(to_flatten): - """Flatten a tuple of tuples into a single tuple.""" - types = set() - - if not isinstance(to_flatten, tuple): - to_flatten = (to_flatten,) - for thing in to_flatten: - if isinstance(thing, tuple): - types.update(flatten_tuples(thing)) - else: - types.add(thing) - return tuple(types) - - -def get_paths_in_connector_config(schema: dict) -> List[str]: - """ - Traverse through the provided schema's values and extract the path_in_connector_config paths - :param properties: jsonschema containing values which may have path_in_connector_config attributes - :returns list of path_in_connector_config paths - """ - return ["/" + "/".join(value["path_in_connector_config"]) for value in schema.values()] - - -def conforms_to_schema(record: Mapping[str, Any], schema: Mapping[str, Any]) -> bool: - """ - Return true iff the record conforms to the supplied schema. - - The record conforms to the supplied schema iff: - - All columns in the record are in the schema. - - For every column in the record, that column's type is equal to or narrower than the same column's - type in the schema. - """ - schema_columns = set(schema.get("properties", {}).keys()) - record_columns = set(record.keys()) - - if not record_columns.issubset(schema_columns): - return False - - for column, definition in schema.get("properties", {}).items(): - expected_type = definition.get("type") - value = record.get(column) - - if value is not None: - if isinstance(expected_type, list): - return any(_is_equal_or_narrower_type(value, e) for e in expected_type) - elif expected_type == "object": - return isinstance(value, dict) - elif expected_type == "array": - if not isinstance(value, list): - return False - array_type = definition.get("items", {}).get("type") - if not all(_is_equal_or_narrower_type(v, array_type) for v in value): - return False - elif not _is_equal_or_narrower_type(value, expected_type): - return False - - return True - - -def _is_equal_or_narrower_type(value: Any, expected_type: str) -> bool: - if isinstance(value, list): - # We do not compare lists directly; the individual items are compared. - # If we hit this condition, it means that the expected type is not - # compatible with the inferred type. - return False - - inferred_type = ComparableType(_get_inferred_type(value)) - - if inferred_type is None: - return False - - return ComparableType(inferred_type) <= ComparableType(_get_comparable_type(expected_type)) - - -def _get_inferred_type(value: Any) -> Optional[ComparableType]: - if value is None: - return ComparableType.NULL - if isinstance(value, bool): - return ComparableType.BOOLEAN - if isinstance(value, int): - return ComparableType.INTEGER - if isinstance(value, float): - return ComparableType.NUMBER - if isinstance(value, str): - return ComparableType.STRING - if isinstance(value, dict): - return ComparableType.OBJECT - else: - return None - - -def _get_comparable_type(value: Any) -> Optional[ComparableType]: - if value == "null": - return ComparableType.NULL - if value == "boolean": - return ComparableType.BOOLEAN - if value == "integer": - return ComparableType.INTEGER - if value == "number": - return ComparableType.NUMBER - if value == "string": - return ComparableType.STRING - if value == "object": - return ComparableType.OBJECT - else: - return None diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/mitm_addons.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/mitm_addons.py deleted file mode 100644 index 032a80ebee23..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/mitm_addons.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -from urllib.parse import parse_qs, urlencode, urlparse - -from mitmproxy import http - - -class SortQueryParams: - """This addon sorts query parameters in the request URL. - It is useful for testing purposes, as it makes it easier to compare requests and get cache hits. - """ - - def request(self, flow: http.HTTPFlow) -> None: - if url := flow.request.url: - parsed_url = urlparse(url) - # Get query parameters as dictionary - query_params = parse_qs(parsed_url.query) - # Sort query parameters alphabetically - sorted_params = {key: query_params[key] for key in sorted(query_params.keys())} - # Reconstruct the URL with sorted query parameters - sorted_url = parsed_url._replace(query=urlencode(sorted_params, doseq=True)).geturl() - - # Update the request URL - flow.request.url = sorted_url - - -# Disabling the addon. -# It can alter the request URL when some connector URL are already encoded. -# See discussion here https://github.com/airbytehq/airbyte-internal-issues/issues/9302#issuecomment-2311854334 - -# addons = [SortQueryParams()] -addons = [] diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/models.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/models.py deleted file mode 100644 index b4bdd87c2c21..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/models.py +++ /dev/null @@ -1,543 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -import _collections_abc -import hashlib -import json -import logging -import tempfile -from collections import defaultdict -from collections.abc import Iterable, Iterator, MutableMapping -from dataclasses import dataclass, field -from enum import Enum -from functools import cache -from pathlib import Path -from typing import Any, Dict, List, Optional - -import dagger -import requests -from airbyte_protocol.models import ( - AirbyteCatalog, # type: ignore - AirbyteMessage, # type: ignore - AirbyteStateMessage, # type: ignore - AirbyteStreamStatusTraceMessage, # type: ignore - ConfiguredAirbyteCatalog, # type: ignore - TraceType, # type: ignore -) -from airbyte_protocol.models import Type as AirbyteMessageType -from genson import SchemaBuilder # type: ignore -from mitmproxy import http -from pydantic import ValidationError - -from live_tests.commons.backends import DuckDbBackend, FileBackend -from live_tests.commons.secret_access import get_airbyte_api_key -from live_tests.commons.utils import ( - get_connector_container, - get_http_flows_from_mitm_dump, - mitm_http_stream_to_har, - sanitize_stream_name, - sort_dict_keys, -) - - -class UserDict(_collections_abc.MutableMapping): # type: ignore - # Start by filling-out the abstract methods - def __init__(self, _dict: Optional[MutableMapping] = None, **kwargs: Any): - self.data: MutableMapping = {} - if _dict is not None: - self.update(_dict) - if kwargs: - self.update(kwargs) - - def __len__(self) -> int: - return len(self.data) - - def __getitem__(self, key: Any) -> Any: - if key in self.data: - return self.data[key] - if hasattr(self.__class__, "__missing__"): - return self.__class__.__missing__(self, key) - raise KeyError(key) - - def __setitem__(self, key: Any, item: Any) -> None: - self.data[key] = item - - def __delitem__(self, key: Any) -> None: - del self.data[key] - - def __iter__(self) -> Iterator: - return iter(self.data) - - # Modify __contains__ to work correctly when __missing__ is present - def __contains__(self, key: Any) -> bool: - return key in self.data - - # Now, add the methods in dicts but not in MutableMapping - def __repr__(self) -> str: - return repr(self.data) - - def __or__(self, other: UserDict | dict) -> UserDict: - if isinstance(other, UserDict): - return self.__class__(self.data | other.data) # type: ignore - if isinstance(other, dict): - return self.__class__(self.data | other) # type: ignore - return NotImplemented - - def __ror__(self, other: UserDict | dict) -> UserDict: - if isinstance(other, UserDict): - return self.__class__(other.data | self.data) # type: ignore - if isinstance(other, dict): - return self.__class__(other | self.data) # type: ignore - return NotImplemented - - def __ior__(self, other: UserDict | dict) -> UserDict: - if isinstance(other, UserDict): - self.data |= other.data # type: ignore - else: - self.data |= other # type: ignore - return self - - def __copy__(self) -> UserDict: - inst = self.__class__.__new__(self.__class__) - inst.__dict__.update(self.__dict__) - # Create a copy and avoid triggering descriptors - inst.__dict__["data"] = self.__dict__["data"].copy() - return inst - - def copy(self) -> UserDict: - if self.__class__ is UserDict: - return UserDict(self.data.copy()) # type: ignore - import copy - - data = self.data - try: - self.data = {} - c = copy.copy(self) - finally: - self.data = data - c.update(self) - return c - - @classmethod - def fromkeys(cls, iterable: Iterable, value: Optional[Any] = None) -> UserDict: - d = cls() - for key in iterable: - d[key] = value - return d - - -class SecretDict(UserDict): - def __str__(self) -> str: - return f"{self.__class__.__name__}(******)" - - def __repr__(self) -> str: - return str(self) - - -class Command(Enum): - CHECK = "check" - DISCOVER = "discover" - READ = "read" - READ_WITH_STATE = "read-with-state" - SPEC = "spec" - - def needs_config(self) -> bool: - return self in {Command.CHECK, Command.DISCOVER, Command.READ, Command.READ_WITH_STATE} - - def needs_catalog(self) -> bool: - return self in {Command.READ, Command.READ_WITH_STATE} - - def needs_state(self) -> bool: - return self in {Command.READ_WITH_STATE} - - -class TargetOrControl(Enum): - TARGET = "target" - CONTROL = "control" - - -class ActorType(Enum): - SOURCE = "source" - DESTINATION = "destination" - - -class ConnectionSubset(Enum): - """Signals which connection pool to consider for this live test — just the Airbyte sandboxes, or all possible connctions on Cloud.""" - - SANDBOXES = "sandboxes" - ALL = "all" - - -@dataclass -class ConnectorUnderTest: - """Represents a connector being tested. - In validation tests, there would be one connector under test. - When running regression tests, there would be two connectors under test: the target and the control versions of the same connector. - """ - - # connector image, assuming it's in the format "airbyte/{actor_type}-{connector_name}:{version}" - image_name: str - container: dagger.Container - target_or_control: TargetOrControl - - @property - def name(self) -> str: - return self.image_name.replace("airbyte/", "").split(":")[0] - - @property - def name_without_type_prefix(self) -> str: - return self.name.replace(f"{self.actor_type.value}-", "") - - @property - def version(self) -> str: - return self.image_name.replace("airbyte/", "").split(":")[1] - - @property - def actor_type(self) -> ActorType: - if "airbyte/destination-" in self.image_name: - return ActorType.DESTINATION - elif "airbyte/source-" in self.image_name: - return ActorType.SOURCE - else: - raise ValueError( - f"Can't infer the actor type. Connector image name {self.image_name} does not contain 'airbyte/source' or 'airbyte/destination'" - ) - - @classmethod - async def from_image_name( - cls: type[ConnectorUnderTest], - dagger_client: dagger.Client, - image_name: str, - target_or_control: TargetOrControl, - ) -> ConnectorUnderTest: - container = await get_connector_container(dagger_client, image_name) - return cls(image_name, container, target_or_control) - - -@dataclass -class ExecutionInputs: - hashed_connection_id: str - connector_under_test: ConnectorUnderTest - actor_id: str - global_output_dir: Path - command: Command - config: Optional[SecretDict] = None - configured_catalog: Optional[ConfiguredAirbyteCatalog] = None - state: Optional[dict] = None - environment_variables: Optional[dict] = None - duckdb_path: Optional[Path] = None - - def raise_if_missing_attr_for_command(self, attribute: str) -> None: - if getattr(self, attribute) is None: - raise ValueError(f"We need a {attribute} to run the {self.command.value} command") - - def __post_init__(self) -> None: - if self.command is Command.CHECK: - self.raise_if_missing_attr_for_command("config") - if self.command is Command.DISCOVER: - self.raise_if_missing_attr_for_command("config") - if self.command is Command.READ: - self.raise_if_missing_attr_for_command("config") - self.raise_if_missing_attr_for_command("configured_catalog") - if self.command is Command.READ_WITH_STATE: - self.raise_if_missing_attr_for_command("config") - self.raise_if_missing_attr_for_command("configured_catalog") - self.raise_if_missing_attr_for_command("state") - - @property - def output_dir(self) -> Path: - output_dir = ( - self.global_output_dir - / f"command_execution_artifacts/{self.connector_under_test.name}/{self.command.value}/{self.connector_under_test.version}/{self.hashed_connection_id}" - ) - output_dir.mkdir(parents=True, exist_ok=True) - return output_dir - - -@dataclass -class ExecutionResult: - hashed_connection_id: str - actor_id: str - configured_catalog: ConfiguredAirbyteCatalog - connector_under_test: ConnectorUnderTest - command: Command - stdout_file_path: Path - stderr_file_path: Path - success: bool - executed_container: Optional[dagger.Container] - config: Optional[SecretDict] - http_dump: Optional[dagger.File] = None - http_flows: list[http.HTTPFlow] = field(default_factory=list) - stream_schemas: Optional[dict[str, Any]] = None - backend: Optional[FileBackend] = None - - HTTP_DUMP_FILE_NAME = "http_dump.mitm" - HAR_FILE_NAME = "http_dump.har" - - @property - def logger(self) -> logging.Logger: - return logging.getLogger(f"{self.connector_under_test.target_or_control.value}-{self.command.value}") - - @property - def airbyte_messages(self) -> Iterable[AirbyteMessage]: - return self.parse_airbyte_messages_from_command_output(self.stdout_file_path) - - @property - def duckdb_schema(self) -> Iterable[str]: - return (self.connector_under_test.target_or_control.value, self.command.value, self.hashed_connection_id) - - @property - def configured_streams(self) -> List[str]: - return [stream.stream.name for stream in self.configured_catalog.streams] - - @property - def primary_keys_per_stream(self) -> Dict[str, List[str]]: - return {stream.stream.name: stream.primary_key[0] if stream.primary_key else None for stream in self.configured_catalog.streams} - - @classmethod - async def load( - cls: type[ExecutionResult], - connector_under_test: ConnectorUnderTest, - hashed_connection_id: str, - actor_id: str, - configured_catalog: ConfiguredAirbyteCatalog, - command: Command, - stdout_file_path: Path, - stderr_file_path: Path, - success: bool, - executed_container: Optional[dagger.Container], - config: Optional[SecretDict] = None, - http_dump: Optional[dagger.File] = None, - ) -> ExecutionResult: - execution_result = cls( - hashed_connection_id, - actor_id, - configured_catalog, - connector_under_test, - command, - stdout_file_path, - stderr_file_path, - success, - executed_container, - config, - http_dump, - ) - await execution_result.load_http_flows() - return execution_result - - async def load_http_flows(self) -> None: - if not self.http_dump: - return - with tempfile.NamedTemporaryFile() as temp_file: - await self.http_dump.export(temp_file.name) - self.http_flows = get_http_flows_from_mitm_dump(Path(temp_file.name)) - - def parse_airbyte_messages_from_command_output( - self, command_output_path: Path, log_validation_errors: bool = False - ) -> Iterable[AirbyteMessage]: - with open(command_output_path) as command_output: - for line in command_output: - try: - yield AirbyteMessage.parse_raw(line) - except ValidationError as e: - if log_validation_errors: - self.logger.warn(f"Error parsing AirbyteMessage: {e}") - - def get_records(self) -> Iterable[AirbyteMessage]: - self.logger.info( - f"Reading records all records for command {self.command.value} on {self.connector_under_test.target_or_control.value} version." - ) - for message in self.airbyte_messages: - if message.type is AirbyteMessageType.RECORD: - yield message - - def generate_stream_schemas(self) -> dict[str, Any]: - self.logger.info("Generating stream schemas") - stream_builders: dict[str, SchemaBuilder] = {} - for record in self.get_records(): - stream = record.record.stream - if stream not in stream_builders: - stream_schema_builder = SchemaBuilder() - stream_schema_builder.add_schema({"type": "object", "properties": {}}) - stream_builders[stream] = stream_schema_builder - stream_builders[stream].add_object(self.get_obfuscated_types(record.record.data)) - self.logger.info("Stream schemas generated") - return {stream: sort_dict_keys(stream_builders[stream].to_schema()) for stream in stream_builders} - - @staticmethod - def get_obfuscated_types(data: dict[str, Any]) -> dict[str, Any]: - """ - Convert obfuscated records into a record whose values have the same type as the original values. - """ - types = {} - for k, v in data.items(): - if v.startswith("string_"): - types[k] = "a" - elif v.startswith("integer_"): - types[k] = 0 - elif v.startswith("number_"): - types[k] = 0.1 - elif v.startswith("boolean_"): - types[k] = True - elif v.startswith("null_"): - types[k] = None - elif v.startswith("array_"): - types[k] = [] - elif v.startswith("object_"): - types[k] = {} - else: - types[k] = v - - return types - - def get_records_per_stream(self, stream: str) -> Iterator[AirbyteMessage]: - assert self.backend is not None, "Backend must be set to get records per stream" - self.logger.info(f"Reading records for stream {stream}") - if stream not in self.backend.record_per_stream_paths: - self.logger.warning(f"No records found for stream {stream}") - yield from [] - else: - for message in self.parse_airbyte_messages_from_command_output( - self.backend.record_per_stream_paths[stream], log_validation_errors=True - ): - if message.type is AirbyteMessageType.RECORD: - yield message - - def get_states_per_stream(self, stream: str) -> Dict[str, List[AirbyteStateMessage]]: - self.logger.info(f"Reading state messages for stream {stream}") - states = defaultdict(list) - for message in self.airbyte_messages: - if message.type is AirbyteMessageType.STATE: - states[message.state.stream.stream_descriptor.name].append(message.state) - return states - - def get_status_messages_per_stream(self, stream: str) -> Dict[str, List[AirbyteStreamStatusTraceMessage]]: - self.logger.info(f"Reading state messages for stream {stream}") - statuses = defaultdict(list) - for message in self.airbyte_messages: - if message.type is AirbyteMessageType.TRACE and message.trace.type == TraceType.STREAM_STATUS: - statuses[message.trace.stream_status.stream_descriptor.name].append(message.trace.stream_status) - return statuses - - @cache - def get_message_count_per_type(self) -> dict[AirbyteMessageType, int]: - message_count: dict[AirbyteMessageType, int] = defaultdict(int) - for message in self.airbyte_messages: - message_count[message.type] += 1 - return message_count - - async def save_http_dump(self, output_dir: Path) -> None: - if self.http_dump: - self.logger.info("An http dump was captured during the execution of the command, saving it.") - http_dump_file_path = (output_dir / self.HTTP_DUMP_FILE_NAME).resolve() - await self.http_dump.export(str(http_dump_file_path)) - self.logger.info(f"Http dump saved to {http_dump_file_path}") - - # Define where the har file will be saved - har_file_path = (output_dir / self.HAR_FILE_NAME).resolve() - # Convert the mitmproxy dump file to a har file - mitm_http_stream_to_har(http_dump_file_path, har_file_path) - self.logger.info(f"Har file saved to {har_file_path}") - else: - self.logger.warning("No http dump to save") - - def save_airbyte_messages(self, output_dir: Path, duckdb_path: Optional[Path] = None) -> None: - self.logger.info("Saving Airbyte messages to disk") - airbyte_messages_dir = output_dir / "airbyte_messages" - airbyte_messages_dir.mkdir(parents=True, exist_ok=True) - if duckdb_path: - self.backend = DuckDbBackend(airbyte_messages_dir, duckdb_path, self.duckdb_schema) - else: - self.backend = FileBackend(airbyte_messages_dir) - self.backend.write(self.airbyte_messages) - self.logger.info("Airbyte messages saved") - - def save_stream_schemas(self, output_dir: Path) -> None: - self.stream_schemas = self.generate_stream_schemas() - stream_schemas_dir = output_dir / "stream_schemas" - stream_schemas_dir.mkdir(parents=True, exist_ok=True) - for stream_name, stream_schema in self.stream_schemas.items(): - (stream_schemas_dir / f"{sanitize_stream_name(stream_name)}.json").write_text(json.dumps(stream_schema, sort_keys=True)) - self.logger.info("Stream schemas saved to disk") - - async def save_artifacts(self, output_dir: Path, duckdb_path: Optional[Path] = None) -> None: - self.logger.info("Saving artifacts to disk") - self.save_airbyte_messages(output_dir, duckdb_path) - self.update_configuration() - await self.save_http_dump(output_dir) - self.save_stream_schemas(output_dir) - self.logger.info("All artifacts saved to disk") - - def get_updated_configuration(self, control_message_path: Path) -> Optional[dict[str, Any]]: - """Iterate through the control messages to find CONNECTOR_CONFIG message and return the last updated configuration.""" - if not control_message_path.exists(): - return None - updated_config = None - for line in control_message_path.read_text().splitlines(): - if line.strip(): - connector_config = json.loads(line.strip()).get("connectorConfig", {}) - if connector_config: - updated_config = connector_config - return updated_config - - def update_configuration(self) -> None: - """This function checks if a configuration has to be updated by reading the control messages file. - If a configuration has to be updated, it updates the configuration on the actor using the Airbyte API. - """ - assert self.backend is not None, "Backend must be set to update configuration in order to find the control messages path" - updated_configuration = self.get_updated_configuration(self.backend.jsonl_controls_path) - if updated_configuration is None: - return - - self.logger.warning(f"Updating configuration for {self.connector_under_test.name}, actor {self.actor_id}") - url = f"https://api.airbyte.com/v1/{self.connector_under_test.actor_type.value}s/{self.actor_id}" - - payload = { - "configuration": { - **updated_configuration, - f"{self.connector_under_test.actor_type.value}Type": self.connector_under_test.name_without_type_prefix, - } - } - headers = { - "accept": "application/json", - "content-type": "application/json", - "authorization": f"Bearer {get_airbyte_api_key()}", - } - - response = requests.patch(url, json=payload, headers=headers) - try: - response.raise_for_status() - except requests.HTTPError as e: - self.logger.error(f"Failed to update {self.connector_under_test.name} configuration on actor {self.actor_id}: {e}") - self.logger.error(f"Response: {response.text}") - self.logger.info(f"Updated configuration for {self.connector_under_test.name}, actor {self.actor_id}") - - def __hash__(self): - return hash(self.connector_under_test.version) - - -@dataclass(kw_only=True) -class ConnectionObjects: - source_config: Optional[SecretDict] - destination_config: Optional[SecretDict] - configured_catalog: Optional[ConfiguredAirbyteCatalog] - catalog: Optional[AirbyteCatalog] - state: Optional[dict] - workspace_id: Optional[str] - source_id: Optional[str] - destination_id: Optional[str] - source_docker_image: Optional[str] - connection_id: Optional[str] - - @property - def url(self) -> Optional[str]: - if not self.workspace_id or not self.connection_id: - return None - return f"https://cloud.airbyte.com/workspaces/{self.workspace_id}/connections/{self.connection_id}" - - @property - def hashed_connection_id(self) -> Optional[str]: - if not self.connection_id: - return None - return self.connection_id[:8] diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/proxy.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/proxy.py deleted file mode 100644 index a601ab734fdb..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/proxy.py +++ /dev/null @@ -1,184 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -import logging -import uuid - -import dagger - -from . import mitm_addons - - -class Proxy: - """ - This class is a wrapper around a mitmproxy container. It allows to declare a mitmproxy container, - bind it as a service to a different container and retrieve the mitmproxy stream file. - """ - - MITMPROXY_IMAGE = "mitmproxy/mitmproxy:10.2.4" - MITM_STREAM_FILE = "stream.mitm" - PROXY_PORT = 8080 - MITM_ADDONS_PATH = mitm_addons.__file__ - - def __init__( - self, - dagger_client: dagger.Client, - hostname: str, - session_id: str, - stream_for_server_replay: dagger.File | None = None, - ) -> None: - self.dagger_client = dagger_client - self.hostname = hostname - self.session_id = session_id - self.stream_for_server_replay = stream_for_server_replay - - @property - def dump_cache_volume(self) -> dagger.CacheVolume: - # We namespace the cache by: - # - Mitmproxy image name to make sure we're not re-using a cached artifact on a different and potentially incompatible mitmproxy version - # - Hostname to avoid sharing the same https dump between different tests - # - Session id to avoid sharing the same https dump between different runs of the same tests - # The session id is set to the Airbyte Connection ID to ensure that no cache is shared between connections - return self.dagger_client.cache_volume(f"{self.MITMPROXY_IMAGE}{self.hostname}{self.session_id}") - - @property - def mitmproxy_dir_cache(self) -> dagger.CacheVolume: - return self.dagger_client.cache_volume(self.MITMPROXY_IMAGE) - - def generate_mitmconfig(self): - return ( - self.dagger_client.container() - .from_(self.MITMPROXY_IMAGE) - # Mitmproxy generates its self signed certs at first run, we need to run it once to generate the certs - # They are stored in /root/.mitmproxy - .with_exec(["timeout", "--preserve-status", "1", "mitmdump"]) - .directory("/root/.mitmproxy") - ) - - async def get_container(self, mitm_config: dagger.Directory) -> dagger.Container: - """Get a container for the mitmproxy service. - If a stream for server replay is provided, it will be used to replay requests to the same URL. - - Returns: - dagger.Container: The container for the mitmproxy service. - mitm_config (dagger.Directory): The directory containing the mitmproxy configuration. - """ - container_addons_path = "/addons.py" - proxy_container = ( - self.dagger_client.container() - .from_(self.MITMPROXY_IMAGE) - .with_exec(["mkdir", "/dumps"]) - # This is caching the mitmproxy stream files, which can contain sensitive information - # We want to nuke this cache after test suite execution. - .with_mounted_cache("/dumps", self.dump_cache_volume) - # This is caching the mitmproxy self-signed certificate, no sensitive information is stored in it - .with_file( - container_addons_path, - self.dagger_client.host().file(self.MITM_ADDONS_PATH), - ) - .with_directory("/root/.mitmproxy", mitm_config) - ) - - # If the proxy was instantiated with a stream for server replay from a previous run, we want to use it. - # Requests to the same URL will be replayed from the stream instead of being sent to the server. - # This is useful to avoid rate limiting issues and limits responses drifts due to time based logics. - if self.stream_for_server_replay is not None and await self.stream_for_server_replay.size() > 0: - proxy_container = proxy_container.with_file("/cache.mitm", self.stream_for_server_replay) - command = [ - "mitmdump", - "-s", - container_addons_path, - "--flow-detail", - "2", - "--server-replay", - "/cache.mitm", - "--save-stream-file", - f"/dumps/{self.MITM_STREAM_FILE}", - ] - else: - command = [ - "mitmdump", - "-s", - container_addons_path, - "--flow-detail", - "2", - "--save-stream-file", - f"/dumps/{self.MITM_STREAM_FILE}", - ] - - return proxy_container.with_exec(command) - - async def get_service(self, mitm_config: dagger.Directory) -> dagger.Service: - return (await self.get_container(mitm_config)).with_exposed_port(self.PROXY_PORT).as_service() - - async def bind_container(self, container: dagger.Container) -> dagger.Container: - """Bind a container to the proxy service and set environment variables to use the proxy for HTTP(S) traffic. - - Args: - container (dagger.Container): The container to bind to the proxy service. - - Returns: - dagger.Container: The container with the proxy service bound and environment variables set. - """ - mitmconfig_dir = self.generate_mitmconfig() - pem = mitmconfig_dir.file("mitmproxy-ca.pem") - - # Find the python version in the container to get the correct path for the requests cert file - # We will overwrite this file with the mitmproxy self-signed certificate - # I could not find a less brutal way to make Requests trust the mitmproxy self-signed certificate - # I tried running update-ca-certificates + setting REQUESTS_CA_BUNDLE in the container but it did not work - python_version_output = (await container.with_exec(["python", "--version"]).stdout()).strip() - python_version = python_version_output.split(" ")[-1] - python_version_minor_only = ".".join(python_version.split(".")[:-1]) - requests_cert_path = f"/usr/local/lib/python{python_version_minor_only}/site-packages/certifi/cacert.pem" - current_user = (await container.with_exec(["whoami"]).stdout()).strip() - try: - return await ( - container.with_user("root") - # Overwrite the requests cert file with the mitmproxy self-signed certificate - .with_file(requests_cert_path, pem, owner=current_user) - .with_env_variable("http_proxy", f"{self.hostname}:{self.PROXY_PORT}") - .with_env_variable("https_proxy", f"{self.hostname}:{self.PROXY_PORT}") - .with_user(current_user) - .with_service_binding(self.hostname, await self.get_service(mitmconfig_dir)) - ) - except dagger.DaggerError as e: - # This is likely hapenning on Java connector images whose certificates location is different - # TODO handle this case - logging.warn(f"Failed to bind container to proxy: {e}") - return container - - async def retrieve_http_dump(self) -> dagger.File | None: - """We mount the cache volume, where the mitmproxy container saves the stream file, to a fresh container. - We then copy the stream file to a new directory and return it as a dagger.File. - The copy operation to /to_export is required as Dagger does not support direct access to files in cache volumes. - - - Returns: - dagger.File | None: The mitmproxy stream file if it exists, None otherwise. - """ - container = ( - self.dagger_client.container() - .from_("alpine:latest") - .with_env_variable("CACHEBUSTER", str(uuid.uuid4())) - .with_mounted_cache("/dumps", self.dump_cache_volume) - ) - dump_files = (await container.with_exec(["ls", "/dumps"]).stdout()).splitlines() - if self.MITM_STREAM_FILE not in dump_files: - return None - return await ( - container.with_exec(["mkdir", "/to_export"], use_entrypoint=True) - .with_exec(["cp", "-r", f"/dumps/{self.MITM_STREAM_FILE}", f"/to_export/{self.MITM_STREAM_FILE}"], use_entrypoint=True) - .file(f"/to_export/{self.MITM_STREAM_FILE}") - ) - - async def clear_cache_volume(self) -> None: - """Delete all files in the cache volume. This is useful to avoid caching sensitive information between tests.""" - await ( - self.dagger_client.container() - .from_("alpine:latest") - .with_mounted_cache("/to_clear", self.dump_cache_volume) - .with_exec(["rm", "-rf", "/to_clear/*"], use_entrypoint=True) - .sync() - ) - logging.info(f"Cache volume {self.dump_cache_volume} cleared") diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/secret_access.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/secret_access.py deleted file mode 100644 index 05e6591d4995..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/secret_access.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -import logging - -from google.api_core.exceptions import PermissionDenied -from google.cloud import secretmanager - -LIVE_TESTS_AIRBYTE_API_KEY_SECRET_ID = "projects/587336813068/secrets/live_tests_airbyte_api_key" - - -def get_secret_value(secret_manager_client: secretmanager.SecretManagerServiceClient, secret_id: str) -> str: - """Get the value of the enabled version of a secret - - Args: - secret_manager_client (secretmanager.SecretManagerServiceClient): The secret manager client - secret_id (str): The id of the secret - - Returns: - str: The value of the enabled version of the secret - """ - try: - response = secret_manager_client.list_secret_versions(request={"parent": secret_id, "filter": "state:ENABLED"}) - if len(response.versions) == 0: - raise ValueError(f"No enabled version of secret {secret_id} found") - enabled_version = response.versions[0] - response = secret_manager_client.access_secret_version(name=enabled_version.name) - return response.payload.data.decode("UTF-8") - except PermissionDenied as e: - logging.exception( - f"Permission denied while trying to access secret {secret_id}. Please write to #dev-tooling in Airbyte Slack for help.", - exc_info=e, - ) - raise e - - -def get_airbyte_api_key() -> str: - secret_manager_client = secretmanager.SecretManagerServiceClient() - return get_secret_value(secret_manager_client, LIVE_TESTS_AIRBYTE_API_KEY_SECRET_ID) diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/segment_tracking.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/segment_tracking.py deleted file mode 100644 index a57a2aa542bb..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/segment_tracking.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -import logging -import os -from importlib.metadata import version -from typing import Any, Optional - -from segment import analytics # type: ignore - -ENABLE_TRACKING = os.getenv("REGRESSION_TEST_DISABLE_TRACKING") is None -DEBUG_SEGMENT = os.getenv("DEBUG_SEGMENT") is not None -EVENT_NAME = "regression_test_start" -CURRENT_VERSION = version(__name__.split(".")[0]) - - -def on_error(error: Exception, items: Any) -> None: - logging.warning("An error occurred in Segment Tracking", exc_info=error) - - -# This is not a secret key, it is a public key that is used to identify the Segment project -analytics.write_key = "hnWfMdEtXNKBjvmJ258F72wShsLmcsZ8" -analytics.send = ENABLE_TRACKING -analytics.debug = DEBUG_SEGMENT -analytics.on_error = on_error - - -def track_usage( - user_id: Optional[str], - pytest_options: dict[str, Any], -) -> None: - if user_id: - analytics.identify(user_id) - else: - user_id = "airbyte-ci" - - # It contains default pytest option and the custom one passed by the user - analytics.track( - user_id, - EVENT_NAME, - { - "pytest_options": pytest_options, - "package_version": CURRENT_VERSION, - }, - ) diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/commons/utils.py b/airbyte-ci/connectors/live-tests/src/live_tests/commons/utils.py deleted file mode 100644 index 08aeb1b47de5..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/commons/utils.py +++ /dev/null @@ -1,192 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -import logging -import os -import re -import shutil -from pathlib import Path -from typing import Optional - -import dagger -import docker # type: ignore -import pytest -from mitmproxy import http, io # type: ignore -from mitmproxy.addons.savehar import SaveHar # type: ignore -from slugify import slugify - - -async def get_container_from_id(dagger_client: dagger.Client, container_id: str) -> dagger.Container: - """Get a dagger container from its id. - Please remind that container id are not persistent and can change between Dagger sessions. - - Args: - dagger_client (dagger.Client): The dagger client to use to import the connector image - """ - try: - return await dagger_client.load_container_from_id(dagger.ContainerID(container_id)) - except dagger.DaggerError as e: - pytest.exit(f"Failed to load connector container: {e}") - - -async def get_container_from_tarball_path(dagger_client: dagger.Client, tarball_path: Path) -> dagger.Container: - if not tarball_path.exists(): - pytest.exit(f"Connector image tarball {tarball_path} does not exist") - container_under_test_tar_file = ( - dagger_client.host().directory(str(tarball_path.parent), include=[tarball_path.name]).file(tarball_path.name) - ) - try: - return await dagger_client.container().import_(container_under_test_tar_file) - except dagger.DaggerError as e: - pytest.exit(f"Failed to import connector image from tarball: {e}") - - -async def get_container_from_local_image(dagger_client: dagger.Client, local_image_name: str) -> Optional[dagger.Container]: - """Get a dagger container from a local image. - It will use Docker python client to export the image to a tarball and then import it into dagger. - - Args: - dagger_client (dagger.Client): The dagger client to use to import the connector image - local_image_name (str): The name of the local image to import - - Returns: - Optional[dagger.Container]: The dagger container for the local image or None if the image does not exist - """ - docker_client = docker.from_env() - - try: - image = docker_client.images.get(local_image_name) - except docker.errors.ImageNotFound: - return None - - image_digest = image.id.replace("sha256:", "") - tarball_path = Path(f"/tmp/{image_digest}.tar") - if not tarball_path.exists(): - logging.info(f"Exporting local connector image {local_image_name} to tarball {tarball_path}") - with open(tarball_path, "wb") as f: - for chunk in image.save(named=True): - f.write(chunk) - return await get_container_from_tarball_path(dagger_client, tarball_path) - - -async def get_container_from_dockerhub_image(dagger_client: dagger.Client, dockerhub_image_name: str) -> dagger.Container: - """Get a dagger container from a dockerhub image. - - Args: - dagger_client (dagger.Client): The dagger client to use to import the connector image - dockerhub_image_name (str): The name of the dockerhub image to import - - Returns: - dagger.Container: The dagger container for the dockerhub image - """ - try: - return await dagger_client.container().from_(dockerhub_image_name) - except dagger.DaggerError as e: - pytest.exit(f"Failed to import connector image from DockerHub: {e}") - - -async def get_connector_container(dagger_client: dagger.Client, image_name_with_tag: str) -> dagger.Container: - """Get a dagger container for the connector image to test. - - Args: - dagger_client (dagger.Client): The dagger client to use to import the connector image - image_name_with_tag (str): The docker image name and tag of the connector image to test - - Returns: - dagger.Container: The dagger container for the connector image to test - """ - # If a container_id.txt file is available, we'll use it to load the connector container - # We use a txt file as container ids can be too long to be passed as env vars - # It's used for dagger-in-dagger use case with airbyte-ci, when the connector container is built via an upstream dagger operation - container_id_path = Path(f"/tmp/{slugify(image_name_with_tag)}_container_id.txt") - if container_id_path.exists(): - return await get_container_from_id(dagger_client, container_id_path.read_text()) - - # If the CONNECTOR_UNDER_TEST_IMAGE_TAR_PATH env var is set, we'll use it to import the connector image from the tarball - if connector_image_tarball_path := os.environ.get("CONNECTOR_UNDER_TEST_IMAGE_TAR_PATH"): - tarball_path = Path(connector_image_tarball_path) - return await get_container_from_tarball_path(dagger_client, tarball_path) - - # Let's try to load the connector container from a local image - if connector_container := await get_container_from_local_image(dagger_client, image_name_with_tag): - return connector_container - - # If we get here, we'll try to pull the connector image from DockerHub - return await get_container_from_dockerhub_image(dagger_client, image_name_with_tag) - - -def sh_dash_c(lines: list[str]) -> list[str]: - """Wrap sequence of commands in shell for safe usage of dagger Container's with_exec method.""" - return ["sh", "-c", " && ".join(["set -o xtrace"] + lines)] - - -def clean_up_artifacts(directory: Path, logger: logging.Logger) -> None: - if directory.exists(): - shutil.rmtree(directory) - logger.info(f"🧹 Test artifacts cleaned up from {directory}") - - -def get_http_flows_from_mitm_dump(mitm_dump_path: Path) -> list[http.HTTPFlow]: - """Get http flows from a mitmproxy dump file. - - Args: - mitm_dump_path (Path): Path to the mitmproxy dump file. - - Returns: - List[http.HTTPFlow]: List of http flows. - """ - with open(mitm_dump_path, "rb") as dump_file: - return [f for f in io.FlowReader(dump_file).stream() if isinstance(f, http.HTTPFlow)] - - -def mitm_http_stream_to_har(mitm_http_stream_path: Path, har_file_path: Path) -> Path: - """Converts a mitmproxy http stream file to a har file. - - Args: - mitm_http_stream_path (Path): Path to the mitmproxy http stream file. - har_file_path (Path): Path where the har file will be saved. - - Returns: - Path: Path to the har file. - """ - flows = get_http_flows_from_mitm_dump(mitm_http_stream_path) - SaveHar().export_har(flows, str(har_file_path)) - return har_file_path - - -def extract_connection_id_from_url(url: str) -> str: - pattern = r"/connections/([a-f0-9\-]+)" - match = re.search(pattern, url) - if match: - return match.group(1) - else: - raise ValueError(f"Could not extract connection id from url {url}") - - -def extract_workspace_id_from_url(url: str) -> str: - pattern = r"/workspaces/([a-f0-9\-]+)" - match = re.search(pattern, url) - if match: - return match.group(1) - else: - raise ValueError(f"Could not extract workspace id from url {url}") - - -def build_connection_url(workspace_id: str | None, connection_id: str | None) -> str: - if not workspace_id or not connection_id: - raise ValueError("Both workspace_id and connection_id must be provided") - return f"https://cloud.airbyte.com/workspaces/{workspace_id}/connections/{connection_id}" - - -def sort_dict_keys(d: dict) -> dict: - if isinstance(d, dict): - sorted_dict = {} - for key in sorted(d.keys()): - sorted_dict[key] = sort_dict_keys(d[key]) - return sorted_dict - else: - return d - - -def sanitize_stream_name(stream_name: str) -> str: - return stream_name.replace("/", "_").replace(" ", "_").lower() diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/conftest.py b/airbyte-ci/connectors/live-tests/src/live_tests/conftest.py deleted file mode 100644 index 180fa53a52ae..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/conftest.py +++ /dev/null @@ -1,646 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -from __future__ import annotations - -import hashlib -import logging -import os -import textwrap -import time -import webbrowser -from collections.abc import AsyncIterable, Callable, Generator, Iterable -from itertools import product -from pathlib import Path -from typing import TYPE_CHECKING, List, Optional - -import dagger -import pytest -from airbyte_protocol.models import ConfiguredAirbyteCatalog # type: ignore -from connection_retriever.audit_logging import get_user_email # type: ignore -from connection_retriever.retrieval import ConnectionNotFoundError, get_current_docker_image_tag # type: ignore -from rich.prompt import Confirm, Prompt - -from live_tests import stash_keys -from live_tests.commons.connection_objects_retrieval import ConnectionObject, InvalidConnectionError, get_connection_objects -from live_tests.commons.connector_runner import ConnectorRunner, Proxy -from live_tests.commons.evaluation_modes import TestEvaluationMode -from live_tests.commons.models import ( - ActorType, - Command, - ConnectionObjects, - ConnectionSubset, - ConnectorUnderTest, - ExecutionInputs, - ExecutionResult, - SecretDict, - TargetOrControl, -) -from live_tests.commons.secret_access import get_airbyte_api_key -from live_tests.commons.segment_tracking import track_usage -from live_tests.commons.utils import clean_up_artifacts -from live_tests.report import PrivateDetailsReport, ReportState, TestReport - -if TYPE_CHECKING: - from _pytest.config import Config - from _pytest.config.argparsing import Parser - from _pytest.fixtures import SubRequest - from pytest_sugar import SugarTerminalReporter # type: ignore - -# CONSTS -LOGGER = logging.getLogger("live-tests") -MAIN_OUTPUT_DIRECTORY = Path("/tmp/live_tests_artifacts") - -# It's used by Dagger and its very verbose -logging.getLogger("httpx").setLevel(logging.ERROR) - - -# PYTEST HOOKS -def pytest_addoption(parser: Parser) -> None: - parser.addoption( - "--connector-image", - help="The connector image name on which the tests will run: e.g. airbyte/source-faker", - ) - parser.addoption( - "--control-version", - help="The control version used for regression testing.", - ) - parser.addoption( - "--target-version", - default="dev", - help="The target version used for regression and validation testing. Defaults to dev.", - ) - parser.addoption("--config-path") - parser.addoption("--catalog-path") - parser.addoption("--state-path") - parser.addoption("--connection-id") - parser.addoption("--pr-url", help="The URL of the PR you are testing") - parser.addoption( - "--stream", - help="The stream to run the tests on. (Can be used multiple times)", - action="append", - ) - # Required when running in CI - parser.addoption("--run-id", type=str) - parser.addoption( - "--should-read-with-state", - type=bool, - help="Whether to run the `read` command with state. \n" - "We recommend reading with state to properly test incremental sync. \n" - "But if the target version introduces a breaking change in the state, you might want to run without state. \n", - ) - parser.addoption( - "--test-evaluation-mode", - choices=[e.value for e in TestEvaluationMode], - default=TestEvaluationMode.STRICT.value, - help='If "diagnostic" mode is selected, all tests will pass as long as there is no exception; warnings will be logged. In "strict" mode, tests may fail.', - ) - parser.addoption( - "--connection-subset", - choices=[c.value for c in ConnectionSubset], - default=ConnectionSubset.SANDBOXES.value, - help="Whether to select from sandbox accounts only.", - ) - parser.addoption( - "--max-connections", - default=None, - help="The maximum number of connections to retrieve and use for testing.", - ) - parser.addoption( - "--disable-proxy", - type=bool, - default=False, - help="If a connector uses provider-specific libraries (e.g., facebook-business), it is better to disable the proxy.", - ) - - -def pytest_configure(config: Config) -> None: - user_email = get_user_email() - config.stash[stash_keys.RUN_IN_AIRBYTE_CI] = bool(os.getenv("RUN_IN_AIRBYTE_CI", False)) - config.stash[stash_keys.IS_PRODUCTION_CI] = bool(os.getenv("CI", False)) - - if not config.stash[stash_keys.RUN_IN_AIRBYTE_CI]: - prompt_for_confirmation(user_email) - - track_usage( - "production-ci" - if config.stash[stash_keys.IS_PRODUCTION_CI] - else "local-ci" - if config.stash[stash_keys.RUN_IN_AIRBYTE_CI] - else user_email, - vars(config.option), - ) - config.stash[stash_keys.AIRBYTE_API_KEY] = get_airbyte_api_key() - config.stash[stash_keys.USER] = user_email - config.stash[stash_keys.SESSION_RUN_ID] = config.getoption("--run-id") or str(int(time.time())) - test_artifacts_directory = get_artifacts_directory(config) - duckdb_path = test_artifacts_directory / "duckdb.db" - config.stash[stash_keys.DUCKDB_PATH] = duckdb_path - test_artifacts_directory.mkdir(parents=True, exist_ok=True) - dagger_log_path = test_artifacts_directory / "dagger.log" - config.stash[stash_keys.IS_PERMITTED_BOOL] = False - report_path = test_artifacts_directory / "report.html" - private_details_path = test_artifacts_directory / "private_details.html" - config.stash[stash_keys.TEST_ARTIFACT_DIRECTORY] = test_artifacts_directory - dagger_log_path.touch() - LOGGER.info("Dagger log path: %s", dagger_log_path) - config.stash[stash_keys.DAGGER_LOG_PATH] = dagger_log_path - config.stash[stash_keys.PR_URL] = get_option_or_fail(config, "--pr-url") - _connection_id = config.getoption("--connection-id") - config.stash[stash_keys.AUTO_SELECT_CONNECTION] = _connection_id == "auto" - config.stash[stash_keys.CONNECTOR_IMAGE] = get_option_or_fail(config, "--connector-image") - config.stash[stash_keys.TARGET_VERSION] = get_option_or_fail(config, "--target-version") - config.stash[stash_keys.CONTROL_VERSION] = get_control_version(config) - config.stash[stash_keys.CONNECTION_SUBSET] = ConnectionSubset(get_option_or_fail(config, "--connection-subset")) - custom_source_config_path = config.getoption("--config-path") - custom_configured_catalog_path = config.getoption("--catalog-path") - custom_state_path = config.getoption("--state-path") - config.stash[stash_keys.SELECTED_STREAMS] = set(config.getoption("--stream") or []) - config.stash[stash_keys.TEST_EVALUATION_MODE] = TestEvaluationMode(config.getoption("--test-evaluation-mode", "strict")) - config.stash[stash_keys.MAX_CONNECTIONS] = config.getoption("--max-connections") - config.stash[stash_keys.MAX_CONNECTIONS] = ( - int(config.stash[stash_keys.MAX_CONNECTIONS]) if config.stash[stash_keys.MAX_CONNECTIONS] else None - ) - - config.stash[stash_keys.DISABLE_PROXY] = config.getoption("--disable-proxy") - - if config.stash[stash_keys.RUN_IN_AIRBYTE_CI]: - config.stash[stash_keys.SHOULD_READ_WITH_STATE] = bool(config.getoption("--should-read-with-state")) - elif _should_read_with_state := config.getoption("--should-read-with-state"): - config.stash[stash_keys.SHOULD_READ_WITH_STATE] = _should_read_with_state - else: - config.stash[stash_keys.SHOULD_READ_WITH_STATE] = prompt_for_read_with_or_without_state() - - retrieval_reason = f"Running live tests on connection for connector {config.stash[stash_keys.CONNECTOR_IMAGE]} on target versions ({config.stash[stash_keys.TARGET_VERSION]})." - - try: - config.stash[stash_keys.ALL_CONNECTION_OBJECTS] = get_connection_objects( - { - ConnectionObject.SOURCE_CONFIG, - ConnectionObject.CATALOG, - ConnectionObject.CONFIGURED_CATALOG, - ConnectionObject.STATE, - ConnectionObject.WORKSPACE_ID, - ConnectionObject.SOURCE_DOCKER_IMAGE, - ConnectionObject.SOURCE_ID, - ConnectionObject.DESTINATION_ID, - }, - None if _connection_id == "auto" else _connection_id, - Path(custom_source_config_path) if custom_source_config_path else None, - Path(custom_configured_catalog_path) if custom_configured_catalog_path else None, - Path(custom_state_path) if custom_state_path else None, - retrieval_reason, - connector_image=config.stash[stash_keys.CONNECTOR_IMAGE], - connector_version=config.stash[stash_keys.CONTROL_VERSION], - auto_select_connections=config.stash[stash_keys.AUTO_SELECT_CONNECTION], - selected_streams=config.stash[stash_keys.SELECTED_STREAMS], - connection_subset=config.stash[stash_keys.CONNECTION_SUBSET], - max_connections=config.stash[stash_keys.MAX_CONNECTIONS], - ) - config.stash[stash_keys.IS_PERMITTED_BOOL] = True - except (ConnectionNotFoundError, InvalidConnectionError) as exc: - clean_up_artifacts(MAIN_OUTPUT_DIRECTORY, LOGGER) - LOGGER.error( - f"Failed to retrieve a valid a connection which is using the control version {config.stash[stash_keys.CONTROL_VERSION]}." - ) - pytest.exit(str(exc)) - - if config.stash[stash_keys.CONTROL_VERSION] == config.stash[stash_keys.TARGET_VERSION]: - pytest.exit(f"Control and target versions are the same: {control_version}. Please provide different versions.") - - config.stash[stash_keys.PRIVATE_DETAILS_REPORT] = PrivateDetailsReport( - private_details_path, - config, - ) - - config.stash[stash_keys.TEST_REPORT] = TestReport( - report_path, - config, - private_details_url=config.stash[stash_keys.PRIVATE_DETAILS_REPORT].path.resolve().as_uri(), - ) - - webbrowser.open_new_tab(config.stash[stash_keys.TEST_REPORT].path.resolve().as_uri()) - - -def get_artifacts_directory(config: pytest.Config) -> Path: - run_id = config.stash[stash_keys.SESSION_RUN_ID] - return MAIN_OUTPUT_DIRECTORY / f"session_{run_id}" - - -def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item]) -> None: - for item in items: - if config.stash[stash_keys.SHOULD_READ_WITH_STATE] and "without_state" in item.keywords: - item.add_marker(pytest.mark.skip(reason="Test is marked with without_state marker")) - if not config.stash[stash_keys.SHOULD_READ_WITH_STATE] and "with_state" in item.keywords: - item.add_marker(pytest.mark.skip(reason="Test is marked with with_state marker")) - - -def pytest_terminal_summary(terminalreporter: SugarTerminalReporter, exitstatus: int, config: Config) -> None: - config.stash[stash_keys.TEST_REPORT].update(ReportState.FINISHED) - config.stash[stash_keys.PRIVATE_DETAILS_REPORT].update(ReportState.FINISHED) - if not config.stash.get(stash_keys.IS_PERMITTED_BOOL, False): - # Don't display the prompt if the tests were not run due to inability to fetch config - clean_up_artifacts(MAIN_OUTPUT_DIRECTORY, LOGGER) - pytest.exit(str(NotPermittedError)) - - terminalreporter.ensure_newline() - terminalreporter.section("Test artifacts", sep="=", bold=True, blue=True) - terminalreporter.line( - f"All tests artifacts for this sessions should be available in {config.stash[stash_keys.TEST_ARTIFACT_DIRECTORY].resolve()}" - ) - - if not config.stash[stash_keys.RUN_IN_AIRBYTE_CI]: - try: - Prompt.ask( - textwrap.dedent( - """ - Test artifacts will be destroyed after this prompt. - Press enter when you're done reading them. - 🚨 Do not copy them elsewhere on your disk!!! 🚨 - """ - ) - ) - finally: - clean_up_artifacts(MAIN_OUTPUT_DIRECTORY, LOGGER) - - -def pytest_keyboard_interrupt(excinfo: Exception) -> None: - LOGGER.error("Test execution was interrupted by the user. Cleaning up test artifacts.") - clean_up_artifacts(MAIN_OUTPUT_DIRECTORY, LOGGER) - - -@pytest.hookimpl(tryfirst=True, hookwrapper=True) -def pytest_runtest_makereport(item: pytest.Item, call: pytest.CallInfo) -> Generator: - outcome = yield - report = outcome.get_result() - - # Overwrite test failures with passes for tests being run in diagnostic mode - if ( - item.config.stash.get(stash_keys.TEST_EVALUATION_MODE, TestEvaluationMode.STRICT) == TestEvaluationMode.DIAGNOSTIC - and "allow_diagnostic_mode" in item.keywords - ): - if call.when == "call": - if call.excinfo: - if report.outcome == "failed": - report.outcome = "passed" - - # This is to add skipped or failed tests due to upstream fixture failures on setup - if report.outcome in ["failed", "skipped"] or report.when == "call": - item.config.stash[stash_keys.TEST_REPORT].add_test_result( - report, - item.function.__doc__, # type: ignore - ) - - -# HELPERS - - -def get_option_or_fail(config: pytest.Config, option: str) -> str: - if option_value := config.getoption(option): - return option_value - pytest.fail(f"Missing required option: {option}") - - -def get_control_version(config: pytest.Config) -> str: - if control_version := config.getoption("--control-version"): - return control_version - if connector_docker_repository := config.getoption("--connector-image"): - return get_current_docker_image_tag(connector_docker_repository) - raise ValueError("The control version can't be determined, please pass a --control-version or a --connector-image") - - -def prompt_for_confirmation(user_email: str) -> None: - message = textwrap.dedent( - f""" - 👮 This program is running on live Airbyte Cloud connection. - It means that it might induce costs or rate limits on the source. - This program is storing tests artifacts in {MAIN_OUTPUT_DIRECTORY.resolve()} that you can use for debugging. They will get destroyed after the program execution. - - By approving this prompt, you ({user_email}) confirm that: - 1. You understand the implications of running this test suite. - 2. You have selected the correct target and control versions. - 3. You have selected the right tests according to your testing needs. - 4. You will not copy the test artifacts content. - 5. You want to run the program on the passed connection ID. - - Usage of this tool is tracked and logged. - - Do you want to continue? - """ - ) - if not os.environ.get("CI") and not Confirm.ask(message): - pytest.exit("Test execution was interrupted by the user.") - - -def prompt_for_read_with_or_without_state() -> bool: - message = textwrap.dedent( - """ - 📖 Do you want to run the read command with or without state? - 1. Run the read command with state - 2. Run the read command without state - - We recommend reading with state to properly test incremental sync. - But if the target version introduces a breaking change in the state, you might want to run without state. - """ - ) - return Prompt.ask(message) == "1" - - -# FIXTURES - - -@pytest.fixture(scope="session") -def anyio_backend() -> str: - return "asyncio" - - -@pytest.fixture(scope="session") -def test_artifacts_directory(request: SubRequest) -> Path: - return request.config.stash[stash_keys.TEST_ARTIFACT_DIRECTORY] - - -@pytest.fixture(scope="session") -def connector_image(request: SubRequest) -> str: - return request.config.stash[stash_keys.CONNECTOR_IMAGE] - - -@pytest.fixture(scope="session") -def control_version(request: SubRequest) -> str: - return request.config.stash[stash_keys.CONTROL_VERSION] - - -@pytest.fixture(scope="session") -def target_version(request: SubRequest) -> str: - return request.config.stash[stash_keys.TARGET_VERSION] - - -@pytest.fixture(scope="session") -def all_connection_objects(request: SubRequest) -> List[ConnectionObjects]: - return request.config.stash[stash_keys.ALL_CONNECTION_OBJECTS] - - -def get_connector_config(connection_objects: ConnectionObjects, control_connector: ConnectorUnderTest) -> Optional[SecretDict]: - if control_connector.actor_type is ActorType.SOURCE: - return connection_objects.source_config - elif control_connector.actor_type is ActorType.DESTINATION: - return connection_objects.destination_config - else: - raise ValueError(f"Actor type {control_connector.actor_type} is not supported") - - -@pytest.fixture(scope="session") -def actor_id(connection_objects: ConnectionObjects, control_connector: ConnectorUnderTest) -> str | None: - if control_connector.actor_type is ActorType.SOURCE: - return connection_objects.source_id - elif control_connector.actor_type is ActorType.DESTINATION: - return connection_objects.destination_id - else: - raise ValueError(f"Actor type {control_connector.actor_type} is not supported") - - -def get_actor_id(connection_objects: ConnectionObjects, control_connector: ConnectorUnderTest) -> str | None: - if control_connector.actor_type is ActorType.SOURCE: - return connection_objects.source_id - elif control_connector.actor_type is ActorType.DESTINATION: - return connection_objects.destination_id - else: - raise ValueError(f"Actor type {control_connector.actor_type} is not supported") - - -@pytest.fixture(scope="session") -def configured_streams( - configured_catalog: ConfiguredAirbyteCatalog, -) -> Iterable[str]: - return {stream.stream.name for stream in configured_catalog.streams} - - -@pytest.fixture(scope="session") -def state(connection_objects: ConnectionObjects) -> Optional[dict]: - return connection_objects.state - - -@pytest.fixture(scope="session") -def dagger_connection(request: SubRequest) -> dagger.Connection: - return dagger.Connection(dagger.Config(log_output=request.config.stash[stash_keys.DAGGER_LOG_PATH].open("w"))) - - -@pytest.fixture(scope="session", autouse=True) -async def dagger_client( - dagger_connection: dagger.Connection, -) -> AsyncIterable[dagger.Client]: - async with dagger_connection as client: - yield client - - -@pytest.fixture(scope="session") -async def control_connector(dagger_client: dagger.Client, connector_image: str, control_version: str) -> ConnectorUnderTest: - return await ConnectorUnderTest.from_image_name(dagger_client, f"{connector_image}:{control_version}", TargetOrControl.CONTROL) - - -@pytest.fixture(scope="session") -async def target_connector(dagger_client: dagger.Client, connector_image: str, target_version: str) -> ConnectorUnderTest: - return await ConnectorUnderTest.from_image_name(dagger_client, f"{connector_image}:{target_version}", TargetOrControl.TARGET) - - -@pytest.fixture(scope="session") -def duckdb_path(request: SubRequest) -> Path: - return request.config.stash[stash_keys.DUCKDB_PATH] - - -def get_execution_inputs_for_command( - command: Command, - connection_objects: ConnectionObjects, - control_connector: ConnectorUnderTest, - test_artifacts_directory: Path, - duckdb_path: Path, -) -> ExecutionInputs: - """Get the execution inputs for the given command and connection objects.""" - actor_id = get_actor_id(connection_objects, control_connector) - - inputs_arguments = { - "hashed_connection_id": connection_objects.hashed_connection_id, - "connector_under_test": control_connector, - "actor_id": actor_id, - "global_output_dir": test_artifacts_directory, - "command": command, - "duckdb_path": duckdb_path, - } - - if command.needs_config: - connector_config = get_connector_config(connection_objects, control_connector) - if not connector_config: - pytest.skip("Config is not provided. The config fixture can't be used.") - inputs_arguments["config"] = connector_config - if command.needs_catalog: - configured_catalog = connection_objects.configured_catalog - if not configured_catalog: - pytest.skip("Catalog is not provided. The catalog fixture can't be used.") - inputs_arguments["configured_catalog"] = connection_objects.configured_catalog - if command.needs_state: - state = connection_objects.state - if not state: - pytest.skip("State is not provided. The state fixture can't be used.") - inputs_arguments["state"] = state - - return ExecutionInputs(**inputs_arguments) - - -async def run_command( - dagger_client: dagger.Client, - command: Command, - connection_objects: ConnectionObjects, - connector: ConnectorUnderTest, - test_artifacts_directory: Path, - duckdb_path: Path, - runs_in_ci, - disable_proxy: bool = False, -) -> ExecutionResult: - """Run the given command for the given connector and connection objects.""" - execution_inputs = get_execution_inputs_for_command(command, connection_objects, connector, test_artifacts_directory, duckdb_path) - logging.info(f"Running {command} for {connector.target_or_control.value} connector {execution_inputs.connector_under_test.name}") - proxy = None - - if not disable_proxy: - proxy_hostname = f"proxy_server_{command.value}_{execution_inputs.connector_under_test.version.replace('.', '_')}" - proxy = Proxy(dagger_client, proxy_hostname, connection_objects.connection_id) - - runner = ConnectorRunner(dagger_client, execution_inputs, runs_in_ci, http_proxy=proxy) - execution_result = await runner.run() - return execution_result, proxy - - -async def run_command_and_add_to_report( - dagger_client: dagger.Client, - command: Command, - connection_objects: ConnectionObjects, - connector: ConnectorUnderTest, - test_artifacts_directory: Path, - duckdb_path: Path, - runs_in_ci, - test_report: TestReport, - private_details_report: PrivateDetailsReport, - disable_proxy: bool = False, -) -> ExecutionResult: - """Run the given command for the given connector and connection objects and add the results to the test report.""" - execution_result, proxy = await run_command( - dagger_client, - command, - connection_objects, - connector, - test_artifacts_directory, - duckdb_path, - runs_in_ci, - disable_proxy=disable_proxy, - ) - if connector.target_or_control is TargetOrControl.CONTROL: - test_report.add_control_execution_result(execution_result) - private_details_report.add_control_execution_result(execution_result) - if connector.target_or_control is TargetOrControl.TARGET: - test_report.add_target_execution_result(execution_result) - private_details_report.add_target_execution_result(execution_result) - return execution_result, proxy - - -def generate_execution_results_fixture(command: Command, control_or_target: str) -> Callable: - """Dynamically generate the fixture for the given command and control/target. - This is mainly to avoid code duplication and to make the code more maintainable. - Declaring this explicitly for each command and control/target combination would be cumbersome. - """ - - if control_or_target not in ["control", "target"]: - raise ValueError("control_or_target should be either 'control' or 'target'") - if command not in [Command.SPEC, Command.CHECK, Command.DISCOVER, Command.READ, Command.READ_WITH_STATE]: - raise ValueError("command should be either 'spec', 'check', 'discover', 'read' or 'read_with_state'") - - if control_or_target == "control": - - @pytest.fixture(scope="session") - async def generated_fixture( - request: SubRequest, dagger_client: dagger.Client, control_connector: ConnectorUnderTest, test_artifacts_directory: Path - ) -> ExecutionResult: - connection_objects = request.param - disable_proxy = request.config.stash[stash_keys.DISABLE_PROXY] - - execution_results, proxy = await run_command_and_add_to_report( - dagger_client, - command, - connection_objects, - control_connector, - test_artifacts_directory, - request.config.stash[stash_keys.DUCKDB_PATH], - request.config.stash[stash_keys.RUN_IN_AIRBYTE_CI], - request.config.stash[stash_keys.TEST_REPORT], - request.config.stash[stash_keys.PRIVATE_DETAILS_REPORT], - disable_proxy=disable_proxy, - ) - - yield execution_results - - if not disable_proxy: - await proxy.clear_cache_volume() - - else: - - @pytest.fixture(scope="session") - async def generated_fixture( - request: SubRequest, dagger_client: dagger.Client, target_connector: ConnectorUnderTest, test_artifacts_directory: Path - ) -> ExecutionResult: - connection_objects = request.param - disable_proxy = request.config.stash[stash_keys.DISABLE_PROXY] - - execution_results, proxy = await run_command_and_add_to_report( - dagger_client, - command, - connection_objects, - target_connector, - test_artifacts_directory, - request.config.stash[stash_keys.DUCKDB_PATH], - request.config.stash[stash_keys.RUN_IN_AIRBYTE_CI], - request.config.stash[stash_keys.TEST_REPORT], - request.config.stash[stash_keys.PRIVATE_DETAILS_REPORT], - disable_proxy=disable_proxy, - ) - - yield execution_results - - if not disable_proxy: - await proxy.clear_cache_volume() - - return generated_fixture - - -def inject_fixtures() -> set[str]: - """Dynamically generate th execution result fixtures for all the combinations of commands and control/target. - The fixtures will be named as __execution_result - Add the generated fixtures to the global namespace. - """ - execution_result_fixture_names = [] - for command, control_or_target in product([command for command in Command], ["control", "target"]): - fixture_name = f"{command.name.lower()}_{control_or_target}_execution_result" - globals()[fixture_name] = generate_execution_results_fixture(command, control_or_target) - execution_result_fixture_names.append(fixture_name) - return set(execution_result_fixture_names) - - -EXECUTION_RESULT_FIXTURES = inject_fixtures() - - -def pytest_generate_tests(metafunc): - """This function is called for each test function. - It helps in parameterizing the test functions with the connection objects. - It will provide the connection objects to the "*_execution_result" fixtures as parameters. - This will make sure that the tests are run for all the connection objects available in the configuration. - """ - all_connection_objects = metafunc.config.stash[stash_keys.ALL_CONNECTION_OBJECTS] - requested_fixtures = [fixture_name for fixture_name in metafunc.fixturenames if fixture_name in EXECUTION_RESULT_FIXTURES] - assert isinstance(all_connection_objects, list), "all_connection_objects should be a list" - - if not requested_fixtures: - return - metafunc.parametrize( - requested_fixtures, - [[c] * len(requested_fixtures) for c in all_connection_objects], - indirect=requested_fixtures, - ids=[f"CONNECTION {c.connection_id[:8]}" for c in all_connection_objects], - ) diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/consts.py b/airbyte-ci/connectors/live-tests/src/live_tests/consts.py deleted file mode 100644 index 16bfc69e55bd..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/consts.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -MAX_LINES_IN_REPORT = 1000 diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/pytest.ini b/airbyte-ci/connectors/live-tests/src/live_tests/pytest.ini deleted file mode 100644 index bca444d47897..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/pytest.ini +++ /dev/null @@ -1,9 +0,0 @@ -[pytest] -addopts = --capture=no -console_output_style = progress -log_cli = True -log_cli_level= INFO -markers = - allow_diagnostic_mode: mark a test as eligible for diagnostic mode. - with_state: mark test as running a read command with state. - without_state: mark test as running a read command without state. \ No newline at end of file diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/__init__.py b/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/__init__.py deleted file mode 100644 index f70ecfc3a89e..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/llm_evaluation/README.md b/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/llm_evaluation/README.md deleted file mode 100644 index 93f84175f1ad..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/llm_evaluation/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# LLM-Based Regression Test Evaluation - -Automated evaluation of connector regression test reports using LLM models. - -## How It Works - -After regression tests complete, this evaluates the HTML report and writes a pass/fail judgment to `GITHUB_STEP_SUMMARY`. - -## Configuration - -**Environment Variables:** -- `OPENAI_API_KEY` - API key (use `ollama` for Ollama) -- `OPENAI_BASE_URL` - Base URL for OpenAI-compatible API (e.g., `http://127.0.0.1:11434/v1` for Ollama) -- `EVAL_MODEL` - Model name (defaults to `gpt-4o`) - -**Evaluation Prompt:** -Stored in `.github/prompts/regression-evaluation.prompt.yaml` following GitHub's prompt format. Uses `{{report_text}}` placeholder for dynamic content injection. - -## Local Testing - -```bash -# Install Ollama -curl -fsSL https://ollama.com/install.sh | sh -ollama serve & -ollama pull llama3.2:3b - -# Set environment -export OPENAI_API_KEY=ollama -export OPENAI_BASE_URL=http://127.0.0.1:11434/v1 -export EVAL_MODEL=llama3.2:3b - -# Run evaluation -cd airbyte-ci/connectors/live-tests -poetry install -poetry run python src/live_tests/regression_tests/llm_evaluation/evaluate_report.py \ - --report-path /path/to/report.html -``` diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/llm_evaluation/__init__.py b/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/llm_evaluation/__init__.py deleted file mode 100644 index 7f66676b8716..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/llm_evaluation/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/llm_evaluation/evaluate_report.py b/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/llm_evaluation/evaluate_report.py deleted file mode 100644 index ac9f33c8016e..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/llm_evaluation/evaluate_report.py +++ /dev/null @@ -1,299 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -""" -LLM-based evaluation of regression test reports. - -This script reads a regression test report (HTML format) and uses OpenAI's LLM -to evaluate the results, make a pass/fail judgment, and generate a summary. -The summary is written to GITHUB_STEP_SUMMARY for display in GitHub Actions. -""" - -import argparse -import json -import os -import sys -from pathlib import Path -from typing import Any - -import yaml -from bs4 import BeautifulSoup -from openai import OpenAI - -MAX_REPORT_CHARS = 200000 - -# Default evaluation prompt -EVAL_PROMPT = """You are an expert at evaluating connector regression test results. -Your task is to analyze the test report and determine if the regression tests should PASS or FAIL. - -Consider the following criteria: -1. All test cases should pass (no failed tests) -2. Record count differences between control and target versions should be minimal or explainable -3. Message count differences should not indicate data loss or corruption -4. Stream coverage should be reasonable -5. Any warnings or errors in test outputs should be evaluated for severity - -Provide your evaluation in the following JSON format: -{ - "pass": true/false, - "summary": "A concise 2-3 sentence summary of the evaluation", - "reasoning": "Detailed reasoning for your pass/fail decision, including specific issues found", - "severity": "critical/major/minor/none", - "recommendations": "Any recommendations for addressing issues" -} - -Be strict but fair in your evaluation. Minor differences are acceptable, but data loss, -corruption, or test failures should result in a FAIL.""" - - -def load_prompt_from_yaml(yaml_path: Path | None = None) -> tuple[list[dict[str, str]] | None, str | None, dict[str, Any] | None]: - """ - Load prompt from GitHub-format YAML file. - - Args: - yaml_path: Path to the .prompt.yaml file. If None, uses default location. - - Returns: - Tuple of (messages, model, modelParameters) or (None, None, None) if file not found or invalid - """ - if yaml_path is None: - # Default location: .github/prompts/regression-evaluation.prompt.yaml - github_workspace = os.environ.get("GITHUB_WORKSPACE") - if github_workspace: - yaml_path = Path(github_workspace) / ".github" / "prompts" / "regression-evaluation.prompt.yaml" - else: - script_dir = Path(__file__).parent - repo_root = script_dir.parent.parent.parent.parent.parent.parent - yaml_path = repo_root / ".github" / "prompts" / "regression-evaluation.prompt.yaml" - - if not yaml_path.exists(): - print(f"Prompt file not found at {yaml_path}, using default hardcoded prompt") - return None, None, None - - try: - with open(yaml_path, "r", encoding="utf-8") as f: - prompt_data = yaml.safe_load(f) - - messages = prompt_data.get("messages", []) - model = prompt_data.get("model") - model_params = prompt_data.get("modelParameters", {}) - - if not messages: - print(f"Warning: No messages found in {yaml_path}, using default hardcoded prompt") - return None, None, None - - print(f"Loaded prompt from {yaml_path}") - return messages, model, model_params - - except Exception as e: - print(f"Warning: Failed to load prompt from {yaml_path}: {e}") - print("Using default hardcoded prompt") - return None, None, None - - -def load_report_text(html_path: Path) -> str: - """ - Load and convert HTML report to clean text. - - Args: - html_path: Path to the report.html file - - Returns: - Clean text representation of the report - """ - with open(html_path, "r", encoding="utf-8") as f: - html_content = f.read() - - soup = BeautifulSoup(html_content, "html.parser") - - for element in soup(["script", "style"]): - element.decompose() - - report_text = soup.get_text("\n", strip=True) - - report_text = "\n".join(line.strip() for line in report_text.splitlines() if line.strip()) - - if len(report_text) > MAX_REPORT_CHARS: - original_length = len(report_text) - report_text = report_text[:MAX_REPORT_CHARS] - truncation_note = f"\n\n[Report truncated from {original_length} to {MAX_REPORT_CHARS} characters for evaluation]" - report_text += truncation_note - print(f"Warning: Report truncated from {original_length} to {MAX_REPORT_CHARS} characters") - - return report_text - - -def evaluate_with_llm(report_text: str, prompt: str | None = None, prompt_yaml_path: Path | None = None) -> dict[str, Any]: - """ - Use OpenAI LLM to evaluate the regression test report. - - Supports both OpenAI API and Ollama (OpenAI-compatible). - Configure via environment variables: - - OPENAI_API_KEY: API key (use 'ollama' for Ollama) - - OPENAI_BASE_URL: Optional base URL (e.g., http://127.0.0.1:11434/v1 for Ollama) - - EVAL_MODEL: Model name (defaults to gpt-4o, use llama3.2:3b for Ollama) - - EVAL_PROMPT_PATH: Optional path to custom .prompt.yaml file - - Args: - report_text: Full text of the report - prompt: Optional custom evaluation prompt string (legacy, overrides YAML) - prompt_yaml_path: Optional path to .prompt.yaml file - - Returns: - Dictionary containing evaluation results with 'pass', 'summary', 'reasoning', 'severity', and 'recommendations' keys - - Raises: - Exception: If LLM evaluation fails after retry - """ - api_key = os.environ.get("OPENAI_API_KEY") - base_url = os.environ.get("OPENAI_BASE_URL") - model = os.environ.get("EVAL_MODEL", "gpt-4o") - - if base_url: - client = OpenAI(api_key=api_key, base_url=base_url) - print(f"Using custom base URL: {base_url}") - else: - client = OpenAI(api_key=api_key) - - yaml_messages, yaml_model, yaml_params = load_prompt_from_yaml(prompt_yaml_path) - - if yaml_model and not os.environ.get("EVAL_MODEL"): - model = yaml_model - - temperature = 0.3 - if yaml_params and "temperature" in yaml_params: - temperature = yaml_params["temperature"] - - print(f"Using model: {model}") - - if prompt is not None: - messages = [ - {"role": "system", "content": prompt}, - {"role": "user", "content": f"Report:\n\n{report_text}"}, - ] - elif yaml_messages: - messages = [] - for msg in yaml_messages: - content = msg.get("content", "") - content = content.replace("{{report_text}}", report_text) - messages.append({"role": msg["role"], "content": content}) - else: - # Fallback to hardcoded EVAL_PROMPT - messages = [ - {"role": "system", "content": EVAL_PROMPT}, - {"role": "user", "content": f"Report:\n\n{report_text}"}, - ] - - try: - response = client.chat.completions.create( - model=model, - messages=messages, - temperature=temperature, - response_format={"type": "json_object"}, - ) - - evaluation = json.loads(response.choices[0].message.content) - return evaluation - except Exception as e: - error_msg = str(e).lower() - if "response_format" in error_msg or "json_object" in error_msg: - print(f"Warning: JSON response format not supported, retrying without it: {e}") - response = client.chat.completions.create( - model=model, - messages=messages, - temperature=temperature, - ) - content = response.choices[0].message.content - evaluation = json.loads(content) - return evaluation - raise - - -def write_github_summary(evaluation: dict[str, Any], model: str | None = None) -> None: - """ - Write the evaluation summary to GITHUB_STEP_SUMMARY. - - Args: - evaluation: LLM evaluation results - model: Model name used for evaluation (optional) - """ - summary_file = os.environ.get("GITHUB_STEP_SUMMARY") - if not summary_file: - print("Warning: GITHUB_STEP_SUMMARY environment variable not set. Writing to stdout instead.") - summary_file = "/dev/stdout" - - status_emoji = "✅" if evaluation["pass"] else "❌" - - model_info = f"model: {model}" if model else "OpenAI-compatible API" - - markdown = f"""# {status_emoji} Regression Test Evaluation: {"PASS" if evaluation['pass'] else "FAIL"} - -{evaluation['summary']} - - -{evaluation['reasoning']} - -{evaluation.get('recommendations', 'No specific recommendations.')} - ---- -*This evaluation was generated using {model_info}* -""" - - with open(summary_file, "a", encoding="utf-8") as f: - f.write(markdown) - - print(f"Summary written to {summary_file}") - - -def main(): - """Main entry point for the LLM evaluation script.""" - parser = argparse.ArgumentParser(description="Evaluate regression test reports using OpenAI LLM") - parser.add_argument("--report-path", type=Path, required=True, help="Path to the report.html file") - parser.add_argument("--prompt-file", type=Path, help="Optional path to a custom evaluation prompt file") - parser.add_argument("--output-json", type=Path, help="Optional path to write evaluation results as JSON") - - args = parser.parse_args() - - if not os.environ.get("OPENAI_API_KEY"): - print("Error: OPENAI_API_KEY environment variable not set", file=sys.stderr) - sys.exit(1) - - if not args.report_path.exists(): - print(f"Error: Report file not found: {args.report_path}", file=sys.stderr) - sys.exit(1) - - print(f"Loading report from: {args.report_path}") - report_text = load_report_text(args.report_path) - print(f"Report loaded: {len(report_text)} characters") - - custom_prompt = None - if args.prompt_file and args.prompt_file.exists(): - with open(args.prompt_file, "r", encoding="utf-8") as f: - custom_prompt = f.read() - print(f"Using custom prompt from: {args.prompt_file}") - - prompt_yaml_path = None - eval_prompt_path = os.environ.get("EVAL_PROMPT_PATH") - if eval_prompt_path: - prompt_yaml_path = Path(eval_prompt_path) - - print("Evaluating report with LLM...") - evaluation = evaluate_with_llm(report_text, custom_prompt, prompt_yaml_path) - - print(f"\nEvaluation Result: {'PASS' if evaluation['pass'] else 'FAIL'}") - print(f"Summary: {evaluation['summary']}") - - model = os.environ.get("EVAL_MODEL", "gpt-4o") - write_github_summary(evaluation, model) - - if args.output_json: - output_data = {"evaluation": evaluation} - with open(args.output_json, "w", encoding="utf-8") as f: - json.dump(output_data, f, indent=2) - print(f"Evaluation results written to: {args.output_json}") - - sys.exit(0 if evaluation["pass"] else 1) - - -if __name__ == "__main__": - main() diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_check.py b/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_check.py deleted file mode 100644 index b18298472aef..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_check.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -from collections.abc import Callable - -import pytest - -from live_tests.commons.models import ExecutionResult -from live_tests.consts import MAX_LINES_IN_REPORT -from live_tests.utils import fail_test_on_failing_execution_results, is_successful_check, tail_file - -pytestmark = [ - pytest.mark.anyio, -] - - -async def test_check_passes_on_both_versions( - record_property: Callable, - check_control_execution_result: ExecutionResult, - check_target_execution_result: ExecutionResult, -) -> None: - """This test runs the check command on both the control and target connectors. - It makes sure that the check command succeeds on both connectors. - Success is determined by the presence of a connection status message with a status of SUCCEEDED. - """ - fail_test_on_failing_execution_results( - record_property, - [ - check_control_execution_result, - check_target_execution_result, - ], - ) - - successful_control_check: bool = is_successful_check(check_control_execution_result) - successful_target_check: bool = is_successful_check(check_target_execution_result) - error_messages = [] - if not successful_control_check: - record_property( - f"Control CHECK standard output [Last {MAX_LINES_IN_REPORT} lines]", - tail_file(check_control_execution_result.stdout_file_path, n=MAX_LINES_IN_REPORT), - ) - error_messages.append("The control check did not succeed, we cannot compare the results.") - if not successful_target_check: - record_property( - f"Target CHECK standard output [Last {MAX_LINES_IN_REPORT} lines]", - tail_file(check_target_execution_result.stdout_file_path, n=MAX_LINES_IN_REPORT), - ) - error_messages.append("The target check did not succeed. Check the test artifacts for more information.") - if error_messages: - pytest.fail("\n".join(error_messages)) diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_discover.py b/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_discover.py deleted file mode 100644 index f4cd47d4b8e8..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_discover.py +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -import json -from collections.abc import Callable, Iterable - -import pytest -from _pytest.fixtures import SubRequest -from airbyte_protocol.models import AirbyteStream # type: ignore - -from live_tests.commons.models import ExecutionResult -from live_tests.utils import fail_test_on_failing_execution_results, get_and_write_diff, get_catalog - -pytestmark = [ - pytest.mark.anyio, -] - - -async def test_catalog_are_the_same( - record_property: Callable, - request: SubRequest, - discover_control_execution_result: ExecutionResult, - discover_target_execution_result: ExecutionResult, -) -> None: - """This test runs the discover command on both the control and target connectors. - It makes sure that the discover command returns the same catalog for both connectors. - A catalog diff is generated and stored in the test artifacts if the catalogs are not the same. - """ - fail_test_on_failing_execution_results( - record_property, - [ - discover_control_execution_result, - discover_target_execution_result, - ], - ) - - control_catalog = get_catalog(discover_control_execution_result) - target_catalog = get_catalog(discover_target_execution_result) - - if control_catalog is None: - pytest.skip("The control discover did not return a catalog, we cannot compare the results.") - - if target_catalog is None: - pytest.fail("The target discover did not return a catalog. Check the test artifacts for more information.") - - control_streams = {c.name: c for c in control_catalog.streams} - target_streams = {t.name: t for t in target_catalog.streams} - - catalog_diff_path_prefix = "catalog_diff" - catalog_diff = get_and_write_diff( - request, - _get_filtered_sorted_streams(control_streams, target_streams.keys(), True), - _get_filtered_sorted_streams(target_streams, control_streams.keys(), True), - catalog_diff_path_prefix, - True, - None, - ) - - control_streams_diff_path_prefix = "control_streams_diff" - control_streams_diff = get_and_write_diff( - request, - _get_filtered_sorted_streams(control_streams, target_streams.keys(), False), - [], - control_streams_diff_path_prefix, - True, - None, - ) - - target_streams_diff_path_prefix = "target_streams_diff" - target_streams_diff = get_and_write_diff( - request, - [], - _get_filtered_sorted_streams(target_streams, control_streams.keys(), False), - target_streams_diff_path_prefix, - True, - None, - ) - - has_diff = catalog_diff or control_streams_diff or target_streams_diff - - if has_diff: - record_property("Catalog diff", catalog_diff) - record_property("Control streams diff", control_streams_diff) - record_property("Target streams diff", target_streams_diff) - - if control_streams.keys() != target_streams.keys(): - pytest.fail( - f"The set of streams in the control and target catalogs do not match. control_streams={', '.join(control_streams.keys())} target_streams={', '.join(target_streams.keys())}. Detailed diff is stored in Diff is stored at {catalog_diff}, {control_streams_diff}, and {target_streams_diff}." - ) - - else: - pytest.fail( - f"The control and target output are not the same. Diff is stored at {catalog_diff}, {control_streams_diff}, and {target_streams_diff}." - ) - - -def _get_filtered_sorted_streams(streams: dict[str, AirbyteStream], stream_set: Iterable[str], include_target: bool) -> list[dict]: - return sorted( - filter( - lambda x: (x["name"] in stream_set if include_target else x["name"] not in stream_set), - [json.loads(s.json(sort_keys=True)) for s in streams.values()], - ), - key=lambda x: x["name"], - ) diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_read.py b/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_read.py deleted file mode 100644 index c55dae963289..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_read.py +++ /dev/null @@ -1,551 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -import json -from collections.abc import Callable, Generator, Iterable -from typing import TYPE_CHECKING, Any, Optional - -import pytest -from airbyte_protocol.models import AirbyteMessage # type: ignore -from deepdiff import DeepDiff # type: ignore - -from live_tests.commons.models import ExecutionResult -from live_tests.utils import fail_test_on_failing_execution_results, get_and_write_diff, get_test_logger, write_string_to_test_artifact - -if TYPE_CHECKING: - from _pytest.fixtures import SubRequest - -pytestmark = [ - pytest.mark.anyio, -] - - -EXCLUDE_PATHS = ["emitted_at"] - - -class TestDataIntegrity: - """This class contains tests that check if the data integrity is preserved between the control and target versions. - The tests have some overlap but they are meant to be gradually stricter in terms of integrity checks. - - 1. test_record_count: On each stream, check if the target version produces at least the same number of records as the control version. - 2. test_all_pks_are_produced_in_target_version: On each stream, check if all primary key values produced by the control version are present in the target version. - 3. test_all_records_are_the_same: On each stream, check if all records produced by the control version are the same as in the target version. This will write a diff of the records to the test artifacts. - - All these test have a full refresh and incremental variant. - """ - - async def _check_all_pks_are_produced_in_target_version( - self, - request: SubRequest, - record_property: Callable, - read_with_state_control_execution_result: ExecutionResult, - read_with_state_target_execution_result: ExecutionResult, - ) -> None: - """This test gathers all primary key values from the control version and checks if they are present in the target version for each stream. - If there are missing primary keys, the test fails and the missing records are stored in the test artifacts. - Args: - request (SubRequest): The test request. - record_property (Callable): A callable for stashing information on the report. - streams: (Iterable[str]): The list of streams configured for the connection. - primary_keys_per_stream (Dict[str, Optional[List[str]]]): The primary keys for each stream. - read_with_state_control_execution_result (ExecutionResult): The control version execution result. - read_with_state_target_execution_result (ExecutionResult): The target version execution result. - """ - if not read_with_state_control_execution_result.primary_keys_per_stream: - pytest.skip("No primary keys provided on any stream. Skipping the test.") - - logger = get_test_logger(request) - streams_with_missing_records = set() - for stream_name in read_with_state_control_execution_result.configured_streams: - _primary_key = read_with_state_control_execution_result.primary_keys_per_stream[stream_name] - if not _primary_key: - # TODO: report skipped PK test per individual stream - logger.warning(f"No primary keys provided on stream {stream_name}.") - continue - - primary_key = _primary_key[0] if isinstance(_primary_key, list) else _primary_key - - control_pks = set() - target_pks = set() - logger.info(f"Retrieving primary keys for stream {stream_name} on control version.") - for control_record in read_with_state_control_execution_result.get_records_per_stream(stream_name): - control_pks.add(control_record.record.data[primary_key]) - - logger.info(f"Retrieving primary keys for stream {stream_name} on target version.") - for target_record in read_with_state_target_execution_result.get_records_per_stream(stream_name): - target_pks.add(target_record.record.data[primary_key]) - - if missing_pks := control_pks - target_pks: - logger.warning(f"Found {len(missing_pks)} primary keys for stream {stream_name}. Retrieving missing records.") - streams_with_missing_records.add(stream_name) - missing_records = [ - r - for r in read_with_state_control_execution_result.get_records_per_stream(stream_name) - if r.record.data[primary_key] in missing_pks - ] - record_property( - f"Missing records on stream {stream_name}", - json.dumps(missing_records), - ) - artifact_path = write_string_to_test_artifact( - request, - json.dumps(missing_records), - f"missing_records_{stream_name}.json", - subdir=request.node.name, - ) - logger.info(f"Missing records for stream {stream_name} are stored in {artifact_path}.") - if streams_with_missing_records: - pytest.fail(f"Missing records for streams: {', '.join(streams_with_missing_records)}.") - - async def _check_record_counts( - self, - record_property: Callable, - read_control_execution_result: ExecutionResult, - read_target_execution_result: ExecutionResult, - ) -> None: - record_count_difference_per_stream: dict[str, dict[str, int]] = {} - for stream_name in read_control_execution_result.configured_streams: - control_records_count = sum(1 for _ in read_control_execution_result.get_records_per_stream(stream_name)) - target_records_count = sum(1 for _ in read_target_execution_result.get_records_per_stream(stream_name)) - - difference = { - "delta": target_records_count - control_records_count, - "control": control_records_count, - "target": target_records_count, - } - - if difference["delta"] != 0: - record_count_difference_per_stream[stream_name] = difference - error_messages = [] - for stream, difference in record_count_difference_per_stream.items(): - if difference["delta"] > 0: - error_messages.append( - f"Stream {stream} has {difference['delta']} more records in the target version ({difference['target']} vs. {difference['control']})." - ) - if difference["delta"] < 0: - error_messages.append( - f"Stream {stream} has {-difference['delta']} fewer records in the target version({difference['target']} vs. {difference['control']})." - ) - if error_messages: - record_property("Record count differences", "\n".join(error_messages)) - pytest.fail("Record counts are different.") - - async def _check_all_records_are_the_same( - self, - request: SubRequest, - record_property: Callable, - read_control_execution_result: ExecutionResult, - read_target_execution_result: ExecutionResult, - ) -> None: - """This test checks if all records in the control version are present in the target version for each stream. - If there are mismatches, the test fails and the missing records are stored in the test artifacts. - It will catch differences in record schemas, missing records, and extra records. - - Args: - request (SubRequest): The test request. - read_control_execution_result (ExecutionResult): The control version execution result. - read_target_execution_result (ExecutionResult): The target version execution result. - """ - streams_with_diff = set() - for stream in read_control_execution_result.configured_streams: - control_records = list(read_control_execution_result.get_records_per_stream(stream)) - target_records = list(read_target_execution_result.get_records_per_stream(stream)) - - if control_records and not target_records: - pytest.fail(f"Stream {stream} is missing in the target version.") - - if primary_key := read_control_execution_result.primary_keys_per_stream.get(stream): - diffs = self._get_diff_on_stream_with_pk( - request, - record_property, - stream, - control_records, - target_records, - primary_key, - ) - else: - diffs = self._get_diff_on_stream_without_pk( - request, - record_property, - stream, - control_records, - target_records, - ) - - if diffs: - streams_with_diff.add(stream) - - if streams_with_diff: - messages = [ - f"Records for stream {stream} are different. Please check the diff in the test artifacts for debugging." - for stream in sorted(streams_with_diff) - ] - pytest.fail("/n".join(messages)) - - def _check_record_schema_match( - self, - request: SubRequest, - record_property: Callable, - control_execution_result: ExecutionResult, - target_execution_result: ExecutionResult, - ) -> None: - """This test checks if the schema of the records in the control and target versions match. - It compares the meta schema inferred for each streams on the control and target versions. - It also fetches an example record for each stream from the DuckDB instance and compares the schema of the records. - - Args: - record_property (Callable): The record property to store the mismatching fields. - control_execution_result (ExecutionResult): The control version execution result. - target_execution_result (ExecutionResult): The target version execution result. - """ - logger = get_test_logger(request) - - assert control_execution_result.stream_schemas is not None, "Control schemas were not inferred." - assert target_execution_result.stream_schemas is not None, "Target schemas were not inferred." - - mismatches_count = 0 - for stream in control_execution_result.stream_schemas: - control_schema = control_execution_result.stream_schemas.get(stream, {}) - if not control_schema: - logger.warning(f"Stream {stream} was not found in the control results.") - - target_schema = target_execution_result.stream_schemas.get(stream, {}) - if control_schema and not target_schema: - logger.warning(f"Stream {stream} was present in the control results but not in the target results.") - - diff = DeepDiff(control_schema, target_schema, ignore_order=True) - if diff: - record_property(f"{stream} diff between control and target version", diff.pretty()) - try: - control_record = next(control_execution_result.get_records_per_stream(stream)) - control_example = json.dumps(control_record.record.data, indent=2) - record_property(f"{stream} example record for control version", control_example) - except StopIteration: - logger.warning(f"Stream {stream} has no record in the control version.") - try: - target_record = next(target_execution_result.get_records_per_stream(stream)) - target_example = json.dumps(target_record.record.data, indent=2) - record_property(f"{stream} example record for target version", target_example) - except StopIteration: - logger.warning(f"Stream {stream} has no record in the target version.") - mismatches_count += 1 - - if mismatches_count > 0: - pytest.fail(f"{mismatches_count} streams have mismatching schemas between control and target versions.") - - @pytest.mark.with_state() - async def test_record_count_with_state( - self, - record_property: Callable, - read_with_state_control_execution_result: ExecutionResult, - read_with_state_target_execution_result: ExecutionResult, - ) -> None: - """This test compares the record counts between the control and target versions on each stream. - Records are pulled from the output of the read command to which the connection state is passed. - It fails if there are any differences in the record counts. - It is not bulletproof, if the upstream source supports insertion or deletion it may lead to false positives. - The HTTP cache used between the control and target versions command execution might limit this problem. - Extra records in the target version might mean that a bug was fixed, but it could also mean that the target version produces duplicates. - We should add a new test for duplicates and not fail this one if extra records are found. - More advanced checks are done in the other tests. - """ - fail_test_on_failing_execution_results( - record_property, - [ - read_with_state_control_execution_result, - read_with_state_target_execution_result, - ], - ) - await self._check_record_counts( - record_property, - read_with_state_control_execution_result, - read_with_state_target_execution_result, - ) - - @pytest.mark.without_state() - async def test_record_count_without_state( - self, - record_property: Callable, - read_control_execution_result: ExecutionResult, - read_target_execution_result: ExecutionResult, - ) -> None: - """This test compares the record counts between the control and target versions on each stream. - Records are pulled from the output of the read command to which no connection state is passed (leading to a full-refresh like sync). - It fails if there are any differences in the record counts. - It is not bulletproof, if the upstream source supports insertion or deletion it may lead to false positives. - The HTTP cache used between the control and target versions command execution might limit this problem. - Extra records in the target version might mean that a bug was fixed, but it could also mean that the target version produces duplicates. - We should add a new test for duplicates and not fail this one if extra records are found. - More advanced checks are done in the other tests. - """ - fail_test_on_failing_execution_results( - record_property, - [ - read_control_execution_result, - read_target_execution_result, - ], - ) - await self._check_record_counts( - record_property, - read_control_execution_result, - read_target_execution_result, - ) - - @pytest.mark.with_state() - async def test_all_pks_are_produced_in_target_version_with_state( - self, - request: SubRequest, - record_property: Callable, - read_with_state_control_execution_result: ExecutionResult, - read_with_state_target_execution_result: ExecutionResult, - ) -> None: - """This test checks if all primary key values produced by the control version are present in the target version for each stream. - It is reading the records from the output of the read command to which the connection state is passed. - A failing test means that the target version is missing some records. - """ - fail_test_on_failing_execution_results( - record_property, - [ - read_with_state_control_execution_result, - read_with_state_target_execution_result, - ], - ) - await self._check_all_pks_are_produced_in_target_version( - request, - record_property, - read_with_state_control_execution_result, - read_with_state_target_execution_result, - ) - - @pytest.mark.without_state() - async def test_all_pks_are_produced_in_target_version_without_state( - self, - request: SubRequest, - record_property: Callable, - read_control_execution_result: ExecutionResult, - read_target_execution_result: ExecutionResult, - ) -> None: - """This test checks if all primary key values produced by the control version are present in the target version for each stream. - Records are pulled from the output of the read command to which no connection state is passed (leading to a full-refresh like sync). - A failing test means that the target version is missing some records. - """ - fail_test_on_failing_execution_results( - record_property, - [ - read_control_execution_result, - read_target_execution_result, - ], - ) - await self._check_all_pks_are_produced_in_target_version( - request, - record_property, - read_control_execution_result, - read_target_execution_result, - ) - - @pytest.mark.with_state() - async def test_record_schema_match_with_state( - self, - request: SubRequest, - record_property: Callable, - read_with_state_control_execution_result: ExecutionResult, - read_with_state_target_execution_result: ExecutionResult, - ) -> None: - """This test checks if the schema of the streams in the control and target versions match. - It produces a meta schema for each stream on control and target version and compares them. - It is not using the catalog schema, but inferring schemas from the actual records produced by the read command. - Records are pulled from the output of the read command to which the connection state is passed. - """ - self._check_record_schema_match( - request, - record_property, - read_with_state_control_execution_result, - read_with_state_target_execution_result, - ) - - @pytest.mark.without_state() - async def test_record_schema_match_without_state( - self, - request: SubRequest, - record_property: Callable, - read_control_execution_result: ExecutionResult, - read_target_execution_result: ExecutionResult, - ) -> None: - """This test checks if the schema of the streams in the control and target versions match. - It produces a meta schema for each stream on control and target version and compares them. - It is not using the catalog schema, but inferring schemas from the actual records produced by the read command. - Records are pulled from the output of the read command to which the connection state is passed. - """ - self._check_record_schema_match( - request, - record_property, - read_control_execution_result, - read_target_execution_result, - ) - - @pytest.mark.allow_diagnostic_mode - @pytest.mark.with_state() - async def test_all_records_are_the_same_with_state( - self, - request: SubRequest, - record_property: Callable, - read_with_state_control_execution_result: ExecutionResult, - read_with_state_target_execution_result: ExecutionResult, - ) -> None: - """This test compares all records between the control and target versions on each stream. - It is very sensitive to record schema and order changes. - It fails if there are any differences in the records. - It is reading the records from the output of the read command to which the connection state is passed. - """ - fail_test_on_failing_execution_results( - record_property, - [ - read_with_state_control_execution_result, - read_with_state_target_execution_result, - ], - ) - await self._check_all_records_are_the_same( - request, - record_property, - read_with_state_control_execution_result, - read_with_state_target_execution_result, - ) - - @pytest.mark.allow_diagnostic_mode - @pytest.mark.without_state() - async def test_all_records_are_the_same_without_state( - self, - request: SubRequest, - record_property: Callable, - read_control_execution_result: ExecutionResult, - read_target_execution_result: ExecutionResult, - ) -> None: - """This test compares all records between the control and target versions on each stream. - It is very sensitive to record schema and order changes. - It fails if there are any differences in the records. - It is reading the records from the output of the read command to which no connection state is passed (leading to a full-refresh like sync). - """ - fail_test_on_failing_execution_results( - record_property, - [ - read_control_execution_result, - read_target_execution_result, - ], - ) - await self._check_all_records_are_the_same( - request, - record_property, - read_control_execution_result, - read_target_execution_result, - ) - - def _get_diff_on_stream_with_pk( - self, - request: SubRequest, - record_property: Callable, - stream: str, - control_records: list[AirbyteMessage], - target_records: list[AirbyteMessage], - primary_key: list[str], - ) -> Optional[Iterable[str]]: - control_pks = {r.record.data[primary_key[0]] for r in control_records} - target_pks = {r.record.data[primary_key[0]] for r in target_records} - - # Compare the diff for all records whose primary key is in - record_diff_path_prefix = f"{stream}_record_diff" - record_diff = get_and_write_diff( - request, - _get_filtered_sorted_records(control_records, target_pks, True, primary_key), - _get_filtered_sorted_records(target_records, control_pks, True, primary_key), - record_diff_path_prefix, - ignore_order=False, - exclude_paths=EXCLUDE_PATHS, - ) - - control_records_diff_path_prefix = f"{stream}_control_records_diff" - control_records_diff = get_and_write_diff( - request, - _get_filtered_sorted_records(control_records, target_pks, False, primary_key), - [], - control_records_diff_path_prefix, - ignore_order=False, - exclude_paths=EXCLUDE_PATHS, - ) - - target_records_diff_path_prefix = f"{stream}_target_records_diff" - target_records_diff = get_and_write_diff( - request, - [], - _get_filtered_sorted_records(target_records, control_pks, False, primary_key), - target_records_diff_path_prefix, - ignore_order=False, - exclude_paths=EXCLUDE_PATHS, - ) - - has_diff = record_diff or control_records_diff or target_records_diff - - if has_diff: - record_property( - f"{stream} stream: records with primary key in target & control whose values differ", - record_diff, - ) - record_property( - f"{stream} stream: records in control but not target", - control_records_diff, - ) - record_property( - f"{stream} stream: records in target but not control", - target_records_diff, - ) - - return (record_diff, control_records_diff, target_records_diff) - return None - - def _get_diff_on_stream_without_pk( - self, - request: SubRequest, - record_property: Callable, - stream: str, - control_records: list[AirbyteMessage], - target_records: list[AirbyteMessage], - ) -> Optional[Iterable[str]]: - diff = get_and_write_diff( - request, - [json.loads(r.record.json(sort_keys=True)) for r in control_records], - [json.loads(r.record.json(sort_keys=True)) for r in target_records], - f"{stream}_diff", - ignore_order=True, - exclude_paths=EXCLUDE_PATHS, - ) - if diff: - record_property(f"Diff for stream {stream}", diff) - return (diff,) - return None - - -def _get_filtered_sorted_records( - records: list[AirbyteMessage], - primary_key_set: set[Generator[Any, Any, None]], - include_target: bool, - primary_key: list[str], -) -> list[dict]: - """ - Get a list of records sorted by primary key, and filtered as specified. - - For example, if `include_target` is true, we filter the records such that - only those whose primary key is in `primary_key_set` are returned. - If `include_target` is false, we only return records whose primary key - is not in `primary_key_set`. - """ - if include_target: - _filter = lambda x: x["data"].get(primary_key[0]) in primary_key_set - else: - _filter = lambda x: x["data"].get(primary_key[0]) not in primary_key_set - - return sorted( - filter( - _filter, - [json.loads(s.record.json(sort_keys=True)) for s in records], - ), - key=lambda x: x["data"][primary_key[0]], - ) diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_spec.py b/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_spec.py deleted file mode 100644 index 7a1985fd3e40..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/regression_tests/test_spec.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -from collections.abc import Callable - -import pytest -from airbyte_protocol.models import Type # type: ignore - -from live_tests.commons.models import ExecutionResult -from live_tests.utils import fail_test_on_failing_execution_results - -pytestmark = [ - pytest.mark.anyio, -] - - -async def test_spec_passes_on_both_versions( - record_property: Callable, - spec_control_execution_result: ExecutionResult, - spec_target_execution_result: ExecutionResult, -) -> None: - """This test runs the spec command on both the control and target connectors. - It makes sure that the spec command succeeds on both connectors by checking the presence of a SPEC message. - """ - fail_test_on_failing_execution_results( - record_property, - [ - spec_control_execution_result, - spec_target_execution_result, - ], - ) - - def has_spec(execution_result: ExecutionResult) -> bool: - for message in execution_result.airbyte_messages: - if message.type is Type.SPEC and message.spec: - return True - return False - - if not has_spec(spec_control_execution_result): - pytest.skip("The control spec did not succeed, we cannot compare the results.") - if not has_spec(spec_target_execution_result): - pytest.fail("The target spec did not succeed. Check the test artifacts for more information.") diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/report.py b/airbyte-ci/connectors/live-tests/src/live_tests/report.py deleted file mode 100644 index 78bb06720c72..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/report.py +++ /dev/null @@ -1,411 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -import datetime -import json -from abc import ABC, abstractmethod -from collections import defaultdict -from collections.abc import Iterable, MutableMapping -from copy import deepcopy -from enum import Enum -from functools import cache -from pathlib import Path -from typing import TYPE_CHECKING, Any, Optional - -import requests -import yaml -from jinja2 import Environment, PackageLoader, select_autoescape - -from live_tests import stash_keys -from live_tests.commons.models import Command, ConnectionObjects -from live_tests.consts import MAX_LINES_IN_REPORT - -if TYPE_CHECKING: - from typing import List - - import pytest - from _pytest.config import Config - from airbyte_protocol.models import AirbyteStream, ConfiguredAirbyteStream, SyncMode, Type # type: ignore - - from live_tests.commons.models import ExecutionResult - - -class ReportState(Enum): - INITIALIZING = "initializing" - RUNNING = "running" - FINISHED = "finished" - - -class BaseReport(ABC): - TEMPLATE_NAME: str - - def __init__(self, path: Path, pytest_config: Config) -> None: - self.path = path - self.pytest_config = pytest_config - self.created_at = datetime.datetime.utcnow() - self.updated_at = self.created_at - - self.control_execution_results_per_command: dict[Command, List[ExecutionResult]] = {command: [] for command in Command} - self.target_execution_results_per_command: dict[Command, List[ExecutionResult]] = {command: [] for command in Command} - self.update(ReportState.INITIALIZING) - - @abstractmethod - def render(self) -> None: - pass - - @property - def all_connection_objects(self) -> List[ConnectionObjects]: - return self.pytest_config.stash[stash_keys.ALL_CONNECTION_OBJECTS] - - def add_control_execution_result(self, control_execution_result: ExecutionResult) -> None: - self.control_execution_results_per_command[control_execution_result.command].append(control_execution_result) - self.update() - - def add_target_execution_result(self, target_execution_result: ExecutionResult) -> None: - self.target_execution_results_per_command[target_execution_result.command].append(target_execution_result) - self.update() - - def update(self, state: ReportState = ReportState.RUNNING) -> None: - self._state = state - self.updated_at = datetime.datetime.utcnow() - self.render() - - -class PrivateDetailsReport(BaseReport): - TEMPLATE_NAME = "private_details.html.j2" - SPEC_SECRET_MASK_URL = "https://connectors.airbyte.com/files/registries/v0/specs_secrets_mask.yaml" - - def __init__(self, path: Path, pytest_config: Config) -> None: - self.secret_properties = self.get_secret_properties() - super().__init__(path, pytest_config) - - def get_secret_properties(self) -> list: - response = requests.get(self.SPEC_SECRET_MASK_URL) - response.raise_for_status() - return yaml.safe_load(response.text)["properties"] - - def scrub_secrets_from_config(self, to_scrub: MutableMapping) -> MutableMapping: - if isinstance(to_scrub, dict): - for key, value in to_scrub.items(): - if key in self.secret_properties: - to_scrub[key] = "********" - elif isinstance(value, dict): - to_scrub[key] = self.scrub_secrets_from_config(value) - return to_scrub - - @property - def renderable_connection_objects(self) -> list[dict[str, Any]]: - return [ - { - "workspace_id": connection_objects.workspace_id, - "connection_id": connection_objects.connection_id, - "hashed_connection_id": connection_objects.hashed_connection_id, - "source_config": json.dumps( - self.scrub_secrets_from_config( - deepcopy(connection_objects.source_config.data) if connection_objects.source_config else {} - ), - indent=2, - ), - "url": connection_objects.url, - } - for connection_objects in self.all_connection_objects - ] - - def render(self) -> None: - jinja_env = Environment( - loader=PackageLoader(__package__, "templates"), - autoescape=select_autoescape(), - trim_blocks=False, - lstrip_blocks=True, - ) - template = jinja_env.get_template(self.TEMPLATE_NAME) - rendered = template.render( - user=self.pytest_config.stash[stash_keys.USER], - test_date=self.created_at, - all_connection_objects=self.renderable_connection_objects, - connector_image=self.pytest_config.stash[stash_keys.CONNECTOR_IMAGE], - control_version=self.pytest_config.stash[stash_keys.CONTROL_VERSION], - target_version=self.pytest_config.stash[stash_keys.TARGET_VERSION], - requested_urls_per_command=self.get_requested_urls_per_command(), - fully_generated=self._state is ReportState.FINISHED, - ) - self.path.write_text(rendered) - - def get_requested_urls_per_command( - self, - ) -> dict[Command, list[tuple[int, str, str]]]: - requested_urls_per_command = {} - all_commands = sorted( - list(set(self.control_execution_results_per_command.keys()).union(set(self.target_execution_results_per_command.keys()))), - key=lambda command: command.value, - ) - for command in all_commands: - if command in self.control_execution_results_per_command: - control_flows = [ - flow for exec_result in self.control_execution_results_per_command[command] for flow in exec_result.http_flows - ] - else: - control_flows = [] - if command in self.target_execution_results_per_command: - target_flows = [ - flow for exec_result in self.target_execution_results_per_command[command] for flow in exec_result.http_flows - ] - else: - target_flows = [] - all_flows = [] - max_flows = max(len(control_flows), len(target_flows)) - for i in range(max_flows): - control_url = control_flows[i].request.url if i < len(control_flows) else "" - target_url = target_flows[i].request.url if i < len(target_flows) else "" - all_flows.append((i, control_url, target_url)) - requested_urls_per_command[command] = all_flows - return requested_urls_per_command - - -class TestReport(BaseReport): - TEMPLATE_NAME = "report.html.j2" - - def __init__(self, path: Path, pytest_config: Config, private_details_url: Optional[str] = None) -> None: - self.private_details_url = private_details_url - self.test_results: list[dict[str, Any]] = [] - super().__init__(path, pytest_config) - - def add_test_result(self, test_report: pytest.TestReport, test_documentation: Optional[str] = None) -> None: - cut_properties: list[tuple[str, str]] = [] - for property_name, property_value in test_report.user_properties: - if len(str(property_value).splitlines()) > MAX_LINES_IN_REPORT: - cut_property_name = f"{property_name} (truncated)" - cut_property_value = "\n".join(str(property_value).splitlines()[:MAX_LINES_IN_REPORT]) - cut_property_value += f"\n... and {len(str(property_value).splitlines()) - MAX_LINES_IN_REPORT} more lines.\nPlease check the artifacts files for the full output." - cut_properties.append((cut_property_name, cut_property_value)) - else: - cut_properties.append((property_name, str(property_value))) - self.test_results.append( - { - "name": test_report.head_line, - "result": test_report.outcome, - "output": test_report.longreprtext if test_report.longrepr else "", - "properties": cut_properties, - "documentation": test_documentation, - } - ) - self.update() - - def render(self) -> None: - jinja_env = Environment( - loader=PackageLoader(__package__, "templates"), - autoescape=select_autoescape(), - trim_blocks=False, - lstrip_blocks=True, - ) - template = jinja_env.get_template(self.TEMPLATE_NAME) - rendered = template.render( - fully_generated=self._state is ReportState.FINISHED, - user=self.pytest_config.stash[stash_keys.USER], - test_date=self.updated_at, - connector_image=self.pytest_config.stash[stash_keys.CONNECTOR_IMAGE], - control_version=self.pytest_config.stash[stash_keys.CONTROL_VERSION], - target_version=self.pytest_config.stash[stash_keys.TARGET_VERSION], - all_connection_objects=self.renderable_connection_objects, - message_count_per_type=self.get_message_count_per_type(), - stream_coverage_metrics=self.get_stream_coverage_metrics(), - untested_streams=self.get_untested_streams(), - selected_streams=self.get_configured_streams(), - sync_mode_coverage=self.get_sync_mode_coverage(), - http_metrics_per_command=self.get_http_metrics_per_command(), - record_count_per_command_and_stream=self.get_record_count_per_stream(), - test_results=self.test_results, - max_lines=MAX_LINES_IN_REPORT, - private_details_url=self.private_details_url, - ) - self.path.write_text(rendered) - - @property - def renderable_connection_objects(self) -> list[dict[str, Any]]: - return [ - { - "hashed_connection_id": connection_objects.hashed_connection_id, - "catalog": connection_objects.catalog.json(indent=2) if connection_objects.catalog else {}, - "configured_catalog": connection_objects.configured_catalog.json(indent=2), - "state": json.dumps(connection_objects.state if connection_objects.state else {}, indent=2), - } - for connection_objects in self.all_connection_objects - ] - - def get_stream_coverage_metrics(self) -> dict[str, str]: - configured_catalog_stream_count = len(self.get_configured_streams()) - catalog_stream_count = len(self.all_streams) - coverage = configured_catalog_stream_count / catalog_stream_count if catalog_stream_count > 0 else 0 - return { - "Available in catalog": str(catalog_stream_count), - "In use (in configured catalog)": str(configured_catalog_stream_count), - "Coverage": f"{coverage * 100:.2f}%", - } - - def get_record_count_per_stream( - self, - ) -> dict[Command, dict[str, dict[str, int] | int]]: - record_count_per_command_and_stream: dict[Command, dict[str, dict[str, int] | int]] = {} - for control_results, target_results in zip( - self.control_execution_results_per_command.values(), - self.target_execution_results_per_command.values(), - strict=False, - ): - per_stream_count = defaultdict(lambda: {"control": 0, "target": 0}) # type: ignore - for results, source in [ - (control_results, "control"), - (target_results, "target"), - ]: - stream_schemas: Iterable = [stream_schema for result in results for stream_schema in result.stream_schemas] - - for stream in stream_schemas: - per_stream_count[stream][source] = sum([self._get_record_count_for_stream(result, stream) for result in results]) - for stream in per_stream_count: - per_stream_count[stream]["difference"] = per_stream_count[stream]["target"] - per_stream_count[stream]["control"] - if control_results: - record_count_per_command_and_stream[control_results[0].command] = per_stream_count # type: ignore - - return record_count_per_command_and_stream - - @cache - def _get_record_count_for_stream(self, result: ExecutionResult, stream: str) -> int: - return sum(1 for _ in result.get_records_per_stream(stream)) # type: ignore - - def get_untested_streams(self) -> list[str]: - streams_with_data: set[str] = set() - for stream_count in self.get_record_count_per_stream().values(): - streams_with_data.update(stream_count.keys()) - - return [stream.name for stream in self.all_streams if stream.name not in streams_with_data] - - @property - def all_streams(self) -> List[AirbyteStream]: - # A set would be better but AirbyteStream is not hashable - all_streams = dict() - for connection_objects in self.all_connection_objects: - if connection_objects.catalog: - for stream in connection_objects.catalog.streams: - all_streams[stream.name] = stream - return list(all_streams.values()) - - @property - def all_configured_streams(self) -> List[ConfiguredAirbyteStream]: - all_configured_streams = dict() - for connection_objects in self.all_connection_objects: - if connection_objects.configured_catalog: - for configured_airbyte_stream in connection_objects.configured_catalog.streams: - all_configured_streams[configured_airbyte_stream.stream.name] = configured_airbyte_stream - return list(all_configured_streams.values()) - - def get_configured_streams(self) -> dict[str, dict[str, SyncMode | bool]]: - untested_streams = self.get_untested_streams() - return ( - { - configured_stream.stream.name: { - "sync_mode": configured_stream.sync_mode, - "has_data": configured_stream.stream.name not in untested_streams, - } - for configured_stream in sorted( - self.all_configured_streams, - key=lambda x: x.stream.name, - ) - } - if self.all_configured_streams - else {} - ) - - def get_sync_mode_coverage(self) -> dict[SyncMode, int]: - count_per_sync_mode: dict[SyncMode, int] = defaultdict(int) - for s in self.get_configured_streams().values(): - count_per_sync_mode[s["sync_mode"]] += 1 - return count_per_sync_mode - - def get_message_count_per_type( - self, - ) -> tuple[list[Command], dict[Type, dict[Command, dict[str, int]]]]: - message_count_per_type_and_command: dict[Type, dict[Command, dict[str, int]]] = {} - all_message_types = set() - all_commands = set() - # Gather all message types from both control and target execution reports - for execution_results_per_command in [ - self.control_execution_results_per_command, - self.target_execution_results_per_command, - ]: - for command, execution_results in execution_results_per_command.items(): - all_commands.add(command) - for execution_result in execution_results: - for message_type in execution_result.get_message_count_per_type().keys(): - all_message_types.add(message_type) - - all_commands_sorted = sorted(all_commands, key=lambda command: command.value) - all_message_types_sorted = sorted(all_message_types, key=lambda message_type: message_type.value) - - # Iterate over all message types and commands to count messages - for message_type in all_message_types_sorted: - message_count_per_type_and_command[message_type] = {} - for command in all_commands_sorted: - message_count_per_type_and_command[message_type][command] = { - "control": 0, - "target": 0, - } - if command in self.control_execution_results_per_command: - for control_result in self.control_execution_results_per_command[command]: - message_count_per_type_and_command[message_type][command]["control"] += ( - control_result.get_message_count_per_type().get(message_type, 0) - ) - if command in self.target_execution_results_per_command: - for target_result in self.target_execution_results_per_command[command]: - message_count_per_type_and_command[message_type][command]["target"] += ( - target_result.get_message_count_per_type().get(message_type, 0) - ) - - message_count_per_type_and_command[message_type][command]["difference"] = ( - message_count_per_type_and_command[message_type][command]["target"] - - message_count_per_type_and_command[message_type][command]["control"] - ) - return all_commands_sorted, message_count_per_type_and_command - - def get_http_metrics_per_command( - self, - ) -> dict[Command, dict[str, dict[str, int | str] | int]]: - metrics_per_command: dict[Command, dict[str, dict[str, int | str] | int]] = {} - - for control_results, target_results in zip( - self.control_execution_results_per_command.values(), - self.target_execution_results_per_command.values(), - strict=False, - ): - # TODO - # Duplicate flow counts may be wrong when we gather results from multiple connections - control_flow_count = sum([len(control_result.http_flows) for control_result in control_results]) - control_all_urls = [f.request.url for control_result in control_results for f in control_result.http_flows] - control_duplicate_flow_count = len(control_all_urls) - len(set(control_all_urls)) - control_cache_hits_count = sum(1 for control_result in control_results for f in control_result.http_flows if f.is_replay) - control_cache_hit_ratio = f"{(control_cache_hits_count / control_flow_count) * 100:.2f}%" if control_flow_count != 0 else "N/A" - - target_flow_count = sum([len(target_result.http_flows) for target_result in target_results]) - target_all_urls = [f.request.url for target_result in target_results for f in target_result.http_flows] - target_duplicate_flow_count = len(target_all_urls) - len(set(target_all_urls)) - - target_cache_hits_count = sum(1 for target_result in target_results for f in target_result.http_flows if f.is_replay) - target_cache_hit_ratio = f"{(target_cache_hits_count / target_flow_count) * 100:.2f}%" if target_flow_count != 0 else "N/A" - - flow_count_difference = target_flow_count - control_flow_count - if control_results: - metrics_per_command[control_results[0].command] = { - "control": { - "flow_count": control_flow_count, - "duplicate_flow_count": control_duplicate_flow_count, - "cache_hits_count": control_cache_hits_count, - "cache_hit_ratio": control_cache_hit_ratio, - }, - "target": { - "flow_count": target_flow_count, - "duplicate_flow_count": target_duplicate_flow_count, - "cache_hits_count": target_cache_hits_count, - "cache_hit_ratio": target_cache_hit_ratio, - }, - "difference": flow_count_difference, - } - - return metrics_per_command diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/stash_keys.py b/airbyte-ci/connectors/live-tests/src/live_tests/stash_keys.py deleted file mode 100644 index 4d05f4e93974..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/stash_keys.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -from pathlib import Path -from typing import List - -import pytest - -from live_tests.commons.evaluation_modes import TestEvaluationMode -from live_tests.commons.models import ConnectionObjects, ConnectionSubset -from live_tests.report import PrivateDetailsReport, TestReport - -AIRBYTE_API_KEY = pytest.StashKey[str]() -AUTO_SELECT_CONNECTION = pytest.StashKey[bool]() -ALL_CONNECTION_OBJECTS = pytest.StashKey[List[ConnectionObjects]]() -CONNECTION_URL = pytest.StashKey[str | None]() -CONNECTOR_IMAGE = pytest.StashKey[str]() -CONTROL_VERSION = pytest.StashKey[str]() -CONNECTION_SUBSET = pytest.StashKey[ConnectionSubset]() -DAGGER_LOG_PATH = pytest.StashKey[Path]() -DUCKDB_PATH = pytest.StashKey[Path]() -HTTP_DUMP_CACHE_VOLUMES = pytest.StashKey[list]() -RUN_IN_AIRBYTE_CI = pytest.StashKey[bool]() # Running in airbyte-ci, locally or in GhA -IS_PRODUCTION_CI = pytest.StashKey[bool]() # Running in airbyte-ci in GhA -IS_PERMITTED_BOOL = pytest.StashKey[bool]() -PR_URL = pytest.StashKey[str]() -TEST_REPORT = pytest.StashKey[TestReport]() -PRIVATE_DETAILS_REPORT = pytest.StashKey[PrivateDetailsReport]() -RETRIEVAL_REASONS = pytest.StashKey[str]() -SELECTED_STREAMS = pytest.StashKey[set[str]]() -SESSION_RUN_ID = pytest.StashKey[str]() -SHOULD_READ_WITH_STATE = pytest.StashKey[bool]() -DISABLE_PROXY = pytest.StashKey[bool]() -TARGET_VERSION = pytest.StashKey[str]() -TEST_ARTIFACT_DIRECTORY = pytest.StashKey[Path]() -USER = pytest.StashKey[str]() -WORKSPACE_ID = pytest.StashKey[str]() -TEST_EVALUATION_MODE = pytest.StashKey[TestEvaluationMode] -MAX_CONNECTIONS = pytest.StashKey[int | None]() diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/templates/__init__.py b/airbyte-ci/connectors/live-tests/src/live_tests/templates/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/templates/private_details.html.j2 b/airbyte-ci/connectors/live-tests/src/live_tests/templates/private_details.html.j2 deleted file mode 100644 index 2505bb3d3cea..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/templates/private_details.html.j2 +++ /dev/null @@ -1,305 +0,0 @@ - - - - - - Test Report - - - - - - - -

-

Live test private details

-
-

Context

-
-
    -
  • Tester: {{ user }}
  • -
  • Test date: {{ test_date }}
  • -
  • Connector image: {{ connector_image }}
  • -
  • Control version: {{ control_version }}
  • -
  • Target version: {{ target_version }}
  • -
-
-
-
-

Connections used for testing

- {% for connection_objects in all_connection_objects %} -
-

Details for {{ connection_objects['hashed_connection_id'] }}

-
-

Source configuration

-

The configuration object taken from the given connection that was passed to each version of the connector during the test.

-
{{ connection_objects['source_config'] }}
-
- {% endfor %} -
-
- {% if not fully_generated %} -

Requested URLs

- {% else%} -

Requested URLs

- {% endif %} -
- {% for command, flows in requested_urls_per_command.items() %} -

{{ command.value.upper() }}

- {% if flows %} -
- - - - - - - - - - {% for index, control_url, target_url in flows %} - - - - - - {% endfor %} - -
Control URLTarget URL
{{ index }}{{ control_url }}{{ target_url }}
-
- {% else %} -

No URLs requested

- {% endif %} - {% endfor%} -
-
-
- - diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/templates/report.html.j2 b/airbyte-ci/connectors/live-tests/src/live_tests/templates/report.html.j2 deleted file mode 100644 index 4ec1519a305a..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/templates/report.html.j2 +++ /dev/null @@ -1,515 +0,0 @@ - - - - - - Test Report - - - - - - - -
-

Regression test report

-
-

Context

-
-
    -
  • Tester: {{ user }}
  • -
  • Test date: {{ test_date }}
  • -
  • Connector image: {{ connector_image }}
  • -
  • Control version: {{ control_version }}
  • -
  • Target version: {{ target_version }}
  • -
  • Private details
  • -
-
-
-
-

Coverage metadata

-
-

Stream coverage

- - - - {% for metric_name, metric_value in stream_coverage_metrics.items() %} - - - {% endfor %} - - -
{{ metric_name}}{{ metric_value }}
-

Sync mode coverage

- - - - {% for sync_mode, count in sync_mode_coverage.items() %} - - - {% endfor %} - - -
{{ sync_mode.value }}{{ count }}
- -

Selected stream

- - - - - - - - - {% for stream_name in selected_streams %} - - - - {% if selected_streams[stream_name]['has_data'] %} - - {% else %} - - {% endif %} - - {% endfor %} - -
StreamSync modeHas data
{{ stream_name }}{{ selected_streams[stream_name]['sync_mode'].value }}{{ selected_streams[stream_name]['has_data'] }}{{ selected_streams[stream_name]['has_data'] }}
- {% if untested_streams %} -

Untested streams (not in configured catalog or without data)

-
    - {% for stream_name in untested_streams %} -
  • {{ stream_name }}
  • - {% endfor %} -
- {% endif %} -
-
- {% for connection_objects in all_connection_objects %} - -
-

Connection objects - Connection {{ connection_objects.hashed_connection_id }}

- -
- {% endfor %} - -
- {% if not fully_generated %} -

Command execution metrics

- {% else%} -

Command execution metrics

- {% endif %} -
- {% if message_count_per_type[0] %} -

Message types

- - - - - {% for command in message_count_per_type[0] %} - - {% endfor %} - - - - {% for command in message_count_per_type[0] %} - - - - {% endfor %} - - {% for message_type in message_count_per_type[1] %} - - - {% for command in message_count_per_type[1][message_type] %} - - - {% if message_count_per_type[1][message_type][command]["difference"] != 0 %} - - {% else %} - - {% endif %} - {% endfor %} - - {% endfor %} -
{{ command.value.upper() }}
controltargetΔ
{{ message_type.value }}{{ message_count_per_type[1][message_type][command]["control"] }}{{ message_count_per_type[1][message_type][command]["target"] }}{{ message_count_per_type[1][message_type][command]["difference"] }}{{ message_count_per_type[1][message_type][command]["difference"] }}
- {% endif %} - {% if record_count_per_command_and_stream %} -

Record count per stream

- {% for command, record_count_per_stream in record_count_per_command_and_stream.items() %} -

{{ command.value.upper() }}

- - - - - - - - - - - {% for stream, record_count in record_count_per_stream.items() %} - - - - - {% if record_count.get("difference", 0) != 0 %} - - {% else %} - - {% endif %} - - {% endfor %} - -
streamcontrol record counttarget record countΔ
{{ stream }}{{ record_count.get("control", 0) }}{{ record_count.get("target", 0) }}{{ record_count.get("difference", 0) }}{{ record_count.get("difference", 0) }}
- {% endfor %} - {% endif %} - {% if http_metrics_per_command %} -

HTTP traffic

- - - - - - - - - - - - - - - - - - - {% for command in http_metrics_per_command %} - - - - - - - - {% if http_metrics_per_command[command].get("difference", 0) != 0 %} - - {% else %} - - {% endif %} - - {% endfor %} - -
controltargetΔ
commandrequest countduplicate request countrequest countduplicate request countcache hit ratiorequest count
{{ command.value.upper() }}{{ http_metrics_per_command[command].get("control", {}).get("flow_count", "0")}}{{ http_metrics_per_command[command].get("control", {}).get("duplicate_flow_count", "0")}}{{ http_metrics_per_command[command].get("target", {}).get("flow_count", "0")}}{{ http_metrics_per_command[command].get("target", {}).get("duplicate_flow_count", "0")}}{{ http_metrics_per_command[command].get("target", {}).get("cache_hit_ratio", "0%")}}{{ http_metrics_per_command[command].get("difference", 0)}}{{ http_metrics_per_command[command].get("difference", 0)}}
- {% endif %} -
-
- -
- {% if not fully_generated %} -

Test results

- {% else%} -

Test results

- {% endif %} -
- {% for test in test_results %} -
- {% if test["result"] == "passed" %} - {% if test["output"] %} -

{{ test["name"] }} [{{ test["result"] + " with errors" }}]

- {% else %} -

{{ test["name"] }} [{{ test["result"] }}]

- {% endif %} - {% elif test["result"] == "failed" %} -

{{ test["name"] }} [{{ test["result"] }}]

- {% else %} -

{{ test["name"] }} [{{ test["result"] }}]

- {% endif %} - {% if test["documentation"] %} -

{{ test["documentation"] }}

- {% endif %} - {% if test["output"] %} -
-                    {{ test["output"] }}
-                    
- {% endif %} - {% if test["properties"]%} - {% for property_name, property_value in test["properties"] %} - {% if property_value %} -

{{ property_name }}

-
-                        {{ property_value }}
-                        
- {% else%} - - {% endif %} - {% endfor%} - {% endif %} -
- {% endfor%} -
-
-
- - diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/utils.py b/airbyte-ci/connectors/live-tests/src/live_tests/utils.py deleted file mode 100644 index 4deafdbd8b97..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/utils.py +++ /dev/null @@ -1,162 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -from __future__ import annotations - -import json -import logging -from collections.abc import Callable, Iterable -from pathlib import Path -from typing import TYPE_CHECKING, Optional, Union - -import pytest -from airbyte_protocol.models import AirbyteCatalog, AirbyteMessage, ConnectorSpecification, Status, Type # type: ignore -from deepdiff import DeepDiff # type: ignore - -from live_tests import stash_keys -from live_tests.commons.models import ExecutionResult -from live_tests.consts import MAX_LINES_IN_REPORT - -if TYPE_CHECKING: - from _pytest.fixtures import SubRequest - -MAX_DIFF_SIZE_FOR_LOGGING = 500 - - -def get_test_logger(request: SubRequest) -> logging.Logger: - return logging.getLogger(request.node.name) - - -def filter_records(messages: Iterable[AirbyteMessage]) -> Iterable[AirbyteMessage]: - for message in messages: - if message.type is Type.RECORD: - yield message - - -def write_string_to_test_artifact(request: SubRequest, content: str, filename: str, subdir: Optional[Path] = None) -> Path: - # StashKey (in this case TEST_ARTIFACT_DIRECTORY) defines the output class of this, - # so this is already a Path. - test_artifact_directory = request.config.stash[stash_keys.TEST_ARTIFACT_DIRECTORY] - if subdir: - test_artifact_directory = test_artifact_directory / subdir - test_artifact_directory.mkdir(parents=True, exist_ok=True) - artifact_path = test_artifact_directory / filename - artifact_path.write_text(content) - return artifact_path - - -def get_and_write_diff( - request: SubRequest, - control_data: Union[list, dict], - target_data: Union[list, dict], - filepath: str, - ignore_order: bool, - exclude_paths: Optional[list[str]], -) -> str: - logger = get_test_logger(request) - diff = DeepDiff( - control_data, - target_data, - ignore_order=ignore_order, - report_repetition=True, - exclude_regex_paths=exclude_paths, - ) - if diff: - diff_json = diff.to_json() - parsed_diff = json.loads(diff_json) - formatted_diff_json = json.dumps(parsed_diff, indent=2) - - diff_path_tree = write_string_to_test_artifact(request, str(diff.tree), f"{filepath}_tree.txt", subdir=request.node.name) - diff_path_text = write_string_to_test_artifact( - request, - formatted_diff_json, - f"{filepath}_text.txt", - subdir=Path(request.node.name), - ) - diff_path_pretty = write_string_to_test_artifact( - request, - str(diff.pretty()), - f"{filepath}_pretty.txt", - subdir=Path(request.node.name), - ) - - logger.info(f"Diff file are stored in {diff_path_tree}, {diff_path_text}, and {diff_path_pretty}.") - if len(diff_json.encode("utf-8")) < MAX_DIFF_SIZE_FOR_LOGGING: - logger.error(formatted_diff_json) - - return formatted_diff_json - return "" - - -def fail_test_on_failing_execution_results(record_property: Callable, execution_results: list[ExecutionResult]) -> None: - error_messages = [] - for execution_result in execution_results: - if not execution_result.success: - property_suffix = f"of failing execution {execution_result.command.value} on {execution_result.connector_under_test.name}:{execution_result.connector_under_test.version} [{MAX_LINES_IN_REPORT} last lines]" - record_property( - f"Stdout {property_suffix}", - tail_file(execution_result.stdout_file_path, n=MAX_LINES_IN_REPORT), - ) - record_property( - f"Stderr of {property_suffix}", - tail_file(execution_result.stderr_file_path, n=MAX_LINES_IN_REPORT), - ) - error_messages.append( - f"Failed executing command {execution_result.command} on {execution_result.connector_under_test.name}:{execution_result.connector_under_test.version}" - ) - if error_messages: - pytest.fail("\n".join(error_messages)) - - -def tail_file(file_path: Path, n: int = MAX_LINES_IN_REPORT) -> list[str]: - with open(file_path) as f: - # Move the cursor to the end of the file - f.seek(0, 2) - file_size = f.tell() - lines: list[str] = [] - read_size = min(4096, file_size) - cursor = file_size - read_size - - # Read chunks of the file until we've found n lines - while len(lines) < n and cursor >= 0: - f.seek(cursor) - chunk = f.read(read_size) - lines.extend(chunk.splitlines(True)[-n:]) - cursor -= read_size - - # Return the last n lines - return lines[-n:] - - -def is_successful_check(execution_result: ExecutionResult) -> bool: - for message in execution_result.airbyte_messages: - if message.type is Type.CONNECTION_STATUS and message.connectionStatus and message.connectionStatus.status is Status.SUCCEEDED: - return True - return False - - -def get_catalog(execution_result: ExecutionResult) -> AirbyteCatalog: - catalog = [m.catalog for m in execution_result.airbyte_messages if m.type is Type.CATALOG and m.catalog] - try: - return catalog[0] - except ValueError: - raise ValueError(f"Expected exactly one catalog in the execution result, but got {len(catalog)}.") - - -def get_spec(execution_result: ExecutionResult) -> ConnectorSpecification: - spec = [m.spec for m in execution_result.airbyte_messages if m.type is Type.SPEC] - try: - return spec[0] - except ValueError: - raise ValueError(f"Expected exactly one spec in the execution result, but got {len(spec)}.") - - -def find_all_values_for_key_in_schema(schema: dict, searched_key: str): - """Retrieve all (nested) values in a schema for a specific searched key""" - if isinstance(schema, list): - for schema_item in schema: - yield from find_all_values_for_key_in_schema(schema_item, searched_key) - if isinstance(schema, dict): - for key, value in schema.items(): - if key == searched_key: - yield value - if isinstance(value, dict) or isinstance(value, list): - yield from find_all_values_for_key_in_schema(value, searched_key) diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/__init__.py b/airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_check.py b/airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_check.py deleted file mode 100644 index ac945b830ffb..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_check.py +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -from typing import Callable - -import pytest -from airbyte_protocol.models import Type - -from live_tests.commons.models import ExecutionResult -from live_tests.consts import MAX_LINES_IN_REPORT -from live_tests.utils import fail_test_on_failing_execution_results, is_successful_check, tail_file - -pytestmark = [ - pytest.mark.anyio, -] - - -@pytest.mark.allow_diagnostic_mode -async def test_check_succeeds( - record_property: Callable, - check_target_execution_result: ExecutionResult, -) -> None: - """ - Verify that the check command succeeds on the target connection. - - Success is determined by the presence of a connection status message with a status of SUCCEEDED. - """ - fail_test_on_failing_execution_results( - record_property, - [check_target_execution_result], - ) - assert len([msg for msg in check_target_execution_result.airbyte_messages if msg.type == Type.CONNECTION_STATUS]) == 1 - - successful_target_check: bool = is_successful_check(check_target_execution_result) - error_messages = [] - if not successful_target_check: - record_property( - f"Target CHECK standard output [Last {MAX_LINES_IN_REPORT} lines]", - tail_file(check_target_execution_result.stdout_file_path, n=MAX_LINES_IN_REPORT), - ) - error_messages.append("The target check did not succeed. Check the test artifacts for more information.") - if error_messages: - pytest.fail("\n".join(error_messages)) diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_discover.py b/airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_discover.py deleted file mode 100644 index 0ac95f3fc82e..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_discover.py +++ /dev/null @@ -1,172 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -from typing import Callable, List, Union - -import dpath.util -import jsonschema -import pytest -from airbyte_protocol.models import AirbyteCatalog - -from live_tests.commons.models import ExecutionResult -from live_tests.utils import fail_test_on_failing_execution_results, find_all_values_for_key_in_schema, get_catalog - -pytestmark = [ - pytest.mark.anyio, -] - - -@pytest.fixture(scope="session") -def target_discovered_catalog(discover_target_execution_result: ExecutionResult) -> AirbyteCatalog: - return get_catalog(discover_target_execution_result) - - -@pytest.mark.allow_diagnostic_mode -async def test_discover( - record_property: Callable, - discover_target_execution_result: ExecutionResult, - target_discovered_catalog: AirbyteCatalog, -): - """ - Verify that the discover command succeeds on the target connection. - - Success is determined by the presence of a catalog with one or more streams, all with unique names. - """ - fail_test_on_failing_execution_results( - record_property, - [discover_target_execution_result], - ) - duplicated_stream_names = _duplicated_stream_names(target_discovered_catalog.streams) - - assert target_discovered_catalog is not None, "Message should have catalog" - assert hasattr(target_discovered_catalog, "streams") and target_discovered_catalog.streams, "Catalog should contain streams" - assert len(duplicated_stream_names) == 0, f"Catalog should have uniquely named streams, duplicates are: {duplicated_stream_names}" - - -def _duplicated_stream_names(streams) -> List[str]: - """Counts number of times a stream appears in the catalog""" - name_counts = dict() - for stream in streams: - count = name_counts.get(stream.name, 0) - name_counts[stream.name] = count + 1 - return [k for k, v in name_counts.items() if v > 1] - - -@pytest.mark.allow_diagnostic_mode -async def test_streams_have_valid_json_schemas(target_discovered_catalog: AirbyteCatalog): - """Check if all stream schemas are valid json schemas.""" - for stream in target_discovered_catalog.streams: - jsonschema.Draft7Validator.check_schema(stream.json_schema) - - -@pytest.mark.allow_diagnostic_mode -async def test_defined_cursors_exist_in_schema(target_discovered_catalog: AirbyteCatalog): - """Check if all of the source defined cursor fields exist on stream's json schema.""" - for stream in target_discovered_catalog.streams: - if not stream.default_cursor_field: - continue - schema = stream.json_schema - assert "properties" in schema, f"Top level item should have an 'object' type for {stream.name} stream schema" - cursor_path = "/properties/".join(stream.default_cursor_field) - cursor_field_location = dpath.util.search(schema["properties"], cursor_path) - assert cursor_field_location, ( - f"Some of defined cursor fields {stream.default_cursor_field} are not specified in discover schema " - f"properties for {stream.name} stream" - ) - - -@pytest.mark.allow_diagnostic_mode -async def test_defined_refs_exist_in_schema(target_discovered_catalog: AirbyteCatalog): - """Check the presence of unresolved `$ref`s values within each json schema.""" - schemas_errors = [] - for stream in target_discovered_catalog.streams: - check_result = list(find_all_values_for_key_in_schema(stream.json_schema, "$ref")) - if check_result: - schemas_errors.append({stream.name: check_result}) - - assert not schemas_errors, f"Found unresolved `$refs` values for selected streams: {tuple(schemas_errors)}." - - -@pytest.mark.allow_diagnostic_mode -@pytest.mark.parametrize("keyword", ["allOf", "not"]) -async def test_defined_keyword_exist_in_schema(keyword, target_discovered_catalog: AirbyteCatalog): - """Check for the presence of not allowed keywords within each json schema""" - schemas_errors = [] - for stream in target_discovered_catalog.streams: - check_result = _find_keyword_schema(stream.json_schema, key=keyword) - if check_result: - schemas_errors.append(stream.name) - - assert not schemas_errors, f"Found not allowed `{keyword}` keyword for selected streams: {schemas_errors}." - - -def _find_keyword_schema(schema: Union[dict, list, str], key: str) -> bool: - """Find at least one keyword in a schema, skip object properties""" - - def _find_keyword(schema, key, _skip=False): - if isinstance(schema, list): - for v in schema: - _find_keyword(v, key) - elif isinstance(schema, dict): - for k, v in schema.items(): - if k == key and not _skip: - raise StopIteration - rec_skip = k == "properties" and schema.get("type") == "object" - _find_keyword(v, key, rec_skip) - - try: - _find_keyword(schema, key) - except StopIteration: - return True - return False - - -@pytest.mark.allow_diagnostic_mode -async def test_primary_keys_exist_in_schema(target_discovered_catalog: AirbyteCatalog): - """Check that all primary keys are present in catalog.""" - for stream in target_discovered_catalog.streams: - for pk in stream.source_defined_primary_key or []: - schema = stream.json_schema - pk_path = "/properties/".join(pk) - pk_field_location = dpath.util.search(schema["properties"], pk_path) - assert pk_field_location, f"One of the PKs ({pk}) is not specified in discover schema for {stream.name} stream" - - -@pytest.mark.allow_diagnostic_mode -async def test_streams_has_sync_modes(target_discovered_catalog: AirbyteCatalog): - """Check that the supported_sync_modes is a not empty field in streams of the catalog.""" - for stream in target_discovered_catalog.streams: - assert stream.supported_sync_modes is not None, f"The stream {stream.name} is missing supported_sync_modes field declaration." - assert len(stream.supported_sync_modes) > 0, f"supported_sync_modes list on stream {stream.name} should not be empty." - - -@pytest.mark.allow_diagnostic_mode -async def test_additional_properties_is_true(target_discovered_catalog: AirbyteCatalog): - """ - Check that value of the "additionalProperties" field is always true. - - A stream schema declaring "additionalProperties": false introduces the risk of accidental breaking changes. - Specifically, when removing a property from the stream schema, existing connector catalog will no longer be valid. - False value introduces the risk of accidental breaking changes. - - Read https://github.com/airbytehq/airbyte/issues/14196 for more details. - """ - for stream in target_discovered_catalog.streams: - additional_properties_values = list(find_all_values_for_key_in_schema(stream.json_schema, "additionalProperties")) - if additional_properties_values: - assert all( - [additional_properties_value is True for additional_properties_value in additional_properties_values] - ), "When set, additionalProperties field value must be true for backward compatibility." - - -@pytest.mark.allow_diagnostic_mode -@pytest.mark.skip("This a placeholder for a CAT which has too many failures. We need to fix the connectors at scale first.") -async def test_catalog_has_supported_data_types(target_discovered_catalog: AirbyteCatalog): - """ - Check that all streams have supported data types, format and airbyte_types. - - Supported data types are listed there: https://docs.airbyte.com/understanding-airbyte/supported-data-types/ - """ - pass diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_read.py b/airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_read.py deleted file mode 100644 index 76b6063b82d2..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_read.py +++ /dev/null @@ -1,143 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -from collections import defaultdict -from functools import reduce -from typing import TYPE_CHECKING, Any, Callable, List, Mapping, Tuple - -import pytest -from airbyte_protocol.models import ( - AirbyteStateMessage, - AirbyteStateStats, - AirbyteStateType, - AirbyteStreamStatus, - AirbyteStreamStatusTraceMessage, - ConfiguredAirbyteCatalog, -) - -from live_tests.commons.json_schema_helper import conforms_to_schema -from live_tests.commons.models import ExecutionResult -from live_tests.utils import fail_test_on_failing_execution_results, get_test_logger - -if TYPE_CHECKING: - from _pytest.fixtures import SubRequest - -pytestmark = [ - pytest.mark.anyio, -] - - -@pytest.mark.allow_diagnostic_mode -async def test_read( - request: "SubRequest", - record_property: Callable, - read_target_execution_result: ExecutionResult, -): - """ - Verify that the read command succeeds on the target connection. - - Also makes assertions about the validity of the read command output: - - At least one state message is emitted per stream - - Appropriate stream status messages are emitted for each stream - - If a primary key exists for the stream, it is present in the records emitted - """ - has_records = False - errors = [] - warnings = [] - fail_test_on_failing_execution_results( - record_property, - [read_target_execution_result], - ) - for stream in read_target_execution_result.configured_catalog.streams: - records = read_target_execution_result.get_records_per_stream(stream.stream.name) - state_messages = read_target_execution_result.get_states_per_stream(stream.stream.name) - statuses = read_target_execution_result.get_status_messages_per_stream(stream.stream.name) - primary_key = read_target_execution_result.primary_keys_per_stream.get(stream.stream.name) - - for record in records: - has_records = True - if not conforms_to_schema(read_target_execution_result.get_obfuscated_types(record.record.data), stream.schema()): - errors.append(f"A record was encountered that does not conform to the schema. stream={stream.stream.name} record={record}") - if primary_key: - if _extract_primary_key_value(record.dict(), primary_key) is None: - errors.append( - f"Primary key subkeys {repr(primary_key)} have null values or not present in {stream.stream.name} stream records." - ) - if stream.stream.name not in state_messages: - errors.append( - f"At least one state message should be emitted per stream, but no state messages were emitted for {stream.stream.name}." - ) - try: - _validate_state_messages( - state_messages=state_messages[stream.stream.name], configured_catalog=read_target_execution_result.configured_catalog - ) - except AssertionError as exc: - warnings.append( - f"Invalid state message for stream {stream.stream.name}. exc={exc} state_messages={state_messages[stream.stream.name]}" - ) - if stream.stream.name not in statuses: - warnings.append(f"No stream statuses were emitted for stream {stream.stream.name}.") - if not _validate_stream_statuses( - configured_catalog=read_target_execution_result.configured_catalog, statuses=statuses[stream.stream.name] - ): - errors.append(f"Invalid statuses for stream {stream.stream.name}. statuses={statuses[stream.stream.name]}") - if not has_records: - errors.append("At least one record should be read using provided catalog.") - - if errors: - logger = get_test_logger(request) - for error in errors: - logger.info(error) - - -def _extract_primary_key_value(record: Mapping[str, Any], primary_key: List[List[str]]) -> dict[Tuple[str], Any]: - pk_values = {} - for pk_path in primary_key: - pk_value: Any = reduce(lambda data, key: data.get(key) if isinstance(data, dict) else None, pk_path, record) - pk_values[tuple(pk_path)] = pk_value - return pk_values - - -def _validate_stream_statuses(configured_catalog: ConfiguredAirbyteCatalog, statuses: List[AirbyteStreamStatusTraceMessage]): - """Validate all statuses for all streams in the catalogs were emitted in correct order: - 1. STARTED - 2. RUNNING (can be >1) - 3. COMPLETE - """ - stream_statuses = defaultdict(list) - for status in statuses: - stream_statuses[f"{status.stream_descriptor.namespace}-{status.stream_descriptor.name}"].append(status.status) - - assert set(f"{x.stream.namespace}-{x.stream.name}" for x in configured_catalog.streams) == set( - stream_statuses - ), "All stream must emit status" - - for stream_name, status_list in stream_statuses.items(): - assert ( - len(status_list) >= 3 - ), f"Stream `{stream_name}` statuses should be emitted in the next order: `STARTED`, `RUNNING`,... `COMPLETE`" - assert status_list[0] == AirbyteStreamStatus.STARTED - assert status_list[-1] == AirbyteStreamStatus.COMPLETE - assert all(x == AirbyteStreamStatus.RUNNING for x in status_list[1:-1]) - - -def _validate_state_messages(state_messages: List[AirbyteStateMessage], configured_catalog: ConfiguredAirbyteCatalog): - # Ensure that at least one state message is emitted for each stream - assert len(state_messages) >= len( - configured_catalog.streams - ), "At least one state message should be emitted for each configured stream." - - for state_message in state_messages: - stream_name = state_message.stream.stream_descriptor.name - state_type = state_message.type - - # Ensure legacy state type is not emitted anymore - assert state_type != AirbyteStateType.LEGACY, ( - f"Ensure that statuses from the {stream_name} stream are emitted using either " - "`STREAM` or `GLOBAL` state types, as the `LEGACY` state type is now deprecated." - ) - - # Check if stats are of the correct type and present in state message - assert isinstance(state_message.sourceStats, AirbyteStateStats), "Source stats should be in state message." diff --git a/airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_spec.py b/airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_spec.py deleted file mode 100644 index f5d3c2238d41..000000000000 --- a/airbyte-ci/connectors/live-tests/src/live_tests/validation_tests/test_spec.py +++ /dev/null @@ -1,514 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Set, Tuple - -import dpath.util -import jsonschema -import pytest -from airbyte_protocol.models import ConnectorSpecification - -from live_tests.commons.json_schema_helper import JsonSchemaHelper, get_expected_schema_structure, get_paths_in_connector_config -from live_tests.commons.models import ExecutionResult -from live_tests.utils import fail_test_on_failing_execution_results, find_all_values_for_key_in_schema, get_spec, get_test_logger - -pytestmark = [ - pytest.mark.anyio, -] - -if TYPE_CHECKING: - from _pytest.fixtures import SubRequest - - -@pytest.fixture(name="secret_property_names") -def secret_property_names_fixture(): - return ( - "client_token", - "access_token", - "api_token", - "token", - "secret", - "client_secret", - "password", - "key", - "service_account_info", - "service_account", - "tenant_id", - "certificate", - "jwt", - "credentials", - "app_id", - "appid", - "refresh_token", - ) - - -DATE_PATTERN = "^[0-9]{2}-[0-9]{2}-[0-9]{4}$" -DATETIME_PATTERN = "^[0-9]{4}-[0-9]{2}-[0-9]{2}(T[0-9]{2}:[0-9]{2}:[0-9]{2})?$" - - -@pytest.fixture -def target_spec(spec_target_execution_result: ExecutionResult) -> ConnectorSpecification: - return get_spec(spec_target_execution_result) - - -@pytest.fixture -def connector_config(spec_target_execution_result: ExecutionResult) -> Dict[str, any]: - return spec_target_execution_result.config - - -async def test_spec( - record_property: Callable, - spec_target_execution_result: ExecutionResult, -): - """Check that the spec call succeeds""" - fail_test_on_failing_execution_results(record_property, [spec_target_execution_result]) - - -@pytest.mark.allow_diagnostic_mode -async def test_config_match_spec( - target_spec: ConnectorSpecification, - connector_config: Dict[str, any], -): - """Check that config matches the actual schema from the spec call""" - # Getting rid of technical variables that start with an underscore - config = {key: value for key, value in connector_config.data.items() if not key.startswith("_")} - try: - jsonschema.validate(instance=config, schema=target_spec.connectionSpecification) - except jsonschema.exceptions.ValidationError as err: - pytest.fail(f"Config invalid: {err}") - except jsonschema.exceptions.SchemaError as err: - pytest.fail(f"Spec is invalid: {err}") - - -async def test_enum_usage(target_spec: ConnectorSpecification): - """Check that enum lists in specs contain distinct values.""" - docs_url = "https://docs.airbyte.io/connector-development/connector-specification-reference" - docs_msg = f"See specification reference at {docs_url}." - - schema_helper = JsonSchemaHelper(target_spec.connectionSpecification) - enum_paths = schema_helper.find_nodes(keys=["enum"]) - - for path in enum_paths: - enum_list = schema_helper.get_node(path) - assert len(set(enum_list)) == len( - enum_list - ), f"Enum lists should not contain duplicate values. Misconfigured enum array: {enum_list}. {docs_msg}" - - -async def test_oneof_usage(target_spec: ConnectorSpecification): - """Check that if spec contains oneOf it follows the rules according to reference - https://docs.airbyte.io/connector-development/connector-specification-reference - """ - docs_url = "https://docs.airbyte.io/connector-development/connector-specification-reference" - docs_msg = f"See specification reference at {docs_url}." - - schema_helper = JsonSchemaHelper(target_spec.connectionSpecification) - variant_paths = schema_helper.find_nodes(keys=["oneOf", "anyOf"]) - - for variant_path in variant_paths: - top_level_obj = schema_helper.get_node(variant_path[:-1]) - assert ( - top_level_obj.get("type") == "object" - ), f"The top-level definition in a `oneOf` block should have type: object. misconfigured object: {top_level_obj}. {docs_msg}" - - variants = schema_helper.get_node(variant_path) - for variant in variants: - assert "properties" in variant, f"Each item in the oneOf array should be a property with type object. {docs_msg}" - - oneof_path = ".".join(map(str, variant_path)) - variant_props = [set(v["properties"].keys()) for v in variants] - common_props = set.intersection(*variant_props) - assert common_props, f"There should be at least one common property for {oneof_path} subobjects. {docs_msg}" - - const_common_props = set() - enum_common_props = set() - for common_prop in common_props: - if all(["const" in variant["properties"][common_prop] for variant in variants]): - const_common_props.add(common_prop) - if all(["enum" in variant["properties"][common_prop] for variant in variants]): - enum_common_props.add(common_prop) - assert len(const_common_props) == 1 or ( - len(const_common_props) == 0 and len(enum_common_props) == 1 - ), f"There should be exactly one common property with 'const' keyword (or equivalent) for {oneof_path} subobjects. {docs_msg}" - - const_common_prop = const_common_props.pop() if const_common_props else enum_common_props.pop() - for n, variant in enumerate(variants): - prop_obj = variant["properties"][const_common_prop] - prop_info = f"common property {oneof_path}[{n}].{const_common_prop}. It's recommended to just use `const`." - if "const" in prop_obj: - const_value = prop_obj["const"] - assert ( - "default" not in prop_obj or prop_obj["default"] == const_value - ), f"'default' needs to be identical to 'const' in {prop_info}. {docs_msg}" - assert "enum" not in prop_obj or prop_obj["enum"] == [ - const_value - ], f"'enum' needs to be an array with a single item identical to 'const' in {prop_info}. {docs_msg}" - else: - assert ( - "enum" in prop_obj and "default" in prop_obj and prop_obj["enum"] == [prop_obj["default"]] - ), f"'enum' needs to be an array with a single item identical to 'default' in {prop_info}. {docs_msg}" - - -def _is_spec_property_name_secret(path: str, secret_property_names) -> Tuple[Optional[str], bool]: - """ - Given a path to a type field, extract a field name and decide whether it is a name of secret or not - based on a provided list of secret names. - Split the path by `/`, drop the last item and make list reversed. - Then iterate over it and find the first item that's not a reserved keyword or an index. - Example: - properties/credentials/oneOf/1/properties/api_key/type -> [api_key, properties, 1, oneOf, credentials, properties] -> api_key - """ - reserved_keywords = ("anyOf", "oneOf", "allOf", "not", "properties", "items", "type", "prefixItems") - for part in reversed(path.split("/")[:-1]): - if part.isdigit() or part in reserved_keywords: - continue - return part, part.lower() in secret_property_names - return None, False - - -def _property_can_store_secret(prop: dict) -> bool: - """ - Some fields can not hold a secret by design, others can. - Null type as well as boolean can not hold a secret value. - A string, a number or an integer type can always store secrets. - Secret objects and arrays can not be rendered correctly in the UI: - A field with a constant value can not hold a secret as well. - """ - unsecure_types = {"string", "integer", "number"} - type_ = prop["type"] - is_property_constant_value = bool(prop.get("const")) - can_store_secret = any( - [ - isinstance(type_, str) and type_ in unsecure_types, - isinstance(type_, list) and (set(type_) & unsecure_types), - ] - ) - if not can_store_secret: - return False - # if a property can store a secret, additional check should be done if it's a constant value - return not is_property_constant_value - - -async def test_secret_is_properly_marked(target_spec: ConnectorSpecification, secret_property_names): - """ - Each field has a type, therefore we can make a flat list of fields from the returned specification. - Iterate over the list, check if a field name is a secret name, can potentially hold a secret value - and make sure it is marked as `airbyte_secret`. - """ - secrets_exposed = [] - non_secrets_hidden = [] - spec_properties = target_spec.connectionSpecification["properties"] - for type_path, type_value in dpath.util.search(spec_properties, "**/type", yielded=True): - _, is_property_name_secret = _is_spec_property_name_secret(type_path, secret_property_names) - if not is_property_name_secret: - continue - absolute_path = f"/{type_path}" - property_path, _ = absolute_path.rsplit(sep="/", maxsplit=1) - property_definition = dpath.util.get(spec_properties, property_path) - marked_as_secret = property_definition.get("airbyte_secret", False) - possibly_a_secret = _property_can_store_secret(property_definition) - if marked_as_secret and not possibly_a_secret: - non_secrets_hidden.append(property_path) - if not marked_as_secret and possibly_a_secret: - secrets_exposed.append(property_path) - - if non_secrets_hidden: - properties = "\n".join(non_secrets_hidden) - pytest.fail( - f"""Some properties are marked with `airbyte_secret` although they probably should not be. - Please double check them. If they're okay, please fix this test. - {properties}""" - ) - if secrets_exposed: - properties = "\n".join(secrets_exposed) - pytest.fail( - f"""The following properties should be marked with `airbyte_secret!` - {properties}""" - ) - - -def _fail_on_errors(errors: List[str]): - if len(errors) > 0: - pytest.fail("\n".join(errors)) - - -def test_property_type_is_not_array(target_spec: ConnectorSpecification): - """ - Each field has one or multiple types, but the UI only supports a single type and optionally "null" as a second type. - """ - errors = [] - for type_path, type_value in dpath.util.search(target_spec.connectionSpecification, "**/properties/*/type", yielded=True): - if isinstance(type_value, List): - number_of_types = len(type_value) - if number_of_types != 2 and number_of_types != 1: - errors.append( - f"{type_path} is not either a simple type or an array of a simple type plus null: {type_value} (for example: type: [string, null])" - ) - if number_of_types == 2 and type_value[1] != "null": - errors.append( - f"Second type of {type_path} is not null: {type_value}. Type can either be a simple type or an array of a simple type plus null (for example: type: [string, null])" - ) - _fail_on_errors(errors) - - -def test_object_not_empty(target_spec: ConnectorSpecification): - """ - Each object field needs to have at least one property as the UI won't be able to show them otherwise. - If the whole spec is empty, it's allowed to have a single empty object at the top level - """ - schema_helper = JsonSchemaHelper(target_spec.connectionSpecification) - errors = [] - for type_path, type_value in dpath.util.search(target_spec.connectionSpecification, "**/type", yielded=True): - if type_path == "type": - # allow empty root object - continue - if type_value == "object": - property = schema_helper.get_parent(type_path) - if "oneOf" not in property and ("properties" not in property or len(property["properties"]) == 0): - errors.append( - f"{type_path} is an empty object which will not be represented correctly in the UI. Either remove or add specific properties" - ) - _fail_on_errors(errors) - - -async def test_array_type(target_spec: ConnectorSpecification): - """ - Each array has one or multiple types for its items, but the UI only supports a single type which can either be object, string or an enum - """ - schema_helper = JsonSchemaHelper(target_spec.connectionSpecification) - errors = [] - for type_path, type_type in dpath.util.search(target_spec.connectionSpecification, "**/type", yielded=True): - property_definition = schema_helper.get_parent(type_path) - if type_type != "array": - # unrelated "items", not an array definition - continue - items_value = property_definition.get("items", None) - if items_value is None: - continue - elif isinstance(items_value, List): - errors.append(f"{type_path} is not just a single item type: {items_value}") - elif items_value.get("type") not in ["object", "string", "number", "integer"] and "enum" not in items_value: - errors.append(f"Items of {type_path} has to be either object or string or define an enum") - _fail_on_errors(errors) - - -async def test_forbidden_complex_types(target_spec: ConnectorSpecification): - """ - not, anyOf, patternProperties, prefixItems, allOf, if, then, else, dependentSchemas and dependentRequired are not allowed - """ - forbidden_keys = [ - "not", - "anyOf", - "patternProperties", - "prefixItems", - "allOf", - "if", - "then", - "else", - "dependentSchemas", - "dependentRequired", - ] - found_keys = set() - for forbidden_key in forbidden_keys: - for path, value in dpath.util.search(target_spec.connectionSpecification, f"**/{forbidden_key}", yielded=True): - found_keys.add(path) - - for forbidden_key in forbidden_keys: - # remove forbidden keys if they are used as properties directly - for path, _value in dpath.util.search(target_spec.connectionSpecification, f"**/properties/{forbidden_key}", yielded=True): - found_keys.remove(path) - - if len(found_keys) > 0: - key_list = ", ".join(found_keys) - pytest.fail(f"Found the following disallowed JSON schema features: {key_list}") - - -async def test_date_pattern(request: "SubRequest", target_spec: ConnectorSpecification): - """ - Properties with format date or date-time should always have a pattern defined how the date/date-time should be formatted - that corresponds with the format the datepicker component is creating. - """ - schema_helper = JsonSchemaHelper(target_spec.connectionSpecification) - for format_path, format in dpath.util.search(target_spec.connectionSpecification, "**/format", yielded=True): - if not isinstance(format, str): - # format is not a format definition here but a property named format - continue - property_definition = schema_helper.get_parent(format_path) - pattern = property_definition.get("pattern") - logger = get_test_logger(request) - if format == "date" and not pattern == DATE_PATTERN: - logger.warning( - f"{format_path} is defining a date format without the corresponding pattern. Consider setting the pattern to {DATE_PATTERN} to make it easier for users to edit this field in the UI." - ) - if format == "date-time" and not pattern == DATETIME_PATTERN: - logger.warning( - f"{format_path} is defining a date-time format without the corresponding pattern Consider setting the pattern to {DATETIME_PATTERN} to make it easier for users to edit this field in the UI." - ) - - -async def test_date_format(request: "SubRequest", target_spec: ConnectorSpecification): - """ - Properties with a pattern that looks like a date should have their format set to date or date-time. - """ - schema_helper = JsonSchemaHelper(target_spec.connectionSpecification) - for pattern_path, pattern in dpath.util.search(target_spec.connectionSpecification, "**/pattern", yielded=True): - if not isinstance(pattern, str): - # pattern is not a pattern definition here but a property named pattern - continue - if pattern == DATE_PATTERN or pattern == DATETIME_PATTERN: - property_definition = schema_helper.get_parent(pattern_path) - format = property_definition.get("format") - logger = get_test_logger(request) - if not format == "date" and pattern == DATE_PATTERN: - logger.warning( - f"{pattern_path} is defining a pattern that looks like a date without setting the format to `date`. Consider specifying the format to make it easier for users to edit this field in the UI." - ) - if not format == "date-time" and pattern == DATETIME_PATTERN: - logger.warning( - f"{pattern_path} is defining a pattern that looks like a date-time without setting the format to `date-time`. Consider specifying the format to make it easier for users to edit this field in the UI." - ) - - -async def test_duplicate_order(target_spec: ConnectorSpecification): - """ - Custom ordering of field (via the "order" property defined in the field) is not allowed to have duplicates within the same group. - `{ "a": { "order": 1 }, "b": { "order": 1 } }` is invalid because there are two fields with order 1 - `{ "a": { "order": 1 }, "b": { "order": 1, "group": "x" } }` is valid because the fields with the same order are in different groups - """ - schema_helper = JsonSchemaHelper(target_spec.connectionSpecification) - errors = [] - for properties_path, properties in dpath.util.search(target_spec.connectionSpecification, "**/properties", yielded=True): - definition = schema_helper.get_parent(properties_path) - if definition.get("type") != "object": - # unrelated "properties", not an actual object definition - continue - used_orders: Dict[str, Set[int]] = {} - for property in properties.values(): - if "order" not in property: - continue - order = property.get("order") - group = property.get("group", "") - if group not in used_orders: - used_orders[group] = set() - orders_for_group = used_orders[group] - if order in orders_for_group: - errors.append(f"{properties_path} has duplicate order: {order}") - orders_for_group.add(order) - _fail_on_errors(errors) - - -async def test_nested_group(target_spec: ConnectorSpecification): - """ - Groups can only be defined on the top level properties - `{ "a": { "group": "x" }}` is valid because field "a" is a top level field - `{ "a": { "oneOf": [{ "type": "object", "properties": { "b": { "group": "x" } } }] }}` is invalid because field "b" is nested in a oneOf - """ - errors = [] - schema_helper = JsonSchemaHelper(target_spec.connectionSpecification) - for result in dpath.util.search(target_spec.connectionSpecification, "/properties/**/group", yielded=True): - group_path = result[0] - parent_path = schema_helper.get_parent_path(group_path) - is_property_named_group = parent_path.endswith("properties") - grandparent_path = schema_helper.get_parent_path(parent_path) - if grandparent_path != "/properties" and not is_property_named_group: - errors.append(f"Groups can only be defined on top level, is defined at {group_path}") - _fail_on_errors(errors) - - -async def test_display_type(target_spec: ConnectorSpecification): - """ - The display_type property can only be set on fields which have a oneOf property, and must be either "dropdown" or "radio" - """ - errors = [] - schema_helper = JsonSchemaHelper(target_spec.connectionSpecification) - for result in dpath.util.search(target_spec.connectionSpecification, "/properties/**/display_type", yielded=True): - display_type_path = result[0] - parent_path = schema_helper.get_parent_path(display_type_path) - is_property_named_display_type = parent_path.endswith("properties") - if is_property_named_display_type: - continue - parent_object = schema_helper.get_parent(display_type_path) - if "oneOf" not in parent_object: - errors.append(f"display_type is only allowed on fields which have a oneOf property, but is set on {parent_path}") - display_type_value = parent_object.get("display_type") - if display_type_value != "dropdown" and display_type_value != "radio": - errors.append(f"display_type must be either 'dropdown' or 'radio', but is set to '{display_type_value}' at {display_type_path}") - _fail_on_errors(errors) - - -async def test_defined_refs_exist_in_json_spec_file(target_spec: ConnectorSpecification): - """Checking for the presence of unresolved `$ref`s values within each json spec file""" - check_result = list(find_all_values_for_key_in_schema(target_spec.connectionSpecification["properties"], "$ref")) - assert not check_result, "Found unresolved `$refs` value in spec.json file" - - -async def test_oauth_flow_parameters(target_spec: ConnectorSpecification): - """Check if connector has correct oauth flow parameters according to - https://docs.airbyte.io/connector-development/connector-specification-reference - """ - advanced_auth = target_spec.advanced_auth - if not advanced_auth: - return - spec_schema = target_spec.connectionSpecification - paths_to_validate = set() - if advanced_auth.predicate_key: - paths_to_validate.add("/" + "/".join(advanced_auth.predicate_key)) - oauth_config_specification = advanced_auth.oauth_config_specification - if oauth_config_specification: - if oauth_config_specification.oauth_user_input_from_connector_config_specification: - paths_to_validate.update( - get_paths_in_connector_config(oauth_config_specification.oauth_user_input_from_connector_config_specification["properties"]) - ) - if oauth_config_specification.complete_oauth_output_specification: - paths_to_validate.update( - get_paths_in_connector_config(oauth_config_specification.complete_oauth_output_specification["properties"]) - ) - if oauth_config_specification.complete_oauth_server_output_specification: - paths_to_validate.update( - get_paths_in_connector_config(oauth_config_specification.complete_oauth_server_output_specification["properties"]) - ) - - diff = paths_to_validate - set(get_expected_schema_structure(spec_schema)) - assert diff == set(), f"Specified oauth fields are missed from spec schema: {diff}" - - -async def test_oauth_is_default_method(target_spec: ConnectorSpecification): - """ - OAuth is default check. - If credentials do have oneOf: we check that the OAuth is listed at first. - If there is no oneOf and Oauth: OAuth is only option to authenticate the source and no check is needed. - """ - advanced_auth = target_spec.advanced_auth - if not advanced_auth: - pytest.skip("Source does not have OAuth method.") - if not advanced_auth.predicate_key: - pytest.skip("Advanced Auth object does not have predicate_key, only one option to authenticate.") - - spec_schema = target_spec.connectionSpecification - credentials = advanced_auth.predicate_key[0] - try: - one_of_default_method = dpath.util.get(spec_schema, f"/**/{credentials}/oneOf/0") - except KeyError: # Key Error when oneOf is not in credentials object - pytest.skip("Credentials object does not have oneOf option.") - - path_in_credentials = "/".join(advanced_auth.predicate_key[1:]) - auth_method_predicate_const = dpath.util.get(one_of_default_method, f"/**/{path_in_credentials}/const") - assert ( - auth_method_predicate_const == advanced_auth.predicate_value - ), f"Oauth method should be a default option. Current default method is {auth_method_predicate_const}." - - -async def test_additional_properties_is_true(target_spec: ConnectorSpecification): - """Check that value of the "additionalProperties" field is always true. - A spec declaring "additionalProperties": false introduces the risk of accidental breaking changes. - Specifically, when removing a property from the spec, existing connector configs will no longer be valid. - False value introduces the risk of accidental breaking changes. - Read https://github.com/airbytehq/airbyte/issues/14196 for more details""" - additional_properties_values = find_all_values_for_key_in_schema(target_spec.connectionSpecification, "additionalProperties") - if additional_properties_values: - assert all( - [additional_properties_value is True for additional_properties_value in additional_properties_values] - ), "When set, additionalProperties field value must be true for backward compatibility." diff --git a/airbyte-ci/connectors/live-tests/tests/__init__.py b/airbyte-ci/connectors/live-tests/tests/__init__.py deleted file mode 100644 index f70ecfc3a89e..000000000000 --- a/airbyte-ci/connectors/live-tests/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. diff --git a/airbyte-ci/connectors/live-tests/tests/backends/__init__.py b/airbyte-ci/connectors/live-tests/tests/backends/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/airbyte-ci/connectors/live-tests/tests/backends/test_file_backend.py b/airbyte-ci/connectors/live-tests/tests/backends/test_file_backend.py deleted file mode 100644 index fbd8f03bc4f7..000000000000 --- a/airbyte-ci/connectors/live-tests/tests/backends/test_file_backend.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -from pathlib import Path - -import pytest -from airbyte_protocol.models import ( - AirbyteCatalog, - AirbyteConnectionStatus, - AirbyteMessage, - AirbyteRecordMessage, - AirbyteStateMessage, - ConnectorSpecification, - Status, -) -from airbyte_protocol.models import Type as AirbyteMessageType - -from live_tests.commons.backends import FileBackend - - -@pytest.mark.parametrize( - "messages, expected_writes", - [ - ( - [ - AirbyteMessage(type=AirbyteMessageType.CATALOG, catalog=AirbyteCatalog(streams=[])), - AirbyteMessage( - type=AirbyteMessageType.CONNECTION_STATUS, - connectionStatus=AirbyteConnectionStatus(status=Status.SUCCEEDED), - ), - AirbyteMessage( - type=AirbyteMessageType.RECORD, - record=AirbyteRecordMessage(stream="test_stream", data={}, emitted_at=123456789), - ), - AirbyteMessage( - type=AirbyteMessageType.SPEC, - spec=ConnectorSpecification(connectionSpecification={}), - ), - AirbyteMessage( - type=AirbyteMessageType.STATE, - state=AirbyteStateMessage(data={"test": "value"}), - ), - ], - [ - ("catalog.jsonl", '{"streams": []}\n'), - ( - "connection_status.jsonl", - '{"status": "SUCCEEDED", "message": null}\n', - ), - ( - "records.jsonl", - '{"namespace": null, "stream": "test_stream", "data": {}, "meta": null}\n', - ), - ( - "spec.jsonl", - '{"documentationUrl": null, "changelogUrl": null, "connectionSpecification": {}, "supportsIncremental": null, "supportsNormalization": false, "supportsDBT": false, "supported_destination_sync_modes": null, "advanced_auth": null, "protocol_version": null}\n', - ), - ( - "states.jsonl", - '{"type": null, "stream": null, "global_": null, "data": {"test": "value"}, "sourceStats": null, "destinationStats": null}\n', - ), - ], - ), - ], -) -def test_write(tmp_path, messages, expected_writes): - backend = FileBackend(tmp_path) - backend.write(messages) - for expected_file, expected_content in expected_writes: - expected_path = Path(tmp_path / expected_file) - assert expected_path.exists() - content = expected_path.read_text() diff --git a/airbyte-ci/connectors/live-tests/tests/test_get_connection_objects_retrieval.py b/airbyte-ci/connectors/live-tests/tests/test_get_connection_objects_retrieval.py deleted file mode 100644 index e38bba4fcc41..000000000000 --- a/airbyte-ci/connectors/live-tests/tests/test_get_connection_objects_retrieval.py +++ /dev/null @@ -1,702 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -import uuid -from unittest.mock import patch -from uuid import UUID - -from connection_retriever import ConnectionObject -from connection_retriever.retrieval import TestingCandidate -from connection_retriever.utils import ConnectionSubset - -from live_tests.commons.connection_objects_retrieval import _get_connection_objects_from_retrieved_objects - -mocking_return_of_retrieve_testing_candidates = [ - TestingCandidate( - connection_id="0b11bcb3-7726-4d1a-bcb4-d68fb579f7a8", - connection_url=f"https://cloud.airbyte.com/workspaces/{str(uuid.uuid4())}/connections/{str(uuid.uuid4())}", - catalog=None, - configured_catalog=None, - state=None, - workspace_id=None, - destination_docker_image=None, - source_docker_image=None, - last_attempt_duration_in_microseconds=44902474342, - streams_with_data=[ - "sponsored_products_report_stream", - "profiles", - "sponsored_display_report_stream", - "sponsored_brands_v3_report_stream", - ], - ), - TestingCandidate( - connection_id="8775fd75-e510-4f7f-98dc-0128ea997133", - connection_url=f"https://cloud.airbyte.com/workspaces/{str(uuid.uuid4())}/connections/{str(uuid.uuid4())}", - catalog=None, - configured_catalog=None, - state=None, - workspace_id=None, - destination_docker_image=None, - source_docker_image=None, - last_attempt_duration_in_microseconds=44902474342, - streams_with_data=[ - "sponsored_products_report_stream", - "sponsored_display_report_stream", - "profiles", - "sponsored_brands_v3_report_stream", - ], - ), -] - -mocking_return_of_retrieve_objects = [ - TestingCandidate( - connection_id="0b11bcb3-7726-4d1a-bcb4-d68fb579f7a8", - connection_url=f"https://cloud.airbyte.com/workspaces/{str(uuid.uuid4())}/connections/{str(uuid.uuid4())}", - catalog={ - "streams": [ - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "countryCode": {"type": [...]}, - }, - "title": "profiles", - "type": ["null", "object"], - }, - "name": "profiles", - "source_defined_primary_key": [["profileId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "state": {"type": [...]}, - }, - "title": "portfolios", - "type": ["null", "object"], - }, - "name": "portfolios", - "source_defined_primary_key": [["portfolioId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "tactic": {"type": [...]}, - }, - "title": "sponsored_display_campaigns", - "type": ["null", "object"], - }, - "name": "sponsored_display_campaigns", - "source_defined_primary_key": [["campaignId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "tactic": {"type": [...]}, - }, - "title": "sponsored_display_ad_groups", - "type": ["null", "object"], - }, - "name": "sponsored_display_ad_groups", - "source_defined_primary_key": [["adGroupId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "state": {"type": [...]}, - }, - "title": "sponsored_display_product_ads", - "type": ["null", "object"], - }, - "name": "sponsored_display_product_ads", - "source_defined_primary_key": [["adId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "targetId": {"type": [...]}, - }, - "title": "sponsored_display_targetings", - "type": ["null", "object"], - }, - "name": "sponsored_display_targetings", - "source_defined_primary_key": [["targetId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "properties": {"type": [...]}, - }, - "title": "sponsored_display_creatives", - "type": ["null", "object"], - }, - "name": "sponsored_display_creatives", - "source_defined_primary_key": [["creativeId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "createdDate": {"type": [...]}, - }, - "title": "sponsored_display_budget_rules", - "type": ["null", "object"], - }, - "name": "sponsored_display_budget_rules", - "source_defined_primary_key": [["ruleId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "adGroupId": {"type": [...]}, - }, - "title": "sponsored_brands_keywords", - "type": ["null", "object"], - }, - "name": "sponsored_brands_keywords", - "source_defined_primary_key": [["adGroupId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "bidding": {"type": [...]}, - }, - "title": "sponsored_brands_campaigns", - "type": ["null", "object"], - }, - "name": "sponsored_brands_campaigns", - "source_defined_primary_key": [["campaignId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "adGroupId": {"type": [...]}, - }, - "title": "sponsored_brands_ad_groups", - "type": ["null", "object"], - }, - "name": "sponsored_brands_ad_groups", - "source_defined_primary_key": [["adGroupId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "budget": {"type": [...]}, - }, - "title": "sponsored_product_campaigns", - "type": ["null", "object"], - }, - "name": "sponsored_product_campaigns", - "source_defined_primary_key": [["campaignId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "adGroupId": {"type": [...]}, - }, - "title": "sponsored_product_ad_groups", - "type": ["null", "object"], - }, - "name": "sponsored_product_ad_groups", - "source_defined_primary_key": [["adGroupId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "adGroupId": {"type": [...]}, - }, - "title": "sponsored_product_keywords", - "type": ["null", "object"], - }, - "name": "sponsored_product_keywords", - "source_defined_primary_key": [["keywordId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "adGroupId": {"type": [...]}, - }, - "title": "sponsored_product_negative_keywords", - "type": ["null", "object"], - }, - "name": "sponsored_product_negative_keywords", - "source_defined_primary_key": [["keywordId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "adGroupId": {"type": [...]}, - }, - "title": "sponsored_product_campaign_negative_keywords", - "type": ["null", "object"], - }, - "name": "sponsored_product_campaign_negative_keywords", - "source_defined_primary_key": [["keywordId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "adGroupId": {"type": [...]}, - }, - "title": "sponsored_product_ads", - "type": ["null", "object"], - }, - "name": "sponsored_product_ads", - "source_defined_primary_key": [["adId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "adGroupId": {"type": [...]}, - }, - "title": "sponsored_product_targetings", - "type": ["null", "object"], - }, - "name": "sponsored_product_targetings", - "source_defined_primary_key": [["targetId"]], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "adGroupId": {"type": [...]}, - "bidRecommendationsForTargetingExpressions": {"items": {...}, "type": "array"}, - "campaignId": {"type": [...]}, - "theme": {"type": [...]}, - }, - "title": "sponsored_product_ad_group_bid_recommendations", - "type": ["null", "object"], - }, - "name": "sponsored_product_ad_group_bid_recommendations", - "source_defined_primary_key": [], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": {"adGroupId": {"type": [...]}, "suggestedKeywords": {"items": {...}, "type": [...]}}, - "title": "sponsored_product_ad_group_suggested_keywords", - "type": ["null", "object"], - }, - "name": "sponsored_product_ad_group_suggested_keywords", - "source_defined_primary_key": [], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "adGroupId": {"type": [...]}, - }, - "title": "attribution_report_products", - "type": ["null", "object"], - }, - "name": "attribution_report_products", - "source_defined_primary_key": [], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "adGroupId": {"type": [...]}, - }, - "title": "attribution_report_performance_adgroup", - "type": ["null", "object"], - }, - "name": "attribution_report_performance_adgroup", - "source_defined_primary_key": [], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "adGroupId": {"type": [...]}, - }, - "title": "attribution_report_performance_campaign", - "type": ["null", "object"], - }, - "name": "attribution_report_performance_campaign", - "source_defined_primary_key": [], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "adGroupId": {"type": [...]}, - }, - "title": "attribution_report_performance_creative", - "type": ["null", "object"], - }, - "name": "attribution_report_performance_creative", - "source_defined_primary_key": [], - "supported_sync_modes": ["full_refresh"], - }, - { - "default_cursor_field": ["reportDate"], - "is_resumable": True, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "profileId": {"type": [...]}, - }, - "title": "sponsored_display_report_stream", - "type": ["null", "object"], - }, - "name": "sponsored_display_report_stream", - "source_defined_cursor": True, - "source_defined_primary_key": [["profileId"], ["recordType"], ["reportDate"], ["recordId"]], - "supported_sync_modes": ["full_refresh", "incremental"], - }, - { - "default_cursor_field": ["reportDate"], - "is_resumable": True, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "profileId": {"type": [...]}, - }, - "title": "sponsored_brands_v3_report_stream", - "type": ["null", "object"], - }, - "name": "sponsored_brands_v3_report_stream", - "source_defined_cursor": True, - "source_defined_primary_key": [["profileId"], ["recordType"], ["reportDate"], ["recordId"]], - "supported_sync_modes": ["full_refresh", "incremental"], - }, - { - "default_cursor_field": ["reportDate"], - "is_resumable": True, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "profileId": {"type": [...]}, - }, - "title": "sponsored_products_report_stream", - "type": ["null", "object"], - }, - "name": "sponsored_products_report_stream", - "source_defined_cursor": True, - "source_defined_primary_key": [["profileId"], ["recordType"], ["reportDate"], ["recordId"]], - "supported_sync_modes": ["full_refresh", "incremental"], - }, - ] - }, - configured_catalog={ - "streams": [ - { - "cursor_field": ["reportDate"], - "destination_sync_mode": "append_dedup", - "fields": [ - {"name": "metric", "type": "OBJECT"}, - {"name": "recordId", "type": "STRING"}, - {"name": "profileId", "type": "INTEGER"}, - {"name": "recordType", "type": "STRING"}, - {"name": "reportDate", "type": "STRING"}, - ], - "mappers": [], - "primary_key": [["profileId"], ["recordType"], ["reportDate"], ["recordId"]], - "stream": { - "default_cursor_field": ["reportDate"], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "metric": {...}, - "profileId": {...}, - "recordId": {...}, - "recordType": {...}, - "reportDate": {...}, - }, - "title": "sponsored_display_report_stream", - "type": ["null", "object"], - }, - "name": "sponsored_display_report_stream", - "source_defined_cursor": True, - "source_defined_primary_key": [["profileId"], ["recordType"], ["reportDate"], ["recordId"]], - "supported_sync_modes": ["full_refresh", "incremental"], - }, - "sync_mode": "incremental", - }, - { - "cursor_field": [], - "destination_sync_mode": "overwrite_dedup", - "fields": [ - {"name": "timezone", "type": "STRING"}, - {"name": "profileId", "type": "INTEGER"}, - {"name": "accountInfo", "type": "OBJECT"}, - {"name": "countryCode", "type": "STRING"}, - {"name": "dailyBudget", "type": "NUMBER"}, - {"name": "currencyCode", "type": "STRING"}, - ], - "mappers": [], - "primary_key": [["profileId"]], - "stream": { - "default_cursor_field": [], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "accountInfo": {...}, - "countryCode": {...}, - "currencyCode": {...}, - "dailyBudget": {...}, - "profileId": {...}, - "timezone": {...}, - }, - "title": "profiles", - "type": ["null", "object"], - }, - "name": "profiles", - "source_defined_cursor": False, - "source_defined_primary_key": [["profileId"]], - "supported_sync_modes": ["full_refresh"], - }, - "sync_mode": "full_refresh", - }, - { - "cursor_field": ["reportDate"], - "destination_sync_mode": "append_dedup", - "fields": [ - {"name": "metric", "type": "OBJECT"}, - {"name": "recordId", "type": "STRING"}, - {"name": "profileId", "type": "INTEGER"}, - {"name": "recordType", "type": "STRING"}, - {"name": "reportDate", "type": "STRING"}, - ], - "mappers": [], - "primary_key": [["profileId"], ["recordType"], ["reportDate"], ["recordId"]], - "stream": { - "default_cursor_field": ["reportDate"], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "metric": {...}, - "profileId": {...}, - "recordId": {...}, - "recordType": {...}, - "reportDate": {...}, - }, - "title": "sponsored_brands_v3_report_stream", - "type": ["null", "object"], - }, - "name": "sponsored_brands_v3_report_stream", - "source_defined_cursor": True, - "source_defined_primary_key": [["profileId"], ["recordType"], ["reportDate"], ["recordId"]], - "supported_sync_modes": ["full_refresh", "incremental"], - }, - "sync_mode": "incremental", - }, - { - "cursor_field": ["reportDate"], - "destination_sync_mode": "append_dedup", - "fields": [ - {"name": "metric", "type": "OBJECT"}, - {"name": "recordId", "type": "STRING"}, - {"name": "profileId", "type": "INTEGER"}, - {"name": "recordType", "type": "STRING"}, - {"name": "reportDate", "type": "STRING"}, - ], - "mappers": [], - "primary_key": [["profileId"], ["recordType"], ["reportDate"], ["recordId"]], - "stream": { - "default_cursor_field": ["reportDate"], - "is_resumable": False, - "json_schema": { - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "metric": {...}, - "profileId": {...}, - "recordId": {...}, - "recordType": {...}, - "reportDate": {...}, - }, - "title": "sponsored_products_report_stream", - "type": ["null", "object"], - }, - "name": "sponsored_products_report_stream", - "source_defined_cursor": True, - "source_defined_primary_key": [["profileId"], ["recordType"], ["reportDate"], ["recordId"]], - "supported_sync_modes": ["full_refresh", "incremental"], - }, - "sync_mode": "incremental", - }, - ] - }, - state=[ - { - "stream": { - "stream_descriptor": {"name": "profiles", "namespace": None}, - "stream_state": {"__ab_no_cursor_state_message": True}, - }, - "type": "STREAM", - }, - { - "stream": { - "stream_descriptor": {"name": "sponsored_brands_v3_report_stream", "namespace": None}, - "stream_state": { - "2575400145671382": {"reportDate": "2025-02-04"}, - }, - }, - "type": "STREAM", - }, - { - "stream": { - "stream_descriptor": {"name": "sponsored_products_report_stream", "namespace": None}, - "stream_state": { - "2575400145671382": {"reportDate": "2025-02-04"}, - }, - }, - "type": "STREAM", - }, - { - "stream": { - "stream_descriptor": {"name": "sponsored_display_report_stream", "namespace": None}, - "stream_state": { - "2575400145671382": {"reportDate": "2025-02-04"}, - }, - }, - "type": "STREAM", - }, - ], - workspace_id=UUID("90336fed-1595-492e-a938-eaf4b058fb25"), - destination_docker_image=None, - destination_id=UUID("97dfd7b1-8908-4f76-af4f-38351fb11fd3"), - source_config={"key": "value"}, - source_docker_image="airbyte/source-amazon-ads:6.2.7", - source_id=UUID("93ad83fd-796a-4b5c-bc63-54b0266d28dd"), - last_attempt_duration_in_microseconds=44902474342, - streams_with_data=[ - "sponsored_products_report_stream", - "profiles", - "sponsored_display_report_stream", - "sponsored_brands_v3_report_stream", - ], - ), -] - - -def test_get_connection_objects_from_retrieved_objects(): - with ( - patch( - "live_tests.commons.connection_objects_retrieval.retrieve_testing_candidates", - return_value=mocking_return_of_retrieve_testing_candidates, - ), - patch("live_tests.commons.connection_objects_retrieval.retrieve_objects", return_value=mocking_return_of_retrieve_objects), - ): - requested_objects = { - ConnectionObject.DESTINATION_ID, - ConnectionObject.SOURCE_ID, - ConnectionObject.CONFIGURED_CATALOG, - ConnectionObject.STATE, - ConnectionObject.CATALOG, - ConnectionObject.SOURCE_CONFIG, - ConnectionObject.WORKSPACE_ID, - ConnectionObject.SOURCE_DOCKER_IMAGE, - } - - retrieval_reason = "Running live tests on connection for connector airbyte/source-amazon-ads on target versions (dev)." - selected_streams = {"sponsored_brands_v3_report_stream"} - connection_objects = _get_connection_objects_from_retrieved_objects( - requested_objects=requested_objects, - retrieval_reason=retrieval_reason, - source_docker_repository="airbyte/source-amazon-ads", - source_docker_image_tag="6.2.7", - selected_streams=selected_streams, - connection_id=None, - custom_config=None, - custom_configured_catalog=None, - custom_state=None, - connection_subset=ConnectionSubset.ALL, - max_connections=None, - ) - # it is expected to get 1 connection only from _find_best_candidates_subset, because selected stream is presented in catalog and has data - assert len(connection_objects) == 1 - connection_objects_to_check = connection_objects[0] - assert len(connection_objects_to_check.configured_catalog.streams) == len( - selected_streams - ), f"Number of streams in catatalog should match number of selected streams: {len(selected_streams)}" - assert connection_objects_to_check.configured_catalog.streams[0].stream.name == "sponsored_brands_v3_report_stream" diff --git a/airbyte-ci/connectors/live-tests/tests/test_json_schema_helper.py b/airbyte-ci/connectors/live-tests/tests/test_json_schema_helper.py deleted file mode 100644 index 6b73fbfa3ceb..000000000000 --- a/airbyte-ci/connectors/live-tests/tests/test_json_schema_helper.py +++ /dev/null @@ -1,480 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from enum import Enum -from typing import Any, Iterable, List, Mapping, Text, Tuple, Union - -import pendulum -import pytest -from airbyte_protocol.models import ( - AirbyteMessage, - AirbyteRecordMessage, - AirbyteStream, - ConfiguredAirbyteStream, - DestinationSyncMode, - SyncMode, - Type, -) -from pydantic import BaseModel - -from live_tests.commons.json_schema_helper import ( - ComparableType, - JsonSchemaHelper, - conforms_to_schema, - get_expected_schema_structure, - get_object_structure, -) - - -def records_with_state(records, state, stream_mapping, state_cursor_paths) -> Iterable[Tuple[Any, Any, Any]]: - """Iterate over records and return cursor value with corresponding cursor value from state""" - - for record in records: - stream_name = record.record.stream - stream = stream_mapping[stream_name] - helper = JsonSchemaHelper(schema=stream.stream.json_schema) - cursor_field = helper.field(stream.cursor_field) - record_value = cursor_field.parse(record=record.record.data) - try: - if state[stream_name] is None: - continue - - # first attempt to parse the state value assuming the state object is namespaced on stream names - state_value = cursor_field.parse(record=state[stream_name], path=state_cursor_paths[stream_name]) - except KeyError: - try: - # try second time as an absolute path in state file (i.e. bookmarks -> stream_name -> column -> value) - state_value = cursor_field.parse(record=state, path=state_cursor_paths[stream_name]) - except KeyError: - continue - yield record_value, state_value, stream_name - - -@pytest.fixture(name="simple_state") -def simple_state_fixture(): - return { - "my_stream": { - "id": 11, - "ts_created": "2014-01-01T22:03:11", - "ts_updated": "2015-01-01T22:03:11", - } - } - - -@pytest.fixture(name="none_state") -def none_state_fixture(): - return {"my_stream": None} - - -@pytest.fixture(name="nested_state") -def nested_state_fixture(simple_state): - return {"my_stream": {"some_account_id": simple_state["my_stream"]}} - - -@pytest.fixture(name="singer_state") -def singer_state_fixture(simple_state): - return {"bookmarks": simple_state} - - -@pytest.fixture(name="stream_schema") -def stream_schema_fixture(): - return { - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "properties": { - "id": {"type": "integer"}, - "ts_created": {"type": "string", "format": "datetime"}, - "nested": {"type": "object", "properties": {"ts_updated": {"type": "string", "format": "date"}}}, - }, - } - - -@pytest.fixture(name="stream_mapping") -def stream_mapping_fixture(stream_schema): - return { - "my_stream": ConfiguredAirbyteStream( - stream=AirbyteStream(name="my_stream", json_schema=stream_schema, supported_sync_modes=[SyncMode.full_refresh]), - sync_mode=SyncMode.full_refresh, - destination_sync_mode=DestinationSyncMode.append, - ) - } - - -@pytest.fixture(name="records") -def records_fixture(): - return [ - AirbyteMessage( - type=Type.RECORD, - record=AirbyteRecordMessage( - stream="my_stream", - data={"id": 1, "ts_created": "2015-11-01T22:03:11", "nested": {"ts_updated": "2015-05-01"}}, - emitted_at=0, - ), - ) - ] - - -def test_simple_path(records, stream_mapping, simple_state): - stream_mapping["my_stream"].cursor_field = ["id"] - paths = {"my_stream": ["id"]} - - result = records_with_state(records=records, state=simple_state, stream_mapping=stream_mapping, state_cursor_paths=paths) - record_value, state_value, stream_name = next(result) - - assert record_value == 1, "record value must be correctly found" - assert state_value == 11, "state value must be correctly found" - - -def test_nested_path(records, stream_mapping, nested_state): - stream_mapping["my_stream"].cursor_field = ["nested", "ts_updated"] - paths = {"my_stream": ["some_account_id", "ts_updated"]} - - result = records_with_state(records=records, state=nested_state, stream_mapping=stream_mapping, state_cursor_paths=paths) - record_value, state_value, stream_name = next(result) - - assert record_value == pendulum.datetime(2015, 5, 1), "record value must be correctly found" - assert state_value == pendulum.datetime(2015, 1, 1, 22, 3, 11), "state value must be correctly found" - - -def test_absolute_path(records, stream_mapping, singer_state): - stream_mapping["my_stream"].cursor_field = ["ts_created"] - paths = {"my_stream": ["bookmarks", "my_stream", "ts_created"]} - - result = records_with_state(records=records, state=singer_state, stream_mapping=stream_mapping, state_cursor_paths=paths) - record_value, state_value, stream_name = next(result) - - assert record_value == pendulum.datetime(2015, 11, 1, 22, 3, 11), "record value must be correctly found" - assert state_value == pendulum.datetime(2014, 1, 1, 22, 3, 11), "state value must be correctly found" - - -def test_none_state(records, stream_mapping, none_state): - stream_mapping["my_stream"].cursor_field = ["ts_created"] - paths = {"my_stream": ["unknown", "ts_created"]} - - result = records_with_state(records=records, state=none_state, stream_mapping=stream_mapping, state_cursor_paths=paths) - assert next(result, None) is None - - -def test_json_schema_helper_pydantic_generated(): - class E(str, Enum): - A = "dda" - B = "dds" - C = "ddf" - - class E2(BaseModel): - e2: str - - class C(BaseModel): - aaa: int - e: Union[E, E2] - - class A(BaseModel): - sdf: str - sss: str - c: C - - class B(BaseModel): - name: str - surname: str - - class Root(BaseModel): - f: Union[A, B] - - js_helper = JsonSchemaHelper(Root.schema()) - variant_paths = js_helper.find_nodes(keys=["anyOf", "oneOf"]) - assert len(variant_paths) == 2 - assert variant_paths == [["properties", "f", "anyOf"], ["definitions", "C", "properties", "e", "anyOf"]] - # TODO: implement validation for pydantic generated objects as well - # js_helper.validate_variant_paths(variant_paths) - - -@pytest.mark.parametrize( - "object, paths", - [ - ({}, []), - ({"a": 12}, ["/a"]), - ({"a": {"b": 12}}, ["/a", "/a/b"]), - ({"a": {"b": 12}, "c": 45}, ["/a", "/a/b", "/c"]), - ( - {"a": [{"b": 12}]}, - ["/a", "/a/[]", "/a/[]/b"], - ), - ({"a": [{"b": 12}, {"b": 15}]}, ["/a", "/a/[]", "/a/[]/b"]), - ({"a": [[[{"b": 12}, {"b": 15}]]]}, ["/a", "/a/[]", "/a/[]/[]", "/a/[]/[]/[]", "/a/[]/[]/[]/b"]), - ], -) -def test_get_object_strucutre(object, paths): - assert get_object_structure(object) == paths - - -@pytest.mark.parametrize( - "schema, paths", - [ - ({"type": "object", "properties": {"a": {"type": "string"}}}, ["/a"]), - ({"properties": {"a": {"type": "string"}}}, ["/a"]), - ({"type": "object", "properties": {"a": {"type": "string"}, "b": {"type": "number"}}}, ["/a", "/b"]), - ( - { - "type": "object", - "properties": {"a": {"type": "string"}, "b": {"$ref": "#definitions/b_type"}}, - "definitions": {"b_type": {"type": "number"}}, - }, - ["/a", "/b"], - ), - ({"type": "object", "oneOf": [{"properties": {"a": {"type": "string"}}}, {"properties": {"b": {"type": "string"}}}]}, ["/a", "/b"]), - # Some of pydantic generatec schemas have anyOf keyword - ({"type": "object", "anyOf": [{"properties": {"a": {"type": "string"}}}, {"properties": {"b": {"type": "string"}}}]}, ["/a", "/b"]), - ( - {"type": "array", "items": {"oneOf": [{"properties": {"a": {"type": "string"}}}, {"properties": {"b": {"type": "string"}}}]}}, - ["/[]/a", "/[]/b"], - ), - # There could be an object with any properties with specific type - ({"type": "object", "properties": {"a": {"type": "object", "additionalProperties": {"type": "string"}}}}, ["/a"]), - # Array with no item type specified - ({"type": "array"}, ["/[]"]), - ({"type": "array", "items": {"type": "object", "additionalProperties": {"type": "string"}}}, ["/[]"]), - ], -) -def test_get_expected_schema_structure(schema, paths): - assert paths == get_expected_schema_structure(schema) - - -@pytest.mark.parametrize( - "keys, num_paths, last_value", - [ - (["description"], 1, "Tests that keys can be found inside lists of dicts"), - (["option1"], 2, {"a_key": "a_value"}), - (["option2"], 1, ["value1", "value2"]), - (["nonexistent_key"], 0, None), - (["option1", "option2"], 3, ["value1", "value2"]), - ], -) -def test_find_and_get_nodes(keys: List[Text], num_paths: int, last_value: Any): - schema = { - "title": "Key_inside_oneOf", - "description": "Tests that keys can be found inside lists of dicts", - "type": "object", - "properties": { - "credentials": { - "type": "object", - "oneOf": [ - { - "type": "object", - "properties": { - "common": {"type": "string", "const": "option1", "default": "option1"}, - "option1": {"type": "string"}, - }, - }, - { - "type": "object", - "properties": { - "common": {"type": "string", "const": "option2", "default": "option2"}, - "option1": {"a_key": "a_value"}, - "option2": ["value1", "value2"], - }, - }, - ], - } - }, - } - schema_helper = JsonSchemaHelper(schema) - variant_paths = schema_helper.find_nodes(keys=keys) - assert len(variant_paths) == num_paths - - if variant_paths: - values_at_nodes = [] - for path in variant_paths: - values_at_nodes.append(schema_helper.get_node(path)) - assert last_value in values_at_nodes - - -COMPLETE_CONFORMING_RECORD = { - "null_field": None, - "boolean_field": True, - "integer_field": 1, - "number_field": 1.5, - "string_field": "val1", - "array_field": [1.1, 2.2], - "object_field": {"col": "val"}, -} - - -NONCONFORMING_EXTRA_COLUMN_RECORD = { - "null_field": None, - "boolean_field": True, - "integer_field": 1, - "number_field": 1.5, - "string_field": "val1", - "array_field": [1.1, 2.2], - "object_field": {"col": "val"}, - "column_x": "extra", -} - -CONFORMING_WITH_MISSING_COLUMN_RECORD = { - "null_field": None, - "boolean_field": True, - "integer_field": 1, - "number_field": 1.5, - "string_field": "val1", - "array_field": [1.1, 2.2], -} - -CONFORMING_WITH_NARROWER_TYPE_RECORD = { - "null_field": None, - "boolean_field": True, - "integer_field": True, - "number_field": True, - "string_field": True, - "array_field": [1.1, 2.2], - "object_field": {"col": "val"}, -} - -NONCONFORMING_WIDER_TYPE_RECORD = { - "null_field": "not None", - "boolean_field": True, - "integer_field": 1, - "number_field": 1.5, - "string_field": "val1", - "array_field": [1.1, 2.2], - "object_field": {"col": "val"}, -} - -NONCONFORMING_NON_OBJECT_RECORD = { - "null_field": None, - "boolean_field": True, - "integer_field": 1, - "number_field": 1.5, - "string_field": "val1", - "array_field": [1.1, 2.2], - "object_field": "not an object", -} - -NONCONFORMING_NON_ARRAY_RECORD = { - "null_field": None, - "boolean_field": True, - "integer_field": 1, - "number_field": 1.5, - "string_field": "val1", - "array_field": "not an array", - "object_field": {"col": "val"}, -} - -CONFORMING_MIXED_TYPE_NARROWER_RECORD = { - "null_field": None, - "boolean_field": True, - "integer_field": 1, - "number_field": 1.5, - "string_field": "val1", - "array_field": [1.1, 2.2], - "object_field": {"col": "val"}, -} - -NONCONFORMING_MIXED_TYPE_WIDER_RECORD = { - "null_field": None, - "boolean_field": True, - "integer_field": 1, - "number_field": 1.5, - "string_field": "val1", - "array_field": [1.1, 2.2], - "object_field": {"col": "val"}, -} - -CONFORMING_MIXED_TYPE_WITHIN_TYPE_RANGE_RECORD = { - "null_field": None, - "boolean_field": True, - "integer_field": 1, - "number_field": 1.5, - "string_field": "val1", - "array_field": [1.1, 2.2], - "object_field": {"col": "val"}, -} - -NONCONFORMING_INVALID_ARRAY_RECORD = { - "null_field": None, - "boolean_field": True, - "integer_field": 1, - "number_field": 1.5, - "string_field": ["this should not be an array"], - "array_field": [1.1, 2.2], - "object_field": {"col": "val"}, -} - -NONCONFORMING_TOO_WIDE_ARRAY_RECORD = { - "null_field": None, - "boolean_field": True, - "integer_field": 1, - "number_field": 1.5, - "string_field": "okay", - "array_field": ["val1", "val2"], - "object_field": {"col": "val"}, -} - - -CONFORMING_NARROWER_ARRAY_RECORD = { - "null_field": None, - "boolean_field": True, - "integer_field": 1, - "number_field": 1.5, - "string_field": "okay", - "array_field": [1, 2], - "object_field": {"col": "val"}, -} - - -NONCONFORMING_INVALID_OBJECT_RECORD = { - "null_field": None, - "boolean_field": True, - "integer_field": 1, - "number_field": 1.5, - "string_field": {"this": "should not be an object"}, - "array_field": [1.1, 2.2], - "object_field": {"col": "val"}, -} - - -SCHEMA = { - "type": "object", - "properties": { - "null_field": {"type": "null"}, - "boolean_field": {"type": "boolean"}, - "integer_field": {"type": "integer"}, - "number_field": {"type": "number"}, - "string_field": {"type": "string"}, - "array_field": { - "type": "array", - "items": { - "type": "number", - }, - }, - "object_field": {"type": "object"}, - }, -} - - -@pytest.mark.parametrize( - "record,schema,expected_result", - [ - pytest.param(COMPLETE_CONFORMING_RECORD, SCHEMA, True, id="record-conforms"), - pytest.param(NONCONFORMING_EXTRA_COLUMN_RECORD, SCHEMA, False, id="nonconforming-extra-column"), - pytest.param(CONFORMING_WITH_MISSING_COLUMN_RECORD, SCHEMA, True, id="record-conforms-with-missing-column"), - pytest.param(CONFORMING_WITH_NARROWER_TYPE_RECORD, SCHEMA, True, id="record-conforms-with-narrower-type"), - pytest.param(NONCONFORMING_WIDER_TYPE_RECORD, SCHEMA, False, id="nonconforming-wider-type"), - pytest.param(NONCONFORMING_NON_OBJECT_RECORD, SCHEMA, False, id="nonconforming-string-is-not-an-object"), - pytest.param(NONCONFORMING_NON_ARRAY_RECORD, SCHEMA, False, id="nonconforming-string-is-not-an-array"), - pytest.param(NONCONFORMING_TOO_WIDE_ARRAY_RECORD, SCHEMA, False, id="nonconforming-array-values-too-wide"), - pytest.param(CONFORMING_NARROWER_ARRAY_RECORD, SCHEMA, True, id="conforming-array-values-narrower-than-schema"), - pytest.param(NONCONFORMING_INVALID_ARRAY_RECORD, SCHEMA, False, id="nonconforming-array-is-not-a-string"), - pytest.param(NONCONFORMING_INVALID_OBJECT_RECORD, SCHEMA, False, id="nonconforming-object-is-not-a-string"), - ], -) -def test_conforms_to_schema(record: Mapping[str, Any], schema: Mapping[str, Any], expected_result: bool) -> None: - assert conforms_to_schema(record, schema) == expected_result - - -def test_comparable_types() -> None: - assert ComparableType.OBJECT > ComparableType.STRING - assert ComparableType.STRING > ComparableType.NUMBER - assert ComparableType.NUMBER > ComparableType.INTEGER - assert ComparableType.INTEGER > ComparableType.BOOLEAN - assert ComparableType["OBJECT"] == ComparableType.OBJECT diff --git a/airbyte-ci/connectors/metadata_service/README.md b/airbyte-ci/connectors/metadata_service/README.md deleted file mode 100644 index 5a0c36548ddf..000000000000 --- a/airbyte-ci/connectors/metadata_service/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Metadata Service - -Airbyte Metadata Service manages the Airbyte Connector Registry. - -This system is responsible for the following: - -- Validating Connector metadata -- Storing Connector metadata in GCS -- Serving Connector metadata to various consumers -- Aggregating Connector metadata to provide a unified view of all connectors -- Triggering actions based on changes to Connector metadata - -## Subsystems - -- [Metadata Lib](./lib) responsible for preparing and validating connector metadata. diff --git a/airbyte-ci/connectors/metadata_service/docs/external_documentation_urls.md b/airbyte-ci/connectors/metadata_service/docs/external_documentation_urls.md deleted file mode 100644 index e67d19bb8804..000000000000 --- a/airbyte-ci/connectors/metadata_service/docs/external_documentation_urls.md +++ /dev/null @@ -1,554 +0,0 @@ -# External Documentation URLs Guide - -## Overview - -This guide explains how to identify, scrape, and maintain `externalDocumentationUrls` in connector `metadata.yaml` files. These URLs point to official vendor documentation that helps users understand API changes, authentication requirements, rate limits, and other critical information. - -### Purpose - -External documentation URLs serve several key purposes: -- Surface vendor changelogs and release notes for tracking breaking changes -- Provide quick access to authentication and permissions documentation -- Link to rate limits and quota information -- Direct users to official API references and data model documentation -- Connect users with vendor status pages and developer communities - -### Schema Location - -The schema is defined in `airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorMetadataDefinitionV0.yaml`. - -The `externalDocumentationUrls` field is an optional array where each entry contains: -- `title` (required): Display title for the documentation link -- `url` (required): URL to the external documentation -- `type` (optional): Category of documentation (see taxonomy below) -- `requiresLogin` (optional, default: false): Whether the URL requires authentication to access - -## Documentation Type Taxonomy - -### api_release_history -**Description:** Changelogs, release notes, API version history, and out-of-cycle changes. - -**Typical URL patterns:** -- `*/changelog*` -- `*/release-notes*` -- `*/api/versions*` -- `*/whats-new*` - -**Examples:** -- Airtable: `https://airtable.com/developers/web/api/changelog` -- Google Ads: `https://developers.google.com/google-ads/api/docs/release-notes` -- Salesforce: `https://help.salesforce.com/s/articleView?id=release-notes.salesforce_release_notes.htm` -- Facebook Marketing: `https://developers.facebook.com/docs/marketing-api/marketing-api-changelog` - -### api_reference -**Description:** API documentation, versioning docs, technical references, and API specifications. - -**Typical URL patterns:** -- `*/api/reference*` -- `*/api/docs*` -- `*/developers/api*` -- `*/api-reference*` - -**Examples:** -- GitLab: `https://docs.gitlab.com/ee/api/rest/` -- Chargebee: `https://apidocs.chargebee.com/docs/api/versioning` -- Azure Blob Storage: `https://learn.microsoft.com/en-us/rest/api/storageservices/` -- Pinecone: `https://docs.pinecone.io/reference/api/introduction` - -### api_deprecations -**Description:** Deprecation notices, future breaking changes, and migration timelines. - -**Typical URL patterns:** -- `*/deprecations*` -- `*/breaking-changes*` -- `*/sunset*` -- `*/migration*` - -**Examples:** -- GitLab: `https://docs.gitlab.com/ee/api/rest/deprecations.html` -- Facebook Marketing: `https://developers.facebook.com/docs/marketing-api/out-of-cycle-changes/` -- Stripe: `https://stripe.com/docs/upgrades#api-versions` - -### authentication_guide -**Description:** Official OAuth/API key setup, consent flows, and authentication methods. - -**Typical URL patterns:** -- `*/oauth*` -- `*/authentication*` -- `*/auth*` -- `*/api-keys*` -- `*/credentials*` - -**Examples:** -- Airtable: `https://airtable.com/developers/web/api/oauth-reference` -- Google Cloud: `https://cloud.google.com/iam/docs/service-accounts` -- Salesforce: `https://help.salesforce.com/s/articleView?id=sf.connected_app_create.htm` -- Snowflake: `https://docs.snowflake.com/en/user-guide/key-pair-auth` - -### permissions_scopes -**Description:** Required roles, permissions, OAuth scopes, or database GRANTs. - -**Typical URL patterns:** -- `*/permissions*` -- `*/scopes*` -- `*/roles*` -- `*/access-control*` -- `*/grants*` - -**Examples:** -- BigQuery: `https://cloud.google.com/bigquery/docs/access-control` -- Salesforce: `https://help.salesforce.com/s/articleView?id=sf.connected_app_create_api_integration.htm` -- Google Ads: `https://developers.google.com/google-ads/api/docs/oauth/overview` -- Postgres: `https://www.postgresql.org/docs/current/sql-grant.html` - -### rate_limits -**Description:** Rate limits, quotas, throttling behavior, and concurrency limits. - -**Typical URL patterns:** -- `*/rate-limits*` -- `*/quotas*` -- `*/limits*` -- `*/throttling*` - -**Examples:** -- BigQuery: `https://cloud.google.com/bigquery/quotas` -- GitHub: `https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting` -- Salesforce: `https://developer.salesforce.com/docs/atlas.en-us.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/` -- Stripe: `https://stripe.com/docs/rate-limits` - -### status_page -**Description:** Vendor status/uptime pages for incident tracking. - -**Typical URL patterns:** -- `status.*` -- `*/status*` -- `*/system-status*` - -**Examples:** -- Snowflake: `https://status.snowflake.com/` -- Google Cloud: `https://status.cloud.google.com/` -- Salesforce: `https://status.salesforce.com/` -- GitHub: `https://www.githubstatus.com/` - -### data_model_reference -**Description:** Object/field/endpoint reference for SaaS APIs (what tables/fields exist). - -**Typical URL patterns:** -- `*/object-reference*` -- `*/data-model*` -- `*/schema*` -- `*/objects*` - -**Examples:** -- Salesforce: `https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/` -- HubSpot: `https://developers.hubspot.com/docs/api/crm/understanding-the-crm` -- GitHub: `https://docs.github.com/en/rest/overview/resources-in-the-rest-api` - -### sql_reference -**Description:** SQL dialect/reference docs for databases and warehouses. - -**Typical URL patterns:** -- `*/sql-reference*` -- `*/sql/reference*` -- `*/language-reference*` - -**Examples:** -- BigQuery: `https://cloud.google.com/bigquery/docs/reference/standard-sql` -- Snowflake: `https://docs.snowflake.com/en/sql-reference` -- Postgres: `https://www.postgresql.org/docs/current/sql.html` -- Redshift: `https://docs.aws.amazon.com/redshift/latest/dg/c_SQL_reference.html` - -### migration_guide -**Description:** Vendor migration/breaking-change guides between versions. - -**Typical URL patterns:** -- `*/migration*` -- `*/upgrade*` -- `*/version-migration*` - -**Examples:** -- Stripe: `https://stripe.com/docs/upgrades` -- Elasticsearch: `https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking-changes.html` - -### developer_community -**Description:** Official forums/communities for vendor Q&A and technical discussions. - -**Typical URL patterns:** -- `community.*` -- `*/community*` -- `*/forum*` -- `*/discussions*` - -**Examples:** -- Airtable: `https://community.airtable.com/development-apis-11` -- Salesforce: `https://developer.salesforce.com/forums` -- Snowflake: `https://community.snowflake.com/` - -### other -**Description:** Catch-all for documentation that doesn't fit other categories. Use sparingly. - -**Note:** Since `type` is optional, prefer omitting the type field rather than using "other" when a link doesn't fit neatly into a category. - -## How to Find Documentation URLs - -### Preferred Sources (in order of priority) -1. **Official vendor documentation** (e.g., `docs.vendor.com`, `developers.vendor.com`) -2. **Official vendor blogs** (e.g., `blog.vendor.com`, `developers.vendor.com/blog`) -3. **Official community forums** (e.g., `community.vendor.com`) - -### Search Query Templates - -Use these search patterns to find appropriate documentation: - -``` -# Release notes / changelogs -site: "release notes" -site: "changelog" -site: "API changelog" - -# API reference -site: "API reference" -site: "API documentation" - -# Authentication -site: "OAuth" -site: "authentication" -site: "API key" - -# Permissions -site: "permissions" -site: "scopes" -site: "access control" - -# Rate limits -site: "rate limits" -site: "quotas" -site: "API limits" - -# Status page -site:status. -"" status page - -# SQL reference (for databases/warehouses) -site: "SQL reference" -site: "language reference" -``` - -### URL Selection Heuristics - -1. **Prefer canonical, version-agnostic URLs** that are updated over time rather than version-specific pages - - ✅ Good: `https://docs.vendor.com/api/changelog` - - ❌ Avoid: `https://docs.vendor.com/v2.3/api/changelog` - -2. **Avoid locale-specific paths** when generic URLs exist - - ✅ Good: `https://docs.vendor.com/api/reference` - - ❌ Avoid: `https://docs.vendor.com/en-us/api/reference` - -3. **Prefer stable root pages** over deep-linked anchors that may change - - ✅ Good: `https://docs.vendor.com/rate-limits` - - ⚠️ Use with caution: `https://docs.vendor.com/api#rate-limits-section` - -4. **Always use official vendor domains** - never third-party mirrors or documentation aggregators - -5. **Set `requiresLogin: true`** when the URL requires authentication to access - -## Connector Family-Specific Guidance - -### Data Warehouses (BigQuery, Snowflake, Redshift, Databricks) - -**Priority types to include:** -- `sql_reference` (required) - SQL dialect documentation -- `authentication_guide` - Service account, key pair, or IAM auth -- `permissions_scopes` - Required roles and grants -- `api_release_history` - Release notes for API/driver changes -- `status_page` - Service status monitoring -- `rate_limits` - Query limits, concurrency limits (if applicable) - -**Example (BigQuery):** -```yaml -externalDocumentationUrls: - - title: Release notes - url: https://cloud.google.com/bigquery/docs/release-notes - type: api_release_history - - title: Standard SQL reference - url: https://cloud.google.com/bigquery/docs/reference/standard-sql - type: sql_reference - - title: Service account authentication - url: https://cloud.google.com/iam/docs/service-accounts - type: authentication_guide - - title: Access control and permissions - url: https://cloud.google.com/bigquery/docs/access-control - type: permissions_scopes - - title: Quotas and limits - url: https://cloud.google.com/bigquery/quotas - type: rate_limits - - title: Google Cloud Status - url: https://status.cloud.google.com/ - type: status_page -``` - -### Databases (Postgres, MySQL, MSSQL, MongoDB) - -**Priority types to include:** -- `sql_reference` (for SQL databases) - SQL dialect documentation -- `authentication_guide` - Connection and authentication methods -- `permissions_scopes` - User permissions and grants -- `api_release_history` - Version release notes (if applicable) - -**Example (Postgres):** -```yaml -externalDocumentationUrls: - - title: PostgreSQL documentation - url: https://www.postgresql.org/docs/current/ - type: api_reference - - title: SQL reference - url: https://www.postgresql.org/docs/current/sql.html - type: sql_reference - - title: Authentication methods - url: https://www.postgresql.org/docs/current/auth-methods.html - type: authentication_guide - - title: GRANT permissions - url: https://www.postgresql.org/docs/current/sql-grant.html - type: permissions_scopes -``` - -### SaaS APIs (Salesforce, HubSpot, GitHub, Stripe) - -**Priority types to include:** -- `api_release_history` (required) - Changelogs and release notes -- `api_reference` - API documentation -- `api_deprecations` - Deprecation schedules (if available) -- `authentication_guide` - OAuth or API key setup -- `permissions_scopes` - Required scopes or permissions -- `rate_limits` - API rate limits -- `data_model_reference` - Object/field reference -- `developer_community` - Developer forums -- `status_page` - Service status - -**Example (Salesforce):** -```yaml -externalDocumentationUrls: - - title: API release notes - url: https://help.salesforce.com/s/articleView?id=release-notes.salesforce_release_notes.htm - type: api_release_history - - title: REST API reference - url: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/ - type: api_reference - - title: Connected app OAuth - url: https://help.salesforce.com/s/articleView?id=sf.connected_app_create.htm - type: authentication_guide - - title: OAuth scopes - url: https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_tokens_scopes.htm - type: permissions_scopes - - title: API rate limits - url: https://developer.salesforce.com/docs/atlas.en-us.salesforce_app_limits_cheatsheet.meta/salesforce_app_limits_cheatsheet/ - type: rate_limits - - title: Object reference - url: https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/ - type: data_model_reference - - title: Salesforce Status - url: https://status.salesforce.com/ - type: status_page -``` - -### Vector Stores (Pinecone, Weaviate, Qdrant, Chroma) - -**Priority types to include:** -- `api_reference` (required) - API documentation -- `rate_limits` - Request limits and quotas -- `authentication_guide` - API key or authentication setup -- `api_release_history` - Release notes (if available) -- `status_page` - Service status (if available) -- `migration_guide` - Version migration guides (if versions differ significantly) - -**Example (Pinecone):** -```yaml -externalDocumentationUrls: - - title: API reference - url: https://docs.pinecone.io/reference/api/introduction - type: api_reference - - title: Authentication - url: https://docs.pinecone.io/guides/get-started/authentication - type: authentication_guide - - title: Rate limits - url: https://docs.pinecone.io/troubleshooting/rate-limits - type: rate_limits - - title: Release notes - url: https://docs.pinecone.io/release-notes - type: api_release_history -``` - -## Maintenance Guidelines - -### Link Stability Checks - -Periodically validate that external documentation URLs are still accessible: - -1. **HTTP status validation** - Check that URLs return 200 or 3xx status codes -2. **Flag 4xx/5xx errors** - Document broken links for replacement -3. **Set `requiresLogin: true`** when appropriate to avoid false positives - -**Simple validation script:** -```bash -# Check a single URL -curl -I -L -s -o /dev/null -w "%{http_code}" "https://docs.vendor.com/api/changelog" - -# Expected: 200, 301, 302 -# Action needed: 404, 403, 500 -``` - -### Update Cadence - -- **Quarterly sweep** - Review all external documentation URLs for broken links -- **On vendor announcements** - Update when vendors announce major documentation restructuring -- **On deprecation notices** - Add `api_deprecations` links when vendors announce breaking changes - -### Replacement Rules - -When updating broken or outdated links: - -1. **Prefer same domain** - Look for the new location on the same vendor domain -2. **Check vendor consolidation** - Vendors may consolidate multiple doc sites into one -3. **Update to canonical** - If vendor provides a redirect, update to the final destination -4. **Document in PR** - Note why the link was changed in the PR description - -### PR Review Practices - -When reviewing PRs that add or modify external documentation URLs: - -1. **Spot-check 2-3 links** per connector to verify they're accessible and relevant -2. **Verify type categorization** - Ensure the `type` field matches the content -3. **Check for duplicates** - Avoid adding the same URL twice with different titles -4. **Validate requiresLogin** - Confirm whether authentication is actually required - -## YAML Template - -Here's a canonical example showing multiple types: - -```yaml -externalDocumentationUrls: - - title: Release notes - url: https://cloud.google.com/bigquery/docs/release-notes - type: api_release_history - - title: Standard SQL reference - url: https://cloud.google.com/bigquery/docs/reference/standard-sql - type: sql_reference - - title: Service account authentication - url: https://cloud.google.com/iam/docs/service-accounts - type: authentication_guide - - title: Access control and permissions - url: https://cloud.google.com/bigquery/docs/access-control - type: permissions_scopes - - title: Quotas and limits - url: https://cloud.google.com/bigquery/quotas - type: rate_limits - - title: Google Cloud Status - url: https://status.cloud.google.com/ - type: status_page - requiresLogin: false -``` - -## Validation Checklist - -Before submitting a PR with external documentation URLs: - -- [ ] Schema validation passes (run `poetry run metadata_service validate `) -- [ ] All URLs return HTTP 200 or 3xx status codes -- [ ] No paywalls or login requirements (unless `requiresLogin: true` is set) -- [ ] URLs are canonical and version-agnostic when possible -- [ ] Type categorization is accurate -- [ ] No duplicate URLs with different titles -- [ ] Official vendor domains only (no third-party mirrors) -- [ ] Titles are descriptive and consistent with vendor terminology - -## Common Pitfalls to Avoid - -1. **Don't over-categorize** - If a link doesn't fit neatly, omit the `type` field rather than forcing it -2. **Avoid version-specific URLs** - Prefer evergreen URLs that are updated over time -3. **Don't link to third-party docs** - Always use official vendor documentation -4. **Watch for locale redirects** - Some URLs may redirect based on browser locale -5. **Don't assume status pages exist** - Not all vendors have public status pages -6. **Avoid deep anchors** - Deep-linked sections may change; prefer stable root pages -7. **Don't duplicate content** - If a single page covers multiple topics, link it once with the most specific type - -## Examples by Connector Type - -### Example: Snowflake (Data Warehouse) -```yaml -externalDocumentationUrls: - - title: Release notes - url: https://docs.snowflake.com/en/release-notes - type: api_release_history - - title: SQL reference - url: https://docs.snowflake.com/en/sql-reference - type: sql_reference - - title: Key pair authentication - url: https://docs.snowflake.com/en/user-guide/key-pair-auth - type: authentication_guide - - title: Access control - url: https://docs.snowflake.com/en/user-guide/security-access-control - type: permissions_scopes - - title: Snowflake Status - url: https://status.snowflake.com/ - type: status_page -``` - -### Example: Stripe (SaaS API) -```yaml -externalDocumentationUrls: - - title: API changelog - url: https://stripe.com/docs/upgrades#api-changelog - type: api_release_history - - title: API reference - url: https://stripe.com/docs/api - type: api_reference - - title: API versioning and upgrades - url: https://stripe.com/docs/upgrades - type: migration_guide - - title: Authentication - url: https://stripe.com/docs/keys - type: authentication_guide - - title: Rate limits - url: https://stripe.com/docs/rate-limits - type: rate_limits - - title: Stripe Status - url: https://status.stripe.com/ - type: status_page -``` - -### Example: Postgres (Database) -```yaml -externalDocumentationUrls: - - title: PostgreSQL documentation - url: https://www.postgresql.org/docs/current/ - type: api_reference - - title: SQL commands - url: https://www.postgresql.org/docs/current/sql-commands.html - type: sql_reference - - title: Client authentication - url: https://www.postgresql.org/docs/current/client-authentication.html - type: authentication_guide - - title: Database roles and privileges - url: https://www.postgresql.org/docs/current/user-manag.html - type: permissions_scopes -``` - -## Regenerating Schema After Changes - -If you modify the schema enum in `ConnectorMetadataDefinitionV0.yaml`, regenerate the generated models: - -```bash -cd airbyte-ci/connectors/metadata_service/lib -poetry install -poetry run poe generate-models -``` - -This will update: -- `metadata_service/models/generated/ConnectorMetadataDefinitionV0.json` -- `metadata_service/models/generated/ConnectorMetadataDefinitionV0.py` - -## Additional Resources - -- [Connector Metadata Schema](../lib/metadata_service/models/src/ConnectorMetadataDefinitionV0.yaml) -- [Metadata Service README](../lib/README.md) -- [Connector Development Guide](https://docs.airbyte.com/connector-development/) diff --git a/airbyte-ci/connectors/metadata_service/lib/README.md b/airbyte-ci/connectors/metadata_service/lib/README.md deleted file mode 100644 index 2ea1156757b1..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/README.md +++ /dev/null @@ -1,91 +0,0 @@ -# Connector Metadata Service Library - -This submodule is responsible for managing all the logic related to validating, uploading, and managing connector metadata. - -## Installation - -To use this submodule, it is recommended that you use Poetry to manage dependencies. - -``` -poetry install -``` - -### Node.js Requirement - -The model generation process also requires Node.js to bundle JSON schemas. Install Node.js: - -- On macOS: `brew install node` -- On Ubuntu/Debian: `sudo apt-get install nodejs npm` -- On other systems: https://nodejs.org/ - -Node.js dependencies will be automatically installed when running `poetry run poe generate-models`. - -## Generating Models - -This submodule includes a tool for generating Python models from JSON Schema specifications. To generate the models, we use the library [datamodel-code-generator](https://github.com/koxudaxi/datamodel-code-generator). The generated models are stored in `models/generated`. - -To generate the models, run the following command: - -```bash -poetry run poe generate-models - -``` - -This will read the JSON Schema specifications in `models/src` and generate Python models in `models/generated`. - -## Running Tests - -```bash -poetry run pytest -``` - -## Changelog - -### 0.24.1 -Update Python version requirement from 3.10 to 3.11. - -## Validating Metadata Files - -To be considered valid, a connector must have a metadata.yaml file which must conform to the [ConnectorMetadataDefinitionV0](./metadata_service/models/src/ConnectorMetadataDefinitionV0.yaml) schema, and a documentation file. - -The paths to both files must be passed to the validate command. - -```bash -poetry run metadata_service validate tests/fixtures/metadata_validate/valid/metadata_simple.yaml tests/fixtures/doc.md -``` - -## Useful Commands - -### Replicate Production Data in your Development Bucket - -This will replicate all the production data to your development bucket. This is useful for testing the metadata service with real up to date data. - -_💡 Note: A prerequisite is you have [gsutil](https://cloud.google.com/storage/docs/gsutil) installed and have run `gsutil auth login`_ - -_⚠️ Warning: Its important to know that this will remove ANY files you have in your destination buckets as it calls `gsutil rsync` with `-d` enabled._ - -```bash -TARGET_BUCKET= poetry run poe replicate-prod -``` - -### Copy specific connector version to your Development Bucket - -This will copy the specified connector version to your development bucket. This is useful for testing the metadata service with a specific version of a connector. - -_💡 Note: A prerequisite is you have [gsutil](https://cloud.google.com/storage/docs/gsutil) installed and have run `gsutil auth login`_ - -```bash -TARGET_BUCKET= CONNECTOR="airbyte/source-stripe" VERSION="3.17.0-preview.ea013c8" poetry run poe copy-connector-from-prod -``` - -### Promote Connector Version to Latest - -This will promote the specified connector version to the latest version in the registry. This is useful for creating a mocked registry in which a prerelease connector is treated as if it was already published. - -_💡 Note: A prerequisite is you have [gsutil](https://cloud.google.com/storage/docs/gsutil) installed and have run `gsutil auth login`_ - -_⚠️ Warning: Its important to know that this will remove ANY existing files in the latest folder that are not in the versioned folder as it calls `gsutil rsync` with `-d` enabled._ - -```bash -TARGET_BUCKET= CONNECTOR="airbyte/source-stripe" VERSION="3.17.0-preview.ea013c8" poetry run poe promote-connector-to-latest -``` diff --git a/airbyte-ci/connectors/metadata_service/lib/bin/bundle-schemas.js b/airbyte-ci/connectors/metadata_service/lib/bin/bundle-schemas.js deleted file mode 100755 index 003d71e7a266..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/bin/bundle-schemas.js +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env node - -/** - * Bundle JSON schemas using @apidevtools/json-schema-ref-parser - * This script resolves all $ref references in the schema files and creates a single bundled schema. - */ - -const $RefParser = require('@apidevtools/json-schema-ref-parser'); -const fs = require('fs'); -const path = require('path'); - -const YAML_DIR = 'metadata_service/models/src'; -const OUTPUT_DIR = 'metadata_service/models/generated'; -const ENTRY_SCHEMA = path.join(YAML_DIR, 'ConnectorMetadataDefinitionV0.yaml'); -const BUNDLE_OUTPUT = path.join(OUTPUT_DIR, 'ConnectorMetadataDefinitionV0.json'); - -async function bundleSchemas() { - try { - console.log('📦 Bundling JSON schemas...'); - console.log(` Entry schema: ${ENTRY_SCHEMA}`); - console.log(` Output: ${BUNDLE_OUTPUT}`); - - if (!fs.existsSync(YAML_DIR)) { - console.error(`❌ Error: The yaml directory does not exist: ${YAML_DIR}`); - process.exit(1); - } - - if (!fs.existsSync(OUTPUT_DIR)) { - fs.mkdirSync(OUTPUT_DIR, { recursive: true }); - } - - const schema = await $RefParser.bundle(ENTRY_SCHEMA, { - dereference: { - circular: 'ignore' // Handle circular references gracefully - } - }); - - fs.writeFileSync(BUNDLE_OUTPUT, JSON.stringify(schema, null, 2)); - - console.log('✅ Successfully bundled schema to', BUNDLE_OUTPUT); - console.log(' This bundled schema can be used for IDE validation and other tools.'); - } catch (error) { - console.error('❌ Error bundling schemas:', error.message); - process.exit(1); - } -} - -bundleSchemas(); diff --git a/airbyte-ci/connectors/metadata_service/lib/bin/generate-metadata-models.sh b/airbyte-ci/connectors/metadata_service/lib/bin/generate-metadata-models.sh deleted file mode 100755 index 4f5790990b91..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/bin/generate-metadata-models.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash - -set -e - - -YAML_DIR=metadata_service/models/src -OUTPUT_DIR=metadata_service/models/generated - -# Ensure the yaml directory exists -if [ ! -d "$YAML_DIR" ]; then - echo "The yaml directory does not exist: $YAML_DIR" - exit 1 -fi - - -rm -rf "$OUTPUT_DIR"/*.py -mkdir -p "$OUTPUT_DIR" - -echo "# generated by generate-metadata-models" > "$OUTPUT_DIR"/__init__.py - -for f in "$YAML_DIR"/*.yaml; do - filename_wo_ext=$(basename "$f" | cut -d . -f 1) - echo "from .$filename_wo_ext import *" >> "$OUTPUT_DIR"/__init__.py - - datamodel-codegen \ - --input "$YAML_DIR/$filename_wo_ext.yaml" \ - --output "$OUTPUT_DIR/$filename_wo_ext.py" \ - --use-title-as-name \ - --use-double-quotes \ - --enum-field-as-literal all \ - --disable-timestamp -done - -echo "" -echo "Generating bundled JSON schema..." -node bin/bundle-schemas.js diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/commands.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/commands.py deleted file mode 100644 index 203eb59746d7..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/commands.py +++ /dev/null @@ -1,252 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -import logging -import pathlib - -import click -import sentry_sdk -from pydantic import ValidationError - -from metadata_service.constants import METADATA_FILE_NAME, VALID_REGISTRIES -from metadata_service.gcs_upload import ( - MetadataDeleteInfo, - MetadataUploadInfo, - delete_release_candidate_from_gcs, - promote_release_candidate_in_gcs, - upload_metadata_to_gcs, -) -from metadata_service.registry import generate_and_persist_connector_registry -from metadata_service.registry_entry import generate_and_persist_registry_entry -from metadata_service.registry_report import generate_and_persist_registry_report -from metadata_service.sentry import setup_sentry -from metadata_service.specs_secrets_mask import generate_and_persist_specs_secrets_mask -from metadata_service.stale_metadata_report import generate_and_publish_stale_metadata_report -from metadata_service.validators.metadata_validator import PRE_UPLOAD_VALIDATORS, ValidatorOptions, validate_and_load - - -def setup_logging(debug: bool = False): - """Configure logging for the CLI.""" - level = logging.DEBUG if debug else logging.INFO - logging.basicConfig( - level=level, - format="%(asctime)s - %(levelname)s - %(message)s", - datefmt="%Y-%m-%d %H:%M:%S", - handlers=[logging.StreamHandler()], - ) - # Suppress logging from the following libraries - logging.getLogger("urllib3").setLevel(logging.WARNING) - logging.getLogger("slack_sdk.web.base_client").setLevel(logging.WARNING) - logging.getLogger("google.resumable_media").setLevel(logging.WARNING) - - -logger = logging.getLogger(__name__) - - -def log_metadata_upload_info(metadata_upload_info: MetadataUploadInfo): - """Log the results of the metadata upload.""" - for file in metadata_upload_info.uploaded_files: - if file.uploaded: - click.secho(f"File:{file.id} for {metadata_upload_info.metadata_file_path} was uploaded to {file.blob_id}.", fg="green") - else: - click.secho( - f"File:{file.id} for {metadata_upload_info.metadata_file_path} was not uploaded.", - fg="yellow", - ) - - -def log_metadata_deletion_info(metadata_deletion_info: MetadataDeleteInfo): - """Log the results of the metadata deletion.""" - for remote_file in metadata_deletion_info.deleted_files: - if remote_file.deleted: - click.secho(f"The {remote_file.description} was deleted ({remote_file.blob_id}).", fg="green") - else: - click.secho( - f"The {remote_file.description} was not deleted ({remote_file.blob_id}).", - fg="red", - ) - - -@click.group(help="Airbyte Metadata Service top-level command group.") -@click.option("--debug", is_flag=True, help="Enable debug logging", default=False) -def metadata_service(debug: bool): - """Top-level command group with logging configuration.""" - setup_sentry() - setup_logging(debug) - - -@metadata_service.command(help="Validate a given metadata YAML file.") -@click.argument("metadata_file_path", type=click.Path(exists=True, path_type=pathlib.Path), required=True) -@click.argument("docs_path", type=click.Path(exists=True, path_type=pathlib.Path), required=True) -def validate(metadata_file_path: pathlib.Path, docs_path: pathlib.Path): - metadata_file_path = metadata_file_path if not metadata_file_path.is_dir() else metadata_file_path / METADATA_FILE_NAME - - click.echo(f"Validating {metadata_file_path}...") - metadata, error = validate_and_load(metadata_file_path, PRE_UPLOAD_VALIDATORS, ValidatorOptions(docs_path=str(docs_path))) - if metadata: - click.echo(f"{metadata_file_path} is a valid ConnectorMetadataDefinitionV0 YAML file.") - else: - click.echo(f"{metadata_file_path} is not a valid ConnectorMetadataDefinitionV0 YAML file.") - click.echo(str(error)) - exit(1) - - -@metadata_service.command(help="Upload a metadata YAML file to a GCS bucket.") -@click.argument("metadata-file-path", type=click.Path(exists=True, path_type=pathlib.Path), required=True) -@click.argument("docs-path", type=click.Path(exists=True, path_type=pathlib.Path), required=True) -@click.argument("bucket-name", type=click.STRING, required=True) -@click.option("--prerelease", type=click.STRING, required=False, default=None, help="The prerelease tag of the connector.") -@click.option("--disable-dockerhub-checks", is_flag=True, help="Disable 'image exists on DockerHub' validations.", default=False) -def upload(metadata_file_path: pathlib.Path, docs_path: pathlib.Path, bucket_name: str, prerelease: str, disable_dockerhub_checks: bool): - metadata_file_path = metadata_file_path if not metadata_file_path.is_dir() else metadata_file_path / METADATA_FILE_NAME - validator_opts = ValidatorOptions( - docs_path=str(docs_path), prerelease_tag=prerelease, disable_dockerhub_checks=disable_dockerhub_checks - ) - try: - upload_info = upload_metadata_to_gcs(bucket_name, metadata_file_path, validator_opts) - log_metadata_upload_info(upload_info) - except (ValidationError, FileNotFoundError) as e: - click.secho(f"The metadata file could not be uploaded: {str(e)}", fg="red") - exit(1) - if upload_info.metadata_uploaded: - exit(0) - else: - exit(5) - - -@metadata_service.command(help="Generate and publish a stale metadata report to Slack.") -@click.argument("bucket-name", type=click.STRING, required=True) -def publish_stale_metadata_report(bucket_name: str): - click.echo(f"Starting stale metadata report for bucket: {bucket_name}") - logger.debug("Starting stale metadata report generation and publishing process") - try: - report_published, error_message = generate_and_publish_stale_metadata_report(bucket_name) - if not report_published: - logger.warning(f"Failed to publish the report to Slack: '{error_message}'.") - click.secho(f"WARNING: The stale metadata report could not be published: '{error_message}'", fg="red") - exit(1) - else: - click.secho(f"Stale metadata report for bucket: {bucket_name} completed successfully", fg="green") - logger.debug("Stale metadata report generation and publishing process completed.") - except Exception as e: - logger.exception(f"A fatal error occurred when generating and publishing the stale metadata report") - click.secho(f"FATAL ERROR: The stale metadata report could not be published: '{e}'", fg="red") - exit(1) - - -@metadata_service.command(help="Rollback a release candidate by deleting its metadata files from a GCS bucket.") -@click.argument("connector-docker-repository", type=click.STRING) -@click.argument("connector-version", type=click.STRING) -@click.argument("bucket-name", type=click.STRING) -def rollback_release_candidate(connector_docker_repository: str, connector_version: str, bucket_name: str): - try: - deletion_info = delete_release_candidate_from_gcs(bucket_name, connector_docker_repository, connector_version) - log_metadata_deletion_info(deletion_info) - except (FileNotFoundError, ValueError) as e: - click.secho(f"The release candidate could not be deleted: {str(e)}", fg="red") - exit(1) - - -@metadata_service.command(help="Promote a release candidate by moving its metadata files to the main release folder in a GCS bucket.") -@click.argument("connector-docker-repository", type=click.STRING) -@click.argument("connector-version", type=click.STRING) -@click.argument("bucket-name", type=click.STRING) -def promote_release_candidate(connector_docker_repository: str, connector_version: str, bucket_name: str): - try: - upload_info, deletion_info = promote_release_candidate_in_gcs(bucket_name, connector_docker_repository, connector_version) - log_metadata_upload_info(upload_info) - log_metadata_deletion_info(deletion_info) - except (FileNotFoundError, ValueError) as e: - click.secho(f"The release candidate could not be promoted: {str(e)}", fg="red") - exit(1) - - -@metadata_service.command(help="Generate the cloud registry and persist it to GCS.") -@click.argument("bucket-name", type=click.STRING, required=True) -@click.argument("registry-type", type=click.Choice(VALID_REGISTRIES), required=True) -@sentry_sdk.trace -def generate_connector_registry(bucket_name: str, registry_type: str): - # Set Sentry context for the generate_registry command - sentry_sdk.set_tag("command", "generate_registry") - sentry_sdk.set_tag("bucket_name", bucket_name) - sentry_sdk.set_tag("registry_type", registry_type) - - logger.info(f"Starting {registry_type} registry generation and upload process.") - try: - generate_and_persist_connector_registry(bucket_name, registry_type) - logger.info(f"SUCCESS: {registry_type} registry generation and upload process completed successfully.") - sentry_sdk.set_tag("operation_success", True) - except Exception as e: - sentry_sdk.set_tag("operation_success", False) - sentry_sdk.capture_exception(e) - logger.exception(f"FATAL ERROR: An error occurred when generating and persisting the {registry_type} registry") - exit(1) - - -@metadata_service.command(help="Generate the specs secrets mask and persist it to GCS.") -@click.argument("bucket-name", type=click.STRING, required=True) -@sentry_sdk.trace -def generate_specs_secrets_mask(bucket_name: str): - # Set Sentry context for the generate_specs_secrets_mask command - sentry_sdk.set_tag("command", "generate_specs_secrets_mask") - sentry_sdk.set_tag("bucket_name", bucket_name) - - logger.info("Starting specs secrets mask generation and upload process.") - try: - generate_and_persist_specs_secrets_mask(bucket_name) - sentry_sdk.set_tag("operation_success", True) - logger.info("Specs secrets mask generation and upload process completed successfully.") - except Exception as e: - sentry_sdk.set_tag("operation_success", False) - sentry_sdk.capture_exception(e) - logger.exception(f"FATAL ERROR: An error occurred when generating and persisting the specs secrets mask") - exit(1) - - -@metadata_service.command(help="Generate the registry entry and persist it to GCS.") -@click.option("--bucket-name", type=click.STRING, required=True) -@click.option("--metadata-file-path", type=click.STRING, required=True) -@click.option("--registry-type", type=click.Choice(VALID_REGISTRIES), required=True) -@click.option("--docker-image-tag", type=click.STRING, required=True) -@click.option( - "--pre-release/--main-release", type=bool, is_flag=True, required=True, help="Whether this is a prerelease or mainrelease publish." -) -@sentry_sdk.trace -def generate_registry_entry( - bucket_name: str, metadata_file_path: pathlib.Path, registry_type: str, docker_image_tag: str, pre_release: bool -): - # Set Sentry context for the generate_registry_entry command - sentry_sdk.set_tag("command", "generate_registry_entry") - sentry_sdk.set_tag("bucket_name", bucket_name) - - logger.info("Starting registry entry generation and upload process.") - try: - generate_and_persist_registry_entry(bucket_name, metadata_file_path, registry_type, docker_image_tag, pre_release) - sentry_sdk.set_tag("operation_success", True) - logger.info("Registry entry generation and upload process completed successfully.") - except Exception as e: - sentry_sdk.set_tag("operation_success", False) - sentry_sdk.capture_exception(e) - logger.exception(f"FATAL ERROR: An error occurred when generating and persisting the registry entry") - exit(1) - - -@metadata_service.command(help="Generate the registry report and persist it to GCS.") -@click.argument("bucket-name", type=click.STRING, required=True) -@sentry_sdk.trace -def generate_registry_report(bucket_name: str): - # Set Sentry context for the generate_specs_secrets_mask command - sentry_sdk.set_tag("command", "generate_registry_report") - sentry_sdk.set_tag("bucket_name", bucket_name) - - logger.info("Starting registry report generation and upload process.") - try: - generate_and_persist_registry_report(bucket_name) - sentry_sdk.set_tag("operation_success", True) - logger.info("Registry report generation and upload process completed successfully.") - except Exception as e: - sentry_sdk.set_tag("operation_success", False) - sentry_sdk.capture_exception(e) - logger.exception(f"FATAL ERROR: An error occurred when generating and persisting the registry report") - exit(1) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/constants.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/constants.py deleted file mode 100644 index da78f9620709..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/constants.py +++ /dev/null @@ -1,65 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -import datetime -from typing import Optional - -CONNECTORS_PATH = "airbyte-integrations/connectors" -METADATA_FILE_NAME = "metadata.yaml" -MANIFEST_FILE_NAME = "manifest.yaml" -COMPONENTS_PY_FILE_NAME = "components.py" -ICON_FILE_NAME = "icon.svg" -METADATA_FOLDER = "metadata" -DOCS_FOLDER_PATH = "docs/integrations" -DOC_FILE_NAME = "doc.md" -DOC_INAPP_FILE_NAME = "doc.inapp.md" -COMPONENTS_ZIP_FILE_NAME = "components.zip" -COMPONENTS_ZIP_SHA256_FILE_NAME = "components.zip.sha256" -LATEST_GCS_FOLDER_NAME = "latest" -RELEASE_CANDIDATE_GCS_FOLDER_NAME = "release_candidate" -METADATA_CDN_BASE_URL = "https://connectors.airbyte.com/files" -DEFAULT_ASSET_URL = "https://storage.googleapis.com" - -VALID_REGISTRIES = ["oss", "cloud"] -REGISTRIES_FOLDER = "registries/v0" -ANALYTICS_BUCKET = "ab-analytics-connector-metrics" -ANALYTICS_FOLDER = "data/connector_quality_metrics" -PUBLIC_GCS_BASE_URL = "https://storage.googleapis.com/" - -VALID_REGISTRIES = ["oss", "cloud"] -REGISTRIES_FOLDER = "registries/v0" -ANALYTICS_BUCKET = "ab-analytics-connector-metrics" -ANALYTICS_FOLDER = "data/connector_quality_metrics" -PUBLIC_GCS_BASE_URL = "https://storage.googleapis.com/" - -GITHUB_REPO_NAME = "airbytehq/airbyte" -EXTENSIBILITY_TEAM_SLACK_TEAM_ID = "S08SQDL2RS9" # @oc-extensibility-critical-systems -STALE_REPORT_CHANNEL = "C05507UP11A" # #dev-connectors-extensibility-alerts -PUBLISH_UPDATE_CHANNEL = "C056HGD1QSW" # #connector-publish-updates -# We give 6 hours for the metadata to be updated -# This is an empirical value that we can adjust if needed -# When our auto-merge pipeline runs it can merge hundreds of up-to-date PRs following. -# Given our current publish concurrency of 10 runners, it can take up to 6 hours to publish all the connectors. -# A shorter grace period could lead to false positives in stale metadata detection. -PUBLISH_GRACE_PERIOD = datetime.timedelta(hours=6) -SLACK_NOTIFICATIONS_ENABLED = "true" - -SPECS_SECRETS_MASK_FILE_NAME = "specs_secrets_mask.yaml" - -CONNECTOR_DEPENDENCY_FOLDER = "connector_dependencies" -CONNECTOR_DEPENDENCY_FILE_NAME = "dependencies.json" - - -def get_public_url_for_gcs_file(bucket_name: str, file_path: str, cdn_url: Optional[str] = None) -> str: - """Get the public URL to a file in the GCS bucket. - - Args: - bucket_name: The name of the GCS bucket. - file_path: The path to the file in the bucket. - cdn_url: The base URL of the CDN that serves the bucket. - - Returns: - The public URL to the file. - """ - return f"{cdn_url}/{file_path}" if cdn_url else f"{DEFAULT_ASSET_URL}/{bucket_name}/{file_path}" diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/docker_hub.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/docker_hub.py deleted file mode 100644 index 924319ebff32..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/docker_hub.py +++ /dev/null @@ -1,137 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import os -import time -from typing import Dict, Optional - -import requests - - -def get_docker_hub_auth_token() -> str: - docker_username = os.environ.get("DOCKER_HUB_USERNAME") - docker_password = os.environ.get("DOCKER_HUB_PASSWORD") - - if not (docker_username and docker_password): - raise ValueError("Please set the DOCKER_HUB_USERNAME and DOCKER_HUB_PASSWORD environment variables.") - - auth_url = "https://hub.docker.com/v2/users/login/" - auth_data = {"username": docker_username, "password": docker_password} - # make request look like docker client to avoid cloudflare blocks in CI - headers = {"User-Agent": "Docker-Client/24.0.0 (linux)"} - response = requests.post(auth_url, json=auth_data, headers=headers) - - if response.status_code != 200: - print(f"Failed to log in to Docker Hub - {response.status_code}: {response.text}") - raise ValueError("Failed to authenticate with Docker Hub. Please check your credentials.") - - token = response.json().get("token") - return token - - -def get_docker_hub_headers() -> Dict | None: - if not os.environ.get("DOCKER_HUB_USERNAME") or not os.environ.get("DOCKER_HUB_PASSWORD"): - # If the Docker Hub credentials are not provided (or are empty), we can only anonymously call the Docker Hub API. - # This will only work for public images and lead to a lower rate limit. - return {} - else: - token = get_docker_hub_auth_token() - return {"Authorization": f"JWT {token}"} if token else {} - - -def get_docker_hub_tags_and_digests( - image_name: str, - retries: int = 0, - wait_sec: int = 30, - next_page_url: str | None = None, - tags_and_digests: Dict[str, str] | None = None, - paginate: bool = True, -) -> Dict[str, str]: - """Find all released tags and digests for an image. - - Args: - image_name (str): The image name to get tags and digest - retries (int, optional): The number of times to retry the request. Defaults to 0. - wait_sec (int, optional): The number of seconds to wait between retries. Defaults to 30. - next_page_url (str | None, optional): The next DockerHub page to consume. Defaults to None. - tags_and_digest (Dict[str, str] | None, optional): The accumulated tags and digests for recursion. Defaults to None. - - Returns: - Dict[str, str]: Mapping of image tag to digest - """ - headers = get_docker_hub_headers() - tags_and_digests = tags_and_digests or {} - - if not next_page_url: - tags_url = f"https://registry.hub.docker.com/v2/repositories/{image_name}/tags" - else: - tags_url = next_page_url - - # Allow for retries as the DockerHub API is not always reliable with returning the latest publish. - for _ in range(retries + 1): - response = requests.get(tags_url, headers=headers) - if response.ok: - break - - # This is to handle the case when a connector has not ever been released yet. - if response.status_code == 404: - print(f"{tags_url} returned a 404. The connector might not be released yet.") - print(response) - return tags_and_digests - time.sleep(wait_sec) - - response.raise_for_status() - json_response = response.json() - tags_and_digests.update({result["name"]: result.get("digest") for result in json_response.get("results", [])}) - if paginate: - if next_page_url := json_response.get("next"): - tags_and_digests.update( - get_docker_hub_tags_and_digests( - image_name, retries=retries, wait_sec=wait_sec, next_page_url=next_page_url, tags_and_digests=tags_and_digests - ) - ) - return tags_and_digests - - -def get_latest_version_on_dockerhub(image_name: str) -> str | None: - tags_and_digests = get_docker_hub_tags_and_digests(image_name, retries=3, wait_sec=30) - if latest_digest := tags_and_digests.get("latest"): - for tag, digest in tags_and_digests.items(): - if digest == latest_digest and tag != "latest": - return tag - return None - - -def is_image_on_docker_hub(image_name: str, version: str, digest: Optional[str] = None, retries: int = 0, wait_sec: int = 30) -> bool: - """Check if a given image and version exists on Docker Hub. - - Args: - image_name (str): The name of the image to check. - version (str): The version of the image to check. - digest (str, optional): The digest of the image to check. Defaults to None. - retries (int, optional): The number of times to retry the request. Defaults to 0. - wait_sec (int, optional): The number of seconds to wait between retries. Defaults to 30. - Returns: - bool: True if the image and version exists on Docker Hub, False otherwise. - """ - - headers = get_docker_hub_headers() - - tag_url = f"https://registry.hub.docker.com/v2/repositories/{image_name}/tags/{version}" - - # Allow for retries as the DockerHub API is not always reliable with returning the latest publish. - for _ in range(retries + 1): - response = requests.get(tag_url, headers=headers) - if response.ok: - break - time.sleep(wait_sec) - - if not response.ok: - response.raise_for_status() - return False - - # If a digest is provided, check that it matches the digest of the image on Docker Hub. - if digest is not None: - return f"sha256:{digest}" == response.json()["digest"] - return True diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/gcs_upload.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/gcs_upload.py deleted file mode 100644 index c555ba2e13cf..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/gcs_upload.py +++ /dev/null @@ -1,679 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import logging -import re -import tempfile -from dataclasses import dataclass -from pathlib import Path -from typing import List, NamedTuple, Optional, Tuple - -import git -import requests -import yaml -from google.cloud import storage -from pydash import set_ -from pydash.objects import get - -from metadata_service.constants import ( - COMPONENTS_PY_FILE_NAME, - COMPONENTS_ZIP_FILE_NAME, - COMPONENTS_ZIP_SHA256_FILE_NAME, - DOC_FILE_NAME, - DOC_INAPP_FILE_NAME, - ICON_FILE_NAME, - LATEST_GCS_FOLDER_NAME, - MANIFEST_FILE_NAME, - METADATA_FILE_NAME, - METADATA_FOLDER, - RELEASE_CANDIDATE_GCS_FOLDER_NAME, -) -from metadata_service.helpers.files import compute_gcs_md5, create_zip_and_get_sha256 -from metadata_service.helpers.gcs import get_gcs_storage_client -from metadata_service.models.generated.ConnectorMetadataDefinitionV0 import ConnectorMetadataDefinitionV0 -from metadata_service.models.generated.GitInfo import GitInfo -from metadata_service.models.transform import to_json_sanitized_dict -from metadata_service.validators.metadata_validator import POST_UPLOAD_VALIDATORS, ValidatorOptions, validate_and_load - -# 🧩 TYPES - - -@dataclass(frozen=True) -class UploadedFile: - id: str - uploaded: bool - blob_id: Optional[str] - - -@dataclass(frozen=True) -class DeletedFile: - id: str - deleted: bool - description: str - blob_id: Optional[str] - - -@dataclass(frozen=True) -class MetadataUploadInfo: - metadata_uploaded: bool - metadata_file_path: str - uploaded_files: List[UploadedFile] - - -@dataclass(frozen=True) -class MetadataDeleteInfo: - metadata_deleted: bool - deleted_files: List[DeletedFile] - - -class MaybeUpload(NamedTuple): - uploaded: bool - blob_id: str - - -@dataclass -class ManifestOnlyFilePaths: - zip_file_path: Path | None - sha256_file_path: Path | None - sha256: str | None - manifest_file_path: Path - - -# 🛣️ FILES AND PATHS - - -def get_doc_local_file_path(docs_path: Path, inapp: bool) -> Optional[Path]: - extension = ".inapp.md" if inapp else ".md" - return docs_path.with_suffix(extension) - - -def get_manifest_only_file_paths(working_directory: Path) -> ManifestOnlyFilePaths: - """Create a zip file for components if they exist and return its SHA256 hash.""" - yaml_manifest_file_path = working_directory / MANIFEST_FILE_NAME - components_py_file_path = working_directory / COMPONENTS_PY_FILE_NAME - - if not components_py_file_path.exists(): - return ManifestOnlyFilePaths( - zip_file_path=None, - sha256_file_path=None, - sha256=None, - manifest_file_path=yaml_manifest_file_path, - ) - - with ( - tempfile.NamedTemporaryFile(mode="wb", suffix=".zip", delete=False) as zip_tmp_file, - tempfile.NamedTemporaryFile(mode="w", suffix=".sha256", delete=False) as sha256_tmp_file, - ): - python_components_zip_file_path = Path(zip_tmp_file.name) - python_components_zip_sha256_file_path = Path(sha256_tmp_file.name) - - files_to_zip: List[Path] = [components_py_file_path, yaml_manifest_file_path] - components_zip_sha256 = create_zip_and_get_sha256(files_to_zip, python_components_zip_file_path) - sha256_tmp_file.write(components_zip_sha256) - - return ManifestOnlyFilePaths( - zip_file_path=python_components_zip_file_path, - sha256_file_path=python_components_zip_sha256_file_path, - sha256=components_zip_sha256, - manifest_file_path=yaml_manifest_file_path, - ) - - -def _write_metadata_to_tmp_file(metadata_dict: dict) -> Path: - """Write the metadata to a temporary file.""" - with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as tmp_file: - yaml.dump(metadata_dict, tmp_file) - return Path(tmp_file.name) - - -# 🛠️ HELPERS - - -def _safe_load_metadata_file(metadata_file_path: Path) -> dict: - try: - metadata = yaml.safe_load(metadata_file_path.read_text()) - if metadata is None or not isinstance(metadata, dict): - raise ValueError(f"Validation error: Metadata file {metadata_file_path} is invalid yaml.") - return metadata - except Exception as e: - raise ValueError(f"Validation error: Metadata file {metadata_file_path} is invalid yaml: {e}") - - -def _any_uploaded(uploaded_files: List[UploadedFile], keys: List[str]) -> bool: - """Check if the list of uploaded files contains any of the provided keys.""" - for uploaded_file in uploaded_files: - if uploaded_file.id in keys: - return True - return False - - -def _commit_to_git_info(commit: git.Commit) -> GitInfo: - return GitInfo( - commit_sha=commit.hexsha, - commit_timestamp=commit.authored_datetime, - commit_author=commit.author.name, - commit_author_email=commit.author.email, - ) - - -def _get_git_info_for_file(original_metadata_file_path: Path) -> Optional[GitInfo]: - """ - Add additional information to the metadata file before uploading it to GCS. - - e.g. The git commit hash, the date of the commit, the author of the commit, etc. - - """ - try: - repo = git.Repo(search_parent_directories=True) - - # get the commit hash for the last commit that modified the metadata file - commit_sha = repo.git.log("-1", "--format=%H", str(original_metadata_file_path)) - - commit = repo.commit(commit_sha) - return _commit_to_git_info(commit) - except git.exc.InvalidGitRepositoryError: - logging.warning(f"Metadata file {original_metadata_file_path} is not in a git repository, skipping author info attachment.") - return None - except git.exc.GitCommandError as e: - if "unknown revision or path not in the working tree" in str(e): - logging.warning(f"Metadata file {original_metadata_file_path} is not tracked by git, skipping author info attachment.") - return None - else: - raise e - - -# 🚀 UPLOAD - - -def _save_blob_to_gcs(blob_to_save: storage.blob.Blob, file_path: Path, disable_cache: bool = False) -> bool: - """Uploads a file to the bucket.""" - print(f"Uploading {file_path} to {blob_to_save.name}...") - - # Set Cache-Control header to no-cache to avoid caching issues - # This is IMPORTANT because if we don't set this header, the metadata file will be cached by GCS - # and the next time we try to download it, we will get the stale version - if disable_cache: - blob_to_save.cache_control = "no-cache" - - blob_to_save.upload_from_filename(file_path) - - return True - - -def upload_file_if_changed( - local_file_path: Path, bucket: storage.bucket.Bucket, blob_path: str, disable_cache: bool = False -) -> MaybeUpload: - """Upload a file to GCS if it has changed.""" - local_file_md5_hash = compute_gcs_md5(local_file_path) - remote_blob = bucket.blob(blob_path) - - # reload the blob to get the md5_hash - if remote_blob.exists(): - remote_blob.reload() - - remote_blob_md5_hash = remote_blob.md5_hash if remote_blob.exists() else None - - print(f"Local {local_file_path} md5_hash: {local_file_md5_hash}") - print(f"Remote {blob_path} md5_hash: {remote_blob_md5_hash}") - - if local_file_md5_hash != remote_blob_md5_hash: - uploaded = _save_blob_to_gcs(remote_blob, local_file_path, disable_cache=disable_cache) - return MaybeUpload(uploaded, remote_blob.id) - - return MaybeUpload(False, remote_blob.id) - - -def _file_upload( - local_path: Path | None, - gcp_connector_dir: str, - bucket: storage.bucket.Bucket, - file_key: str, - *, - upload_as_version: bool, - upload_as_latest: bool, - skip_if_not_exists: bool = True, - disable_cache: bool = False, - version_folder: Optional[str] = None, - override_destination_file_name: str | None = None, -) -> tuple[UploadedFile, UploadedFile]: - """Upload a file to GCS. - - Optionally upload it as a versioned file and/or as the latest version. - - Args: - local_path: Path to the file to upload. - gcp_connector_dir: Path to the connector folder in GCS. This is the parent folder, - containing the versioned and "latest" folders as its subdirectories. - bucket: GCS bucket to upload the file to. - upload_as_version: The version to upload the file as or 'False' to skip uploading - the versioned copy. - upload_as_latest: Whether to upload the file as the latest version. - skip_if_not_exists: Whether to skip the upload if the file does not exist. Otherwise, - an exception will be raised if the file does not exist. - - Returns: Tuple of two UploadInfo objects, each containing a boolean indicating whether the file was - uploaded, the blob id, and the description. The first tuple is for the versioned file, the second for the - latest file. - """ - if upload_as_version and not version_folder: - raise ValueError("version_folder must be provided if upload_as_version is True") - - latest_file_key = f"latest_{file_key}" - versioned_file_key = f"versioned_{file_key}" - versioned_file_info = UploadedFile(id=versioned_file_key, uploaded=False, blob_id=None) - latest_file_info = UploadedFile(id=latest_file_key, uploaded=False, blob_id=None) - if not local_path or not local_path.exists(): - msg = f"Expected to find file at {local_path}, but none was found." - if skip_if_not_exists: - logging.warning(msg) - return versioned_file_info, latest_file_info - - raise FileNotFoundError(msg) - - file_name = local_path.name if override_destination_file_name is None else override_destination_file_name - - if upload_as_version: - remote_upload_path = f"{gcp_connector_dir}/{version_folder}" - versioned_uploaded, versioned_blob_id = upload_file_if_changed( - local_file_path=local_path, - bucket=bucket, - blob_path=f"{remote_upload_path}/{file_name}", - disable_cache=disable_cache, - ) - versioned_file_info = UploadedFile(id=versioned_file_key, uploaded=versioned_uploaded, blob_id=versioned_blob_id) - - if upload_as_latest: - remote_upload_path = f"{gcp_connector_dir}/{LATEST_GCS_FOLDER_NAME}" - latest_uploaded, latest_blob_id = upload_file_if_changed( - local_file_path=local_path, - bucket=bucket, - blob_path=f"{remote_upload_path}/{file_name}", - disable_cache=disable_cache, - ) - latest_file_info = UploadedFile(id=latest_file_key, uploaded=latest_uploaded, blob_id=latest_blob_id) - - return versioned_file_info, latest_file_info - - -# 🔧 METADATA MODIFICATIONS - - -def _apply_prerelease_overrides(metadata_dict: dict, validator_opts: ValidatorOptions) -> dict: - """Apply any prerelease overrides to the metadata file before uploading it to GCS.""" - if validator_opts.prerelease_tag is None: - return metadata_dict - - # replace any dockerImageTag references with the actual tag - # this includes metadata.data.dockerImageTag, metadata.data.registryOverrides[].dockerImageTag - # where registries is a dictionary of registry name to registry object - metadata_dict["data"]["dockerImageTag"] = validator_opts.prerelease_tag - for registry in get(metadata_dict, "data.registryOverrides", {}).values(): - if "dockerImageTag" in registry: - registry["dockerImageTag"] = validator_opts.prerelease_tag - - return metadata_dict - - -def _apply_author_info_to_metadata_file(metadata_dict: dict, original_metadata_file_path: Path) -> dict: - """Apply author info to the metadata file before uploading it to GCS.""" - git_info = _get_git_info_for_file(original_metadata_file_path) - if git_info: - # Apply to the nested / optional field at metadata.data.generated.git - git_info_dict = to_json_sanitized_dict(git_info, exclude_none=True) - metadata_dict = set_(metadata_dict, "data.generated.git", git_info_dict) - return metadata_dict - - -def _apply_python_components_sha_to_metadata_file( - metadata_dict: dict, - python_components_sha256: Optional[str] = None, -) -> dict: - """If a `components.py` file is required, store the necessary information in the metadata. - - This adds a `required=True` flag and the sha256 hash of the `python_components.zip` file. - - This is a no-op if `python_components_sha256` is not provided. - """ - if python_components_sha256: - metadata_dict = set_(metadata_dict, "data.generated.pythonComponents.required", True) - metadata_dict = set_( - metadata_dict, - "data.generated.pythonComponents.sha256", - python_components_sha256, - ) - - return metadata_dict - - -def _apply_sbom_url_to_metadata_file(metadata_dict: dict) -> dict: - """Apply sbom url to the metadata file before uploading it to GCS.""" - try: - sbom_url = f"https://connectors.airbyte.com/files/sbom/{metadata_dict['data']['dockerRepository']}/{metadata_dict['data']['dockerImageTag']}.spdx.json" - except KeyError: - return metadata_dict - response = requests.head(sbom_url) - if response.ok: - metadata_dict = set_(metadata_dict, "data.generated.sbomUrl", sbom_url) - return metadata_dict - - -def _apply_modifications_to_metadata_file( - original_metadata_file_path: Path, - validator_opts: ValidatorOptions, - components_zip_sha256: str | None = None, -) -> Path: - """Apply modifications to the metadata file before uploading it to GCS. - - e.g. The git commit hash, the date of the commit, the author of the commit, etc. - - Args: - original_metadata_file_path (Path): Path to the original metadata file. - validator_opts (ValidatorOptions): Options to use when validating the metadata file. - components_zip_sha256 (str): The sha256 hash of the `python_components.zip` file. This is - required if the `python_components.zip` file is present. - """ - metadata = _safe_load_metadata_file(original_metadata_file_path) - metadata = _apply_prerelease_overrides(metadata, validator_opts) - metadata = _apply_author_info_to_metadata_file(metadata, original_metadata_file_path) - metadata = _apply_python_components_sha_to_metadata_file(metadata, components_zip_sha256) - metadata = _apply_sbom_url_to_metadata_file(metadata) - return _write_metadata_to_tmp_file(metadata) - - -# 💎 Main Logic - - -def upload_metadata_to_gcs(bucket_name: str, metadata_file_path: Path, validator_opts: ValidatorOptions) -> MetadataUploadInfo: - """Upload a metadata file to a GCS bucket. - - If the per 'version' key already exists it won't be overwritten. - Also updates the 'latest' key on each new version. - - Args: - bucket_name (str): Name of the GCS bucket to which the metadata file will be uploade. - metadata_file_path (Path): Path to the metadata file. - service_account_file_path (Path): Path to the JSON file with the service account allowed to read and write on the bucket. - prerelease_tag (Optional[str]): Whether the connector is a prerelease_tag or not. - Returns: - Tuple[bool, str]: Whether the metadata file was uploaded and its blob id. - """ - # Get our working directory - working_directory = metadata_file_path.parent - manifest_only_file_info = get_manifest_only_file_paths(working_directory) - - metadata_file_path = _apply_modifications_to_metadata_file( - original_metadata_file_path=metadata_file_path, - validator_opts=validator_opts, - components_zip_sha256=manifest_only_file_info.sha256, - ) - - metadata, error = validate_and_load(metadata_file_path, POST_UPLOAD_VALIDATORS, validator_opts) - if metadata is None: - raise ValueError(f"Metadata file {metadata_file_path} is invalid for uploading: {error}") - - is_pre_release = validator_opts.prerelease_tag is not None - is_release_candidate = "-rc" in metadata.data.dockerImageTag - should_upload_release_candidate = is_release_candidate and not is_pre_release - should_upload_latest = not is_release_candidate and not is_pre_release - - storage_client = get_gcs_storage_client() - bucket = storage_client.bucket(bucket_name) - docs_path = Path(validator_opts.docs_path) - gcp_connector_dir = f"{METADATA_FOLDER}/{metadata.data.dockerRepository}" - - # Upload version metadata and doc - # If the connector is a pre-release, we use the pre-release tag as the version - # Otherwise, we use the dockerImageTag from the metadata - version_folder = metadata.data.dockerImageTag if not is_pre_release else validator_opts.prerelease_tag - - # Start uploading files - uploaded_files = [] - - # Metadata upload - metadata_files_uploaded = _file_upload( - file_key="metadata", - local_path=metadata_file_path, - gcp_connector_dir=gcp_connector_dir, - bucket=bucket, - version_folder=version_folder, - upload_as_version=True, - upload_as_latest=should_upload_latest, - disable_cache=True, - override_destination_file_name=METADATA_FILE_NAME, - ) - uploaded_files.extend(metadata_files_uploaded) - - # Release candidate upload - # We just upload the current metadata to the "release_candidate" path - # The doc and inapp doc are not uploaded, which means that the release candidate will still point to the latest doc - if should_upload_release_candidate: - release_candidate_files_uploaded = _file_upload( - file_key="release_candidate", - local_path=metadata_file_path, - gcp_connector_dir=gcp_connector_dir, - bucket=bucket, - version_folder=RELEASE_CANDIDATE_GCS_FOLDER_NAME, - upload_as_version=True, - upload_as_latest=False, - disable_cache=True, - override_destination_file_name=METADATA_FILE_NAME, - ) - uploaded_files.extend(release_candidate_files_uploaded) - - # Icon upload - - icon_files_uploaded = _file_upload( - file_key="icon", - local_path=working_directory / ICON_FILE_NAME, - gcp_connector_dir=gcp_connector_dir, - bucket=bucket, - upload_as_version=False, - upload_as_latest=should_upload_latest, - ) - uploaded_files.extend(icon_files_uploaded) - - # Doc upload - - local_doc_path = get_doc_local_file_path(docs_path, inapp=False) - doc_files_uploaded = _file_upload( - file_key="doc", - local_path=local_doc_path, - gcp_connector_dir=gcp_connector_dir, - bucket=bucket, - upload_as_version=True, - version_folder=version_folder, - upload_as_latest=should_upload_latest, - override_destination_file_name=DOC_FILE_NAME, - ) - uploaded_files.extend(doc_files_uploaded) - - local_inapp_doc_path = get_doc_local_file_path(docs_path, inapp=True) - inapp_doc_files_uploaded = _file_upload( - file_key="inapp_doc", - local_path=local_inapp_doc_path, - gcp_connector_dir=gcp_connector_dir, - bucket=bucket, - upload_as_version=True, - version_folder=version_folder, - upload_as_latest=should_upload_latest, - override_destination_file_name=DOC_INAPP_FILE_NAME, - ) - uploaded_files.extend(inapp_doc_files_uploaded) - - # Manifest and components upload - - manifest_files_uploaded = _file_upload( - file_key="manifest", - local_path=manifest_only_file_info.manifest_file_path, - gcp_connector_dir=gcp_connector_dir, - bucket=bucket, - upload_as_version=True, - version_folder=version_folder, - upload_as_latest=should_upload_latest, - override_destination_file_name=MANIFEST_FILE_NAME, - ) - uploaded_files.extend(manifest_files_uploaded) - - components_zip_sha256_files_uploaded = _file_upload( - file_key="components_zip_sha256", - local_path=manifest_only_file_info.sha256_file_path, - gcp_connector_dir=gcp_connector_dir, - bucket=bucket, - upload_as_version=True, - version_folder=version_folder, - upload_as_latest=should_upload_latest, - override_destination_file_name=COMPONENTS_ZIP_SHA256_FILE_NAME, - ) - uploaded_files.extend(components_zip_sha256_files_uploaded) - - components_zip_files_uploaded = _file_upload( - file_key="components_zip", - local_path=manifest_only_file_info.zip_file_path, - gcp_connector_dir=gcp_connector_dir, - bucket=bucket, - upload_as_version=True, - version_folder=version_folder, - upload_as_latest=should_upload_latest, - override_destination_file_name=COMPONENTS_ZIP_FILE_NAME, - ) - uploaded_files.extend(components_zip_files_uploaded) - - return MetadataUploadInfo( - uploaded_files=uploaded_files, - metadata_file_path=str(metadata_file_path), - metadata_uploaded=_any_uploaded( - uploaded_files, - [ - "latest_metadata", - "version_metadata", - "version_release_candidate", - ], - ), - ) - - -def delete_release_candidate_from_gcs(bucket_name: str, docker_repository: str, connector_version: str) -> MetadataDeleteInfo: - """ - Delete a release candidate from a GCS bucket. - The release candidate and version metadata file will be deleted. - We first check that the release candidate metadata file hash matches the version metadata file hash. - Args: - bucket_name (str): Name of the GCS bucket from which the release candidate will be deleted. - docker_repository (str): Name of the connector docker image. - connector_version (str): Version of the connector. - Returns: - MetadataDeleteInfo: Information about the files that were deleted. - """ - storage_client = get_gcs_storage_client() - bucket = storage_client.bucket(bucket_name) - - gcp_connector_dir = f"{METADATA_FOLDER}/{docker_repository}" - version_path = f"{gcp_connector_dir}/{connector_version}/{METADATA_FILE_NAME}" - rc_path = f"{gcp_connector_dir}/{RELEASE_CANDIDATE_GCS_FOLDER_NAME}/{METADATA_FILE_NAME}" - - version_blob = bucket.blob(version_path) - rc_blob = bucket.blob(rc_path) - - if not version_blob.exists(): - raise FileNotFoundError(f"Version metadata file {version_path} does not exist in the bucket. ") - if not rc_blob.exists(): - raise FileNotFoundError(f"Release candidate metadata file {rc_path} does not exist in the bucket. ") - if rc_blob.md5_hash != version_blob.md5_hash: - raise ValueError( - f"Release candidate metadata file {rc_path} hash does not match the version metadata file {version_path} hash. Unsafe to delete. Please check the Remote Release Candidate to confirm its the version you would like to remove and rerun with --force" - ) - - deleted_files = [] - rc_blob.delete() - deleted_files.append( - DeletedFile( - id="release_candidate_metadata", - deleted=True, - description="release candidate metadata", - blob_id=rc_blob.id, - ) - ) - version_blob.delete() - deleted_files.append( - DeletedFile( - id="version_metadata", - deleted=True, - description="versioned metadata", - blob_id=version_blob.id, - ) - ) - - return MetadataDeleteInfo( - metadata_deleted=True, - deleted_files=deleted_files, - ) - - -def promote_release_candidate_in_gcs( - bucket_name: str, docker_repository: str, connector_version: str -) -> Tuple[MetadataUploadInfo, MetadataDeleteInfo]: - """Promote a release candidate to the latest version in a GCS bucket. - The release candidate metadata file will be copied to the latest metadata file and then deleted. - We first check that the release candidate metadata file hash matches the version metadata file hash. - Args: - bucket_name (str): Name of the GCS bucket from which the release candidate will be deleted. - docker_repository (str): Name of the connector docker image. - connector_version (str): Version of the connector. - Returns: - Tuple[MetadataUploadInfo, MetadataDeleteInfo]: Information about the files that were uploaded (new latest version) and deleted (release candidate). - """ - - storage_client = get_gcs_storage_client() - bucket = storage_client.bucket(bucket_name) - - gcp_connector_dir = f"{METADATA_FOLDER}/{docker_repository}" - version_path = f"{gcp_connector_dir}/{connector_version}/{METADATA_FILE_NAME}" - rc_path = f"{gcp_connector_dir}/{RELEASE_CANDIDATE_GCS_FOLDER_NAME}/{METADATA_FILE_NAME}" - latest_path = f"{gcp_connector_dir}/{LATEST_GCS_FOLDER_NAME}/{METADATA_FILE_NAME}" - - version_blob = bucket.blob(version_path) - latest_blob = bucket.blob(latest_path) - rc_blob = bucket.blob(rc_path) - - if not version_blob.exists(): - raise FileNotFoundError(f"Version metadata file {version_path} does not exist in the bucket.") - if not rc_blob.exists(): - raise FileNotFoundError(f"Release candidate metadata file {rc_path} does not exist in the bucket.") - - if rc_blob.md5_hash != version_blob.md5_hash: - raise ValueError( - f"""Release candidate metadata file {rc_path} hash does not match the version metadata file {version_path} hash. Unsafe to promote. - It's likely that something changed the release candidate hash but have not changed the metadata for the lastest matching version.""" - ) - - uploaded_files = [] - deleted_files = [] - - bucket.copy_blob(rc_blob, bucket, latest_blob) - uploaded_files.append( - UploadedFile( - id="latest_metadata", - uploaded=True, - blob_id=latest_blob.id, - ) - ) - - rc_blob.delete() - deleted_files.append( - DeletedFile( - id="release_candidate_metadata", - deleted=True, - description="release candidate metadata", - blob_id=rc_blob.id, - ) - ) - - return MetadataUploadInfo( - metadata_uploaded=True, - metadata_file_path=str(version_path), - uploaded_files=uploaded_files, - ), MetadataDeleteInfo( - metadata_deleted=True, - deleted_files=deleted_files, - ) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/files.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/files.py deleted file mode 100644 index 680577209fd0..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/files.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -import base64 -import hashlib -import zipfile -from pathlib import Path -from typing import List - - -def compute_gcs_md5(file_name: Path) -> str: - hash_md5 = hashlib.md5() - with Path.open(file_name, "rb") as f: - for chunk in iter(lambda: f.read(4096), b""): - hash_md5.update(chunk) - - return base64.b64encode(hash_md5.digest()).decode("utf8") - - -def compute_sha256(file_name: Path) -> str: - hash_sha256 = hashlib.sha256() - with Path.open(file_name, "rb") as f: - for chunk in iter(lambda: f.read(4096), b""): - hash_sha256.update(chunk) - - return base64.b64encode(hash_sha256.digest()).decode("utf8") - - -def create_zip_and_get_sha256(files_to_zip: List[Path], output_zip_path: Path) -> str: - """Create a zip file from given files and return its SHA256 hash.""" - with zipfile.ZipFile(output_zip_path, "w") as zipf: - for file_path in files_to_zip: - if file_path.exists(): - zipf.write(filename=file_path, arcname=file_path.name) - - zip_sha256 = compute_sha256(output_zip_path) - return zip_sha256 diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/gcs.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/gcs.py deleted file mode 100644 index 89fbc059653e..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/gcs.py +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -import json -import os -from typing import Optional - -from google.cloud import storage -from google.oauth2 import service_account - - -def get_gcs_storage_client(gcs_creds: Optional[str] = None) -> storage.Client: - """Get the GCS storage client using credentials form GCS_CREDENTIALS env variable.""" - gcs_creds = os.environ.get("GCS_CREDENTIALS") if not gcs_creds else gcs_creds - if not gcs_creds: - raise ValueError("Please set the GCS_CREDENTIALS env var.") - - service_account_info = json.loads(gcs_creds) - credentials = service_account.Credentials.from_service_account_info(service_account_info) - return storage.Client(credentials=credentials) - - -def safe_read_gcs_file(gcs_blob: storage.Blob) -> Optional[str]: - """Read the connector metrics jsonl blob. - - Args: - gcs_blob (storage.Blob): The blob. - - Returns: - dict: The metrics. - """ - if not gcs_blob.exists(): - return None - - return gcs_blob.download_as_string().decode("utf-8") diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/object_helpers.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/object_helpers.py deleted file mode 100644 index 96ba5d72b905..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/object_helpers.py +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - - -import copy -from enum import EnumMeta - - -def deep_copy_params(to_call): - def f(*args, **kwargs): - return to_call(*copy.deepcopy(args), **copy.deepcopy(kwargs)) - - return f - - -class CaseInsensitiveKeys(EnumMeta): - """A metaclass for creating enums with case-insensitive keys.""" - - def __getitem__(cls, item): - try: - return super().__getitem__(item) - except Exception: - for key in cls._member_map_: - if key.casefold() == item.casefold(): - return super().__getitem__(key) - - -def default_none_to_dict(value, key, obj): - """Set the value of a key in a dictionary to an empty dictionary if the value is None. - - Useful with pydash's set_with function. - - e.g. set_with(obj, key, value, default_none_to_dict) - - For more information, see https://github.com/dgilland/pydash/issues/122 - - Args: - value: The value to check. - key: The key to set in the dictionary. - obj: The dictionary to set the key in. - """ - if obj is None: - return - - if value is None: - obj[key] = {} diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/slack.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/slack.py deleted file mode 100644 index 977673e20d61..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/helpers/slack.py +++ /dev/null @@ -1,55 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -import logging -import os -from typing import Generator, Optional - -from slack_sdk import WebClient - -from metadata_service.constants import SLACK_NOTIFICATIONS_ENABLED - -logger = logging.getLogger(__name__) - - -def _chunk_messages(message: str) -> Generator[str, None, None]: - """Split message into messages with no more than 3992 chars each. Slack will automatically split any messages that are 4000 chars or more.""" - slack_message_char_limit = 3992 - msg = "" - for line in message.splitlines(): - if len(msg + line + "\n") > slack_message_char_limit: - yield msg - msg += line + "\n" - yield msg - - -def send_slack_message(channel: str, message: str, enable_code_block_wrapping: bool = False) -> tuple[bool, Optional[str]]: - """ - Send a slack message to the given channel. - - Args: - channel (str): The channel to send the message to. - message (str): The message to send. - - Returns: - tuple[bool, str]: (success, error_message) - """ - if (slack_token := os.environ.get("SLACK_TOKEN")) and SLACK_NOTIFICATIONS_ENABLED == "true": - # Ensure that a failure to send a slack message does not cause the pipeline to fail - try: - slack_client = WebClient(token=slack_token) - for message_chunk in _chunk_messages(message): - if enable_code_block_wrapping: - message_chunk = f"```{message_chunk}```" - - slack_client.chat_postMessage(channel=channel, text=message_chunk) - return True, None - except Exception as e: - logger.error(f"Failed to send slack message: {e}") - return False, str(e) - elif not slack_token: - logger.info("Slack token is not set - skipping message send") - else: - logger.info("Slack notifications are disabled - skipping message send") - return True, None diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ActorDefinitionResourceRequirements.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ActorDefinitionResourceRequirements.py deleted file mode 100644 index 1f6e484eef73..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ActorDefinitionResourceRequirements.py +++ /dev/null @@ -1,54 +0,0 @@ -# generated by datamodel-codegen: -# filename: ActorDefinitionResourceRequirements.yaml - -from __future__ import annotations - -from typing import List, Optional - -from pydantic import BaseModel, Extra, Field -from typing_extensions import Literal - - -class ResourceRequirements(BaseModel): - class Config: - extra = Extra.forbid - - cpu_request: Optional[str] = None - cpu_limit: Optional[str] = None - memory_request: Optional[str] = None - memory_limit: Optional[str] = None - - -class JobType(BaseModel): - __root__: Literal[ - "get_spec", - "check_connection", - "discover_schema", - "sync", - "reset_connection", - "connection_updater", - "replicate", - ] = Field( - ..., - description="enum that describes the different types of jobs that the platform runs.", - title="JobType", - ) - - -class JobTypeResourceLimit(BaseModel): - class Config: - extra = Extra.forbid - - jobType: JobType - resourceRequirements: ResourceRequirements - - -class ActorDefinitionResourceRequirements(BaseModel): - class Config: - extra = Extra.forbid - - default: Optional[ResourceRequirements] = Field( - None, - description="if set, these are the requirements that should be set for ALL jobs run for this actor definition.", - ) - jobSpecific: Optional[List[JobTypeResourceLimit]] = None diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/AirbyteInternal.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/AirbyteInternal.py deleted file mode 100644 index 60cd440cc218..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/AirbyteInternal.py +++ /dev/null @@ -1,22 +0,0 @@ -# generated by datamodel-codegen: -# filename: AirbyteInternal.yaml - -from __future__ import annotations - -from typing import Optional - -from pydantic import BaseModel, Extra, Field -from typing_extensions import Literal - - -class AirbyteInternal(BaseModel): - class Config: - extra = Extra.allow - - sl: Optional[Literal[0, 100, 200, 300]] = None - ql: Optional[Literal[0, 100, 200, 300, 400, 500, 600]] = None - isEnterprise: Optional[bool] = False - requireVersionIncrementsInPullRequests: Optional[bool] = Field( - True, - description="When false, version increment checks will be skipped for this connector", - ) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/AllowedHosts.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/AllowedHosts.py deleted file mode 100644 index ce4534f3adca..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/AllowedHosts.py +++ /dev/null @@ -1,18 +0,0 @@ -# generated by datamodel-codegen: -# filename: AllowedHosts.yaml - -from __future__ import annotations - -from typing import List, Optional - -from pydantic import BaseModel, Extra, Field - - -class AllowedHosts(BaseModel): - class Config: - extra = Extra.allow - - hosts: Optional[List[str]] = Field( - None, - description="An array of hosts that this connector can connect to. AllowedHosts not being present for the source or destination means that access to all hosts is allowed. An empty list here means that no network access is granted.", - ) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorBreakingChanges.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorBreakingChanges.py deleted file mode 100644 index b0df13b93210..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorBreakingChanges.py +++ /dev/null @@ -1,65 +0,0 @@ -# generated by datamodel-codegen: -# filename: ConnectorBreakingChanges.yaml - -from __future__ import annotations - -from datetime import date -from typing import Dict, List, Optional - -from pydantic import AnyUrl, BaseModel, Extra, Field, constr -from typing_extensions import Literal - - -class StreamBreakingChangeScope(BaseModel): - class Config: - extra = Extra.forbid - - scopeType: str = Field("stream", const=True) - impactedScopes: List[str] = Field( - ..., - description="List of streams that are impacted by the breaking change.", - min_items=1, - ) - - -class BreakingChangeScope(BaseModel): - __root__: StreamBreakingChangeScope = Field( - ..., - description="A scope that can be used to limit the impact of a breaking change.", - ) - - -class VersionBreakingChange(BaseModel): - class Config: - extra = Extra.forbid - - upgradeDeadline: date = Field( - ..., - description="The deadline by which to upgrade before the breaking change takes effect.", - ) - message: str = Field( - ..., description="Descriptive message detailing the breaking change." - ) - deadlineAction: Optional[Literal["auto_upgrade", "disable"]] = Field( - None, description="Action to do when the deadline is reached." - ) - migrationDocumentationUrl: Optional[AnyUrl] = Field( - None, - description="URL to documentation on how to migrate to the current version. Defaults to ${documentationUrl}-migrations#${version}", - ) - scopedImpact: Optional[List[BreakingChangeScope]] = Field( - None, - description="List of scopes that are impacted by the breaking change. If not specified, the breaking change cannot be scoped to reduce impact via the supported scope types.", - min_items=1, - ) - - -class ConnectorBreakingChanges(BaseModel): - class Config: - extra = Extra.forbid - - __root__: Dict[constr(regex=r"^\d+\.\d+\.\d+$"), VersionBreakingChange] = Field( - ..., - description="Each entry denotes a breaking change in a specific version of a connector that requires user action to upgrade.", - title="ConnectorBreakingChanges", - ) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorBuildOptions.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorBuildOptions.py deleted file mode 100644 index ad7a10d5ab56..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorBuildOptions.py +++ /dev/null @@ -1,15 +0,0 @@ -# generated by datamodel-codegen: -# filename: ConnectorBuildOptions.yaml - -from __future__ import annotations - -from typing import Optional - -from pydantic import BaseModel, Extra - - -class ConnectorBuildOptions(BaseModel): - class Config: - extra = Extra.forbid - - baseImage: Optional[str] = None diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorIPCOptions.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorIPCOptions.py deleted file mode 100644 index 63a5d58f3408..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorIPCOptions.py +++ /dev/null @@ -1,25 +0,0 @@ -# generated by datamodel-codegen: -# filename: ConnectorIPCOptions.yaml - -from __future__ import annotations - -from typing import List - -from pydantic import BaseModel, Extra -from typing_extensions import Literal - - -class DataChannel(BaseModel): - class Config: - extra = Extra.forbid - - version: str - supportedSerialization: List[Literal["JSONL", "PROTOBUF"]] - supportedTransport: List[Literal["STDIO", "SOCKET"]] - - -class ConnectorIPCOptions(BaseModel): - class Config: - extra = Extra.forbid - - dataChannel: DataChannel diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorMetadataDefinitionV0.json b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorMetadataDefinitionV0.json deleted file mode 100644 index aa7a75351f55..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorMetadataDefinitionV0.json +++ /dev/null @@ -1,897 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/ConnectorMetadataDefinitionV0.yml", - "title": "ConnectorMetadataDefinitionV0", - "description": "describes the metadata of a connector", - "type": "object", - "required": [ - "metadataSpecVersion", - "data" - ], - "additionalProperties": false, - "properties": { - "metadataSpecVersion": { - "type": "string" - }, - "data": { - "type": "object", - "required": [ - "name", - "definitionId", - "connectorType", - "dockerRepository", - "dockerImageTag", - "license", - "documentationUrl", - "githubIssueLabel", - "connectorSubtype", - "releaseStage" - ], - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "icon": { - "type": "string" - }, - "definitionId": { - "type": "string", - "format": "uuid" - }, - "connectorBuildOptions": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorBuildOptions.yaml", - "title": "ConnectorBuildOptions", - "description": "metadata specific to the build process.", - "type": "object", - "additionalProperties": false, - "properties": { - "baseImage": { - "type": "string" - } - } - }, - "connectorTestSuitesOptions": { - "type": "array", - "items": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorTestOptions.yaml", - "title": "ConnectorTestSuiteOptions", - "description": "Options for a specific connector test suite.", - "type": "object", - "required": [ - "suite" - ], - "additionalProperties": false, - "properties": { - "suite": { - "description": "Name of the configured test suite", - "type": "string", - "enum": [ - "unitTests", - "integrationTests", - "acceptanceTests", - "liveTests" - ] - }, - "testSecrets": { - "description": "List of secrets required to run the test suite", - "type": "array", - "items": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/Secret.yaml", - "title": "Secret", - "description": "An object describing a secret's metadata", - "type": "object", - "required": [ - "name", - "secretStore" - ], - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "The secret name in the secret store" - }, - "fileName": { - "type": "string", - "description": "The name of the file to which the secret value would be persisted" - }, - "secretStore": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SecretStore.yaml", - "title": "SecretStore", - "description": "An object describing a secret store metadata", - "type": "object", - "additionalProperties": false, - "properties": { - "alias": { - "type": "string", - "description": "The alias of the secret store which can map to its actual secret address" - }, - "type": { - "type": "string", - "description": "The type of the secret store", - "enum": [ - "GSM" - ] - } - } - } - } - } - }, - "testConnections": { - "description": "List of sandbox cloud connections that tests can be run against", - "type": "array", - "items": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/TestConnections.yaml", - "title": "TestConnections", - "description": "List of sandbox cloud connections that tests can be run against", - "type": "object", - "required": [ - "name", - "id" - ], - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "The connection name" - }, - "id": { - "type": "string", - "description": "The connection ID" - } - } - } - } - } - } - }, - "connectorType": { - "type": "string", - "enum": [ - "destination", - "source" - ] - }, - "dockerRepository": { - "type": "string" - }, - "dockerImageTag": { - "type": "string" - }, - "supportsDbt": { - "type": "boolean" - }, - "supportsNormalization": { - "type": "boolean" - }, - "license": { - "type": "string" - }, - "documentationUrl": { - "type": "string", - "format": "uri" - }, - "externalDocumentationUrls": { - "type": "array", - "description": "An array of external vendor documentation URLs (changelogs, API references, deprecation notices, etc.)", - "items": { - "type": "object", - "required": [ - "title", - "url" - ], - "additionalProperties": false, - "properties": { - "title": { - "type": "string", - "description": "Display title for the documentation link" - }, - "url": { - "type": "string", - "format": "uri", - "description": "URL to the external documentation" - }, - "type": { - "type": "string", - "description": "Category of documentation", - "enum": [ - "api_deprecations", - "api_reference", - "api_release_history", - "authentication_guide", - "data_model_reference", - "developer_community", - "migration_guide", - "openapi_spec", - "other", - "permissions_scopes", - "rate_limits", - "sql_reference", - "status_page" - ] - }, - "requiresLogin": { - "type": "boolean", - "description": "Whether the URL requires authentication to access", - "default": false - } - } - } - }, - "githubIssueLabel": { - "type": "string" - }, - "maxSecondsBetweenMessages": { - "description": "Maximum delay between 2 airbyte protocol messages, in second. The source will timeout if this delay is reached", - "type": "integer" - }, - "releaseDate": { - "description": "The date when this connector was first released, in yyyy-mm-dd format.", - "type": "string", - "format": "date" - }, - "protocolVersion": { - "type": "string", - "description": "the Airbyte Protocol version supported by the connector" - }, - "erdUrl": { - "type": "string", - "description": "The URL where you can visualize the ERD" - }, - "connectorSubtype": { - "type": "string", - "enum": [ - "api", - "database", - "datalake", - "file", - "custom", - "message_queue", - "unknown", - "vectorstore" - ] - }, - "releaseStage": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte-platform/blob/main/airbyte-config/config-models/src/main/resources/types/ReleaseStage.yaml", - "title": "ReleaseStage", - "description": "enum that describes a connector's release stage", - "type": "string", - "enum": [ - "alpha", - "beta", - "generally_available", - "custom" - ] - }, - "supportLevel": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/SupportLevel.yaml", - "title": "SupportLevel", - "description": "enum that describes a connector's release stage", - "type": "string", - "enum": [ - "community", - "certified", - "archived" - ] - }, - "tags": { - "type": "array", - "description": "An array of tags that describe the connector. E.g: language:python, keyword:rds, etc.", - "items": { - "type": "string" - }, - "default": [] - }, - "registryOverrides": { - "anyOf": [ - { - "type": "object", - "additionalProperties": false, - "properties": { - "oss": { - "anyOf": [ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/RegistryOverrides.yml", - "title": "RegistryOverrides", - "description": "describes the overrides per registry of a connector", - "type": "object", - "additionalProperties": false, - "required": [ - "enabled" - ], - "properties": { - "enabled": { - "type": "boolean", - "default": false - }, - "name": { - "type": "string" - }, - "dockerRepository": { - "type": "string" - }, - "dockerImageTag": { - "type": "string" - }, - "supportsDbt": { - "type": "boolean" - }, - "supportsNormalization": { - "type": "boolean" - }, - "license": { - "type": "string" - }, - "documentationUrl": { - "type": "string", - "format": "uri" - }, - "connectorSubtype": { - "type": "string" - }, - "allowedHosts": { - "$ref": "#/properties/data/properties/allowedHosts" - }, - "normalizationConfig": { - "$ref": "#/properties/data/properties/normalizationConfig" - }, - "suggestedStreams": { - "$ref": "#/properties/data/properties/suggestedStreams" - }, - "resourceRequirements": { - "$ref": "#/properties/data/properties/resourceRequirements" - } - } - } - ] - }, - "cloud": { - "anyOf": [ - { - "$ref": "#/properties/data/properties/registryOverrides/anyOf/0/properties/oss/anyOf/0" - } - ] - } - } - } - ] - }, - "allowedHosts": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/AllowedHosts.yaml", - "title": "AllowedHosts", - "description": "A connector's allowed hosts. If present, the platform will limit communication to only hosts which are listed in `AllowedHosts.hosts`.", - "type": "object", - "additionalProperties": true, - "properties": { - "hosts": { - "type": "array", - "description": "An array of hosts that this connector can connect to. AllowedHosts not being present for the source or destination means that access to all hosts is allowed. An empty list here means that no network access is granted.", - "items": { - "type": "string" - } - } - } - }, - "releases": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorReleases.yaml", - "title": "ConnectorReleases", - "description": "Contains information about different types of releases for a connector.", - "type": "object", - "additionalProperties": false, - "properties": { - "rolloutConfiguration": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/RolloutConfiguration.yaml", - "title": "RolloutConfiguration", - "description": "configuration for the rollout of a connector", - "type": "object", - "additionalProperties": false, - "properties": { - "enableProgressiveRollout": { - "type": "boolean", - "default": false, - "description": "Whether to enable progressive rollout for the connector." - }, - "initialPercentage": { - "type": "integer", - "minimum": 0, - "maximum": 100, - "default": 0, - "description": "The percentage of users that should receive the new version initially." - }, - "maxPercentage": { - "type": "integer", - "minimum": 0, - "maximum": 100, - "default": 50, - "description": "The percentage of users who should receive the release candidate during the test phase before full rollout." - }, - "advanceDelayMinutes": { - "type": "integer", - "minimum": 10, - "default": 10, - "description": "The number of minutes to wait before advancing the rollout percentage." - } - } - }, - "breakingChanges": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorBreakingChanges.yaml", - "title": "ConnectorBreakingChanges", - "description": "Each entry denotes a breaking change in a specific version of a connector that requires user action to upgrade.", - "type": "object", - "additionalProperties": false, - "minProperties": 1, - "patternProperties": { - "^\\d+\\.\\d+\\.\\d+$": { - "$ref": "#/properties/data/properties/releases/properties/breakingChanges/definitions/VersionBreakingChange" - } - }, - "definitions": { - "VersionBreakingChange": { - "description": "Contains information about a breaking change, including the deadline to upgrade and a message detailing the change.", - "type": "object", - "additionalProperties": false, - "required": [ - "upgradeDeadline", - "message" - ], - "properties": { - "upgradeDeadline": { - "description": "The deadline by which to upgrade before the breaking change takes effect.", - "type": "string", - "format": "date" - }, - "message": { - "description": "Descriptive message detailing the breaking change.", - "type": "string" - }, - "deadlineAction": { - "description": "Action to do when the deadline is reached.", - "type": "string", - "enum": [ - "auto_upgrade", - "disable" - ] - }, - "migrationDocumentationUrl": { - "description": "URL to documentation on how to migrate to the current version. Defaults to ${documentationUrl}-migrations#${version}", - "type": "string", - "format": "uri" - }, - "scopedImpact": { - "description": "List of scopes that are impacted by the breaking change. If not specified, the breaking change cannot be scoped to reduce impact via the supported scope types.", - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/properties/data/properties/releases/properties/breakingChanges/definitions/BreakingChangeScope" - } - } - } - }, - "BreakingChangeScope": { - "description": "A scope that can be used to limit the impact of a breaking change.", - "type": "object", - "oneOf": [ - { - "$ref": "#/properties/data/properties/releases/properties/breakingChanges/definitions/StreamBreakingChangeScope" - } - ] - }, - "StreamBreakingChangeScope": { - "description": "A scope that can be used to limit the impact of a breaking change to specific streams.", - "type": "object", - "additionalProperties": false, - "required": [ - "scopeType", - "impactedScopes" - ], - "properties": { - "scopeType": { - "type": "string", - "const": "stream" - }, - "impactedScopes": { - "description": "List of streams that are impacted by the breaking change.", - "type": "array", - "minItems": 1, - "items": { - "type": "string" - } - } - } - } - } - }, - "migrationDocumentationUrl": { - "description": "URL to documentation on how to migrate from the previous version to the current version. Defaults to ${documentationUrl}-migrations", - "type": "string", - "format": "uri" - } - } - }, - "normalizationConfig": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/NormalizationDestinationDefinitionConfig.yaml", - "title": "NormalizationDestinationDefinitionConfig", - "description": "describes a normalization config for destination definition", - "type": "object", - "required": [ - "normalizationRepository", - "normalizationTag", - "normalizationIntegrationType" - ], - "additionalProperties": true, - "properties": { - "normalizationRepository": { - "type": "string", - "description": "a field indicating the name of the repository to be used for normalization. If the value of the flag is NULL - normalization is not used." - }, - "normalizationTag": { - "type": "string", - "description": "a field indicating the tag of the docker repository to be used for normalization." - }, - "normalizationIntegrationType": { - "type": "string", - "description": "a field indicating the type of integration dialect to use for normalization." - } - } - }, - "suggestedStreams": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SuggestedStreams.yaml", - "title": "SuggestedStreams", - "description": "A source's suggested streams. These will be suggested by default for new connections using this source. Otherwise, all streams will be selected. This is useful for when your source has a lot of streams, but the average user will only want a subset of them synced.", - "type": "object", - "additionalProperties": true, - "properties": { - "streams": { - "type": "array", - "description": "An array of streams that this connector suggests the average user will want. SuggestedStreams not being present for the source means that all streams are suggested. An empty list here means that no streams are suggested.", - "items": { - "type": "string" - } - } - } - }, - "resourceRequirements": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ActorDefinitionResourceRequirements.yaml", - "title": "ActorDefinitionResourceRequirements", - "description": "actor definition specific resource requirements", - "type": "object", - "additionalProperties": false, - "properties": { - "default": { - "description": "if set, these are the requirements that should be set for ALL jobs run for this actor definition.", - "$ref": "#/properties/data/properties/resourceRequirements/definitions/JobTypeResourceLimit/properties/resourceRequirements" - }, - "jobSpecific": { - "type": "array", - "items": { - "$ref": "#/properties/data/properties/resourceRequirements/definitions/JobTypeResourceLimit" - } - } - }, - "definitions": { - "JobTypeResourceLimit": { - "description": "sets resource requirements for a specific job type for an actor definition. these values override the default, if both are set.", - "type": "object", - "additionalProperties": false, - "required": [ - "jobType", - "resourceRequirements" - ], - "properties": { - "jobType": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/JobType.yaml", - "title": "JobType", - "description": "enum that describes the different types of jobs that the platform runs.", - "type": "string", - "enum": [ - "get_spec", - "check_connection", - "discover_schema", - "sync", - "reset_connection", - "connection_updater", - "replicate" - ] - }, - "resourceRequirements": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ResourceRequirements.yaml", - "title": "ResourceRequirements", - "description": "generic configuration for pod source requirements", - "type": "object", - "additionalProperties": false, - "properties": { - "cpu_request": { - "type": "string" - }, - "cpu_limit": { - "type": "string" - }, - "memory_request": { - "type": "string" - }, - "memory_limit": { - "type": "string" - } - } - } - } - } - } - }, - "ab_internal": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/AirbyteInternal.yml", - "title": "AirbyteInternal", - "description": "Fields for internal use only", - "type": "object", - "additionalProperties": true, - "properties": { - "sl": { - "type": "integer", - "enum": [ - 0, - 100, - 200, - 300 - ] - }, - "ql": { - "type": "integer", - "enum": [ - 0, - 100, - 200, - 300, - 400, - 500, - 600 - ] - }, - "isEnterprise": { - "type": "boolean", - "default": false - }, - "requireVersionIncrementsInPullRequests": { - "type": "boolean", - "default": true, - "description": "When false, version increment checks will be skipped for this connector" - } - } - }, - "remoteRegistries": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/RemoteRegistries.yml", - "title": "RemoteRegistries", - "description": "describes how the connector is published to remote registries", - "type": "object", - "additionalProperties": false, - "properties": { - "pypi": { - "$ref": "#/properties/data/properties/remoteRegistries/definitions/PyPi" - } - }, - "definitions": { - "PyPi": { - "title": "PyPi", - "description": "describes the PyPi publishing options", - "type": "object", - "additionalProperties": false, - "required": [ - "enabled", - "packageName" - ], - "properties": { - "enabled": { - "type": "boolean" - }, - "packageName": { - "type": "string", - "description": "The name of the package on PyPi." - } - } - } - } - }, - "supportsRefreshes": { - "type": "boolean", - "default": false - }, - "generated": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/GeneratedFields.yaml", - "title": "GeneratedFields", - "description": "Optional schema for fields generated at metadata upload time", - "type": "object", - "properties": { - "git": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/GitInfo.yaml", - "title": "GitInfo", - "description": "Information about the author of the last commit that modified this file. DO NOT DEFINE THIS FIELD MANUALLY. It will be overwritten by the CI.", - "type": "object", - "additionalProperties": false, - "properties": { - "commit_sha": { - "type": "string", - "description": "The git commit sha of the last commit that modified this file." - }, - "commit_timestamp": { - "type": "string", - "format": "date-time", - "description": "The git commit timestamp of the last commit that modified this file." - }, - "commit_author": { - "type": "string", - "description": "The git commit author of the last commit that modified this file." - }, - "commit_author_email": { - "type": "string", - "description": "The git commit author email of the last commit that modified this file." - } - } - }, - "source_file_info": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/SourceFileInfo.yaml", - "title": "SourceFileInfo", - "description": "Information about the source file that generated the registry entry", - "type": "object", - "properties": { - "metadata_etag": { - "type": "string" - }, - "metadata_file_path": { - "type": "string" - }, - "metadata_bucket_name": { - "type": "string" - }, - "metadata_last_modified": { - "type": "string" - }, - "registry_entry_generated_at": { - "type": "string" - } - } - }, - "metrics": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/ConnectorMetrics.yaml", - "title": "ConnectorMetrics", - "description": "Information about the source file that generated the registry entry", - "type": "object", - "properties": { - "all": { - "type": "ConnectorMetric" - }, - "cloud": { - "type": "ConnectorMetric" - }, - "oss": { - "type": "ConnectorMetric" - } - }, - "definitions": { - "ConnectorMetric": { - "type": "object", - "properties": { - "usage": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - } - ] - }, - "sync_success_rate": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "string", - "enum": [ - "low", - "medium", - "high" - ] - } - ] - }, - "connector_version": { - "type": "string" - } - }, - "additionalProperties": true - } - } - }, - "sbomUrl": { - "type": "string", - "description": "URL to the SBOM file" - } - } - }, - "supportsFileTransfer": { - "type": "boolean", - "default": false - }, - "supportsDataActivation": { - "type": "boolean", - "default": false - }, - "connectorIPCOptions": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorIPCOptions.yaml", - "title": "ConnectorIPCOptions", - "type": "object", - "required": [ - "dataChannel" - ], - "additionalProperties": false, - "properties": { - "dataChannel": { - "type": "object", - "required": [ - "version", - "supportedSerialization", - "supportedTransport" - ], - "additionalProperties": false, - "properties": { - "version": { - "type": "string" - }, - "supportedSerialization": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "JSONL", - "PROTOBUF" - ] - } - }, - "supportedTransport": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "STDIO", - "SOCKET" - ] - } - } - } - } - } - } - } - } - } -} diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorMetadataDefinitionV0.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorMetadataDefinitionV0.py deleted file mode 100644 index 347ee83fa23c..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorMetadataDefinitionV0.py +++ /dev/null @@ -1,479 +0,0 @@ -# generated by datamodel-codegen: -# filename: ConnectorMetadataDefinitionV0.yaml - -from __future__ import annotations - -from datetime import date, datetime -from typing import Any, Dict, List, Optional, Union -from uuid import UUID - -from pydantic import AnyUrl, BaseModel, Extra, Field, conint, constr -from typing_extensions import Literal - - -class ExternalDocumentationUrl(BaseModel): - class Config: - extra = Extra.forbid - - title: str = Field(..., description="Display title for the documentation link") - url: AnyUrl = Field(..., description="URL to the external documentation") - type: Optional[ - Literal[ - "api_deprecations", - "api_reference", - "api_release_history", - "authentication_guide", - "data_model_reference", - "developer_community", - "migration_guide", - "openapi_spec", - "other", - "permissions_scopes", - "rate_limits", - "sql_reference", - "status_page", - ] - ] = Field(None, description="Category of documentation") - requiresLogin: Optional[bool] = Field( - False, description="Whether the URL requires authentication to access" - ) - - -class ConnectorBuildOptions(BaseModel): - class Config: - extra = Extra.forbid - - baseImage: Optional[str] = None - - -class SecretStore(BaseModel): - class Config: - extra = Extra.forbid - - alias: Optional[str] = Field( - None, - description="The alias of the secret store which can map to its actual secret address", - ) - type: Optional[Literal["GSM"]] = Field( - None, description="The type of the secret store" - ) - - -class TestConnections(BaseModel): - class Config: - extra = Extra.forbid - - name: str = Field(..., description="The connection name") - id: str = Field(..., description="The connection ID") - - -class ReleaseStage(BaseModel): - __root__: Literal["alpha", "beta", "generally_available", "custom"] = Field( - ..., - description="enum that describes a connector's release stage", - title="ReleaseStage", - ) - - -class SupportLevel(BaseModel): - __root__: Literal["community", "certified", "archived"] = Field( - ..., - description="enum that describes a connector's release stage", - title="SupportLevel", - ) - - -class AllowedHosts(BaseModel): - class Config: - extra = Extra.allow - - hosts: Optional[List[str]] = Field( - None, - description="An array of hosts that this connector can connect to. AllowedHosts not being present for the source or destination means that access to all hosts is allowed. An empty list here means that no network access is granted.", - ) - - -class NormalizationDestinationDefinitionConfig(BaseModel): - class Config: - extra = Extra.allow - - normalizationRepository: str = Field( - ..., - description="a field indicating the name of the repository to be used for normalization. If the value of the flag is NULL - normalization is not used.", - ) - normalizationTag: str = Field( - ..., - description="a field indicating the tag of the docker repository to be used for normalization.", - ) - normalizationIntegrationType: str = Field( - ..., - description="a field indicating the type of integration dialect to use for normalization.", - ) - - -class SuggestedStreams(BaseModel): - class Config: - extra = Extra.allow - - streams: Optional[List[str]] = Field( - None, - description="An array of streams that this connector suggests the average user will want. SuggestedStreams not being present for the source means that all streams are suggested. An empty list here means that no streams are suggested.", - ) - - -class ResourceRequirements(BaseModel): - class Config: - extra = Extra.forbid - - cpu_request: Optional[str] = None - cpu_limit: Optional[str] = None - memory_request: Optional[str] = None - memory_limit: Optional[str] = None - - -class JobType(BaseModel): - __root__: Literal[ - "get_spec", - "check_connection", - "discover_schema", - "sync", - "reset_connection", - "connection_updater", - "replicate", - ] = Field( - ..., - description="enum that describes the different types of jobs that the platform runs.", - title="JobType", - ) - - -class RolloutConfiguration(BaseModel): - class Config: - extra = Extra.forbid - - enableProgressiveRollout: Optional[bool] = Field( - False, description="Whether to enable progressive rollout for the connector." - ) - initialPercentage: Optional[conint(ge=0, le=100)] = Field( - 0, - description="The percentage of users that should receive the new version initially.", - ) - maxPercentage: Optional[conint(ge=0, le=100)] = Field( - 50, - description="The percentage of users who should receive the release candidate during the test phase before full rollout.", - ) - advanceDelayMinutes: Optional[conint(ge=10)] = Field( - 10, - description="The number of minutes to wait before advancing the rollout percentage.", - ) - - -class StreamBreakingChangeScope(BaseModel): - class Config: - extra = Extra.forbid - - scopeType: str = Field("stream", const=True) - impactedScopes: List[str] = Field( - ..., - description="List of streams that are impacted by the breaking change.", - min_items=1, - ) - - -class AirbyteInternal(BaseModel): - class Config: - extra = Extra.allow - - sl: Optional[Literal[0, 100, 200, 300]] = None - ql: Optional[Literal[0, 100, 200, 300, 400, 500, 600]] = None - isEnterprise: Optional[bool] = False - requireVersionIncrementsInPullRequests: Optional[bool] = Field( - True, - description="When false, version increment checks will be skipped for this connector", - ) - - -class PyPi(BaseModel): - class Config: - extra = Extra.forbid - - enabled: bool - packageName: str = Field(..., description="The name of the package on PyPi.") - - -class GitInfo(BaseModel): - class Config: - extra = Extra.forbid - - commit_sha: Optional[str] = Field( - None, - description="The git commit sha of the last commit that modified this file.", - ) - commit_timestamp: Optional[datetime] = Field( - None, - description="The git commit timestamp of the last commit that modified this file.", - ) - commit_author: Optional[str] = Field( - None, - description="The git commit author of the last commit that modified this file.", - ) - commit_author_email: Optional[str] = Field( - None, - description="The git commit author email of the last commit that modified this file.", - ) - - -class SourceFileInfo(BaseModel): - metadata_etag: Optional[str] = None - metadata_file_path: Optional[str] = None - metadata_bucket_name: Optional[str] = None - metadata_last_modified: Optional[str] = None - registry_entry_generated_at: Optional[str] = None - - -class ConnectorMetrics(BaseModel): - all: Optional[Any] = None - cloud: Optional[Any] = None - oss: Optional[Any] = None - - -class ConnectorMetric(BaseModel): - class Config: - extra = Extra.allow - - usage: Optional[Union[str, Literal["low", "medium", "high"]]] = None - sync_success_rate: Optional[Union[str, Literal["low", "medium", "high"]]] = None - connector_version: Optional[str] = None - - -class DataChannel(BaseModel): - class Config: - extra = Extra.forbid - - version: str - supportedSerialization: List[Literal["JSONL", "PROTOBUF"]] - supportedTransport: List[Literal["STDIO", "SOCKET"]] - - -class ConnectorIPCOptions(BaseModel): - class Config: - extra = Extra.forbid - - dataChannel: DataChannel - - -class Secret(BaseModel): - class Config: - extra = Extra.forbid - - name: str = Field(..., description="The secret name in the secret store") - fileName: Optional[str] = Field( - None, - description="The name of the file to which the secret value would be persisted", - ) - secretStore: SecretStore - - -class JobTypeResourceLimit(BaseModel): - class Config: - extra = Extra.forbid - - jobType: JobType - resourceRequirements: ResourceRequirements - - -class BreakingChangeScope(BaseModel): - __root__: StreamBreakingChangeScope = Field( - ..., - description="A scope that can be used to limit the impact of a breaking change.", - ) - - -class RemoteRegistries(BaseModel): - class Config: - extra = Extra.forbid - - pypi: Optional[PyPi] = None - - -class GeneratedFields(BaseModel): - git: Optional[GitInfo] = None - source_file_info: Optional[SourceFileInfo] = None - metrics: Optional[ConnectorMetrics] = None - sbomUrl: Optional[str] = Field(None, description="URL to the SBOM file") - - -class ConnectorTestSuiteOptions(BaseModel): - class Config: - extra = Extra.forbid - - suite: Literal["unitTests", "integrationTests", "acceptanceTests", "liveTests"] = ( - Field(..., description="Name of the configured test suite") - ) - testSecrets: Optional[List[Secret]] = Field( - None, description="List of secrets required to run the test suite" - ) - testConnections: Optional[List[TestConnections]] = Field( - None, - description="List of sandbox cloud connections that tests can be run against", - ) - - -class ActorDefinitionResourceRequirements(BaseModel): - class Config: - extra = Extra.forbid - - default: Optional[ResourceRequirements] = Field( - None, - description="if set, these are the requirements that should be set for ALL jobs run for this actor definition.", - ) - jobSpecific: Optional[List[JobTypeResourceLimit]] = None - - -class VersionBreakingChange(BaseModel): - class Config: - extra = Extra.forbid - - upgradeDeadline: date = Field( - ..., - description="The deadline by which to upgrade before the breaking change takes effect.", - ) - message: str = Field( - ..., description="Descriptive message detailing the breaking change." - ) - deadlineAction: Optional[Literal["auto_upgrade", "disable"]] = Field( - None, description="Action to do when the deadline is reached." - ) - migrationDocumentationUrl: Optional[AnyUrl] = Field( - None, - description="URL to documentation on how to migrate to the current version. Defaults to ${documentationUrl}-migrations#${version}", - ) - scopedImpact: Optional[List[BreakingChangeScope]] = Field( - None, - description="List of scopes that are impacted by the breaking change. If not specified, the breaking change cannot be scoped to reduce impact via the supported scope types.", - min_items=1, - ) - - -class RegistryOverrides(BaseModel): - class Config: - extra = Extra.forbid - - enabled: bool - name: Optional[str] = None - dockerRepository: Optional[str] = None - dockerImageTag: Optional[str] = None - supportsDbt: Optional[bool] = None - supportsNormalization: Optional[bool] = None - license: Optional[str] = None - documentationUrl: Optional[AnyUrl] = None - connectorSubtype: Optional[str] = None - allowedHosts: Optional[AllowedHosts] = None - normalizationConfig: Optional[NormalizationDestinationDefinitionConfig] = None - suggestedStreams: Optional[SuggestedStreams] = None - resourceRequirements: Optional[ActorDefinitionResourceRequirements] = None - - -class ConnectorBreakingChanges(BaseModel): - class Config: - extra = Extra.forbid - - __root__: Dict[constr(regex=r"^\d+\.\d+\.\d+$"), VersionBreakingChange] = Field( - ..., - description="Each entry denotes a breaking change in a specific version of a connector that requires user action to upgrade.", - title="ConnectorBreakingChanges", - ) - - -class RegistryOverride(BaseModel): - class Config: - extra = Extra.forbid - - oss: Optional[RegistryOverrides] = None - cloud: Optional[RegistryOverrides] = None - - -class ConnectorReleases(BaseModel): - class Config: - extra = Extra.forbid - - rolloutConfiguration: Optional[RolloutConfiguration] = None - breakingChanges: Optional[ConnectorBreakingChanges] = None - migrationDocumentationUrl: Optional[AnyUrl] = Field( - None, - description="URL to documentation on how to migrate from the previous version to the current version. Defaults to ${documentationUrl}-migrations", - ) - - -class Data(BaseModel): - class Config: - extra = Extra.forbid - - name: str - icon: Optional[str] = None - definitionId: UUID - connectorBuildOptions: Optional[ConnectorBuildOptions] = None - connectorTestSuitesOptions: Optional[List[ConnectorTestSuiteOptions]] = None - connectorType: Literal["destination", "source"] - dockerRepository: str - dockerImageTag: str - supportsDbt: Optional[bool] = None - supportsNormalization: Optional[bool] = None - license: str - documentationUrl: AnyUrl - externalDocumentationUrls: Optional[List[ExternalDocumentationUrl]] = Field( - None, - description="An array of external vendor documentation URLs (changelogs, API references, deprecation notices, etc.)", - ) - githubIssueLabel: str - maxSecondsBetweenMessages: Optional[int] = Field( - None, - description="Maximum delay between 2 airbyte protocol messages, in second. The source will timeout if this delay is reached", - ) - releaseDate: Optional[date] = Field( - None, - description="The date when this connector was first released, in yyyy-mm-dd format.", - ) - protocolVersion: Optional[str] = Field( - None, description="the Airbyte Protocol version supported by the connector" - ) - erdUrl: Optional[str] = Field( - None, description="The URL where you can visualize the ERD" - ) - connectorSubtype: Literal[ - "api", - "database", - "datalake", - "file", - "custom", - "message_queue", - "unknown", - "vectorstore", - ] - releaseStage: ReleaseStage - supportLevel: Optional[SupportLevel] = None - tags: Optional[List[str]] = Field( - [], - description="An array of tags that describe the connector. E.g: language:python, keyword:rds, etc.", - ) - registryOverrides: Optional[RegistryOverride] = None - allowedHosts: Optional[AllowedHosts] = None - releases: Optional[ConnectorReleases] = None - normalizationConfig: Optional[NormalizationDestinationDefinitionConfig] = None - suggestedStreams: Optional[SuggestedStreams] = None - resourceRequirements: Optional[ActorDefinitionResourceRequirements] = None - ab_internal: Optional[AirbyteInternal] = None - remoteRegistries: Optional[RemoteRegistries] = None - supportsRefreshes: Optional[bool] = False - generated: Optional[GeneratedFields] = None - supportsFileTransfer: Optional[bool] = False - supportsDataActivation: Optional[bool] = False - connectorIPCOptions: Optional[ConnectorIPCOptions] = None - - -class ConnectorMetadataDefinitionV0(BaseModel): - class Config: - extra = Extra.forbid - - metadataSpecVersion: str - data: Data diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorMetrics.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorMetrics.py deleted file mode 100644 index 33a9f1ba0668..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorMetrics.py +++ /dev/null @@ -1,24 +0,0 @@ -# generated by datamodel-codegen: -# filename: ConnectorMetrics.yaml - -from __future__ import annotations - -from typing import Any, Optional, Union - -from pydantic import BaseModel, Extra -from typing_extensions import Literal - - -class ConnectorMetrics(BaseModel): - all: Optional[Any] = None - cloud: Optional[Any] = None - oss: Optional[Any] = None - - -class ConnectorMetric(BaseModel): - class Config: - extra = Extra.allow - - usage: Optional[Union[str, Literal["low", "medium", "high"]]] = None - sync_success_rate: Optional[Union[str, Literal["low", "medium", "high"]]] = None - connector_version: Optional[str] = None diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorPackageInfo.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorPackageInfo.py deleted file mode 100644 index e4496fa446b5..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorPackageInfo.py +++ /dev/null @@ -1,12 +0,0 @@ -# generated by datamodel-codegen: -# filename: ConnectorPackageInfo.yaml - -from __future__ import annotations - -from typing import Optional - -from pydantic import BaseModel - - -class ConnectorPackageInfo(BaseModel): - cdk_version: Optional[str] = None diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistryDestinationDefinition.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistryDestinationDefinition.py deleted file mode 100644 index 09b5baee491c..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistryDestinationDefinition.py +++ /dev/null @@ -1,407 +0,0 @@ -# generated by datamodel-codegen: -# filename: ConnectorRegistryDestinationDefinition.yaml - -from __future__ import annotations - -from datetime import date, datetime -from typing import Any, Dict, List, Optional, Union -from uuid import UUID - -from pydantic import AnyUrl, BaseModel, Extra, Field, conint, constr -from typing_extensions import Literal - - -class ReleaseStage(BaseModel): - __root__: Literal["alpha", "beta", "generally_available", "custom"] = Field( - ..., - description="enum that describes a connector's release stage", - title="ReleaseStage", - ) - - -class SupportLevel(BaseModel): - __root__: Literal["community", "certified", "archived"] = Field( - ..., - description="enum that describes a connector's release stage", - title="SupportLevel", - ) - - -class ResourceRequirements(BaseModel): - class Config: - extra = Extra.forbid - - cpu_request: Optional[str] = None - cpu_limit: Optional[str] = None - memory_request: Optional[str] = None - memory_limit: Optional[str] = None - - -class JobType(BaseModel): - __root__: Literal[ - "get_spec", - "check_connection", - "discover_schema", - "sync", - "reset_connection", - "connection_updater", - "replicate", - ] = Field( - ..., - description="enum that describes the different types of jobs that the platform runs.", - title="JobType", - ) - - -class NormalizationDestinationDefinitionConfig(BaseModel): - class Config: - extra = Extra.allow - - normalizationRepository: str = Field( - ..., - description="a field indicating the name of the repository to be used for normalization. If the value of the flag is NULL - normalization is not used.", - ) - normalizationTag: str = Field( - ..., - description="a field indicating the tag of the docker repository to be used for normalization.", - ) - normalizationIntegrationType: str = Field( - ..., - description="a field indicating the type of integration dialect to use for normalization.", - ) - - -class AllowedHosts(BaseModel): - class Config: - extra = Extra.allow - - hosts: Optional[List[str]] = Field( - None, - description="An array of hosts that this connector can connect to. AllowedHosts not being present for the source or destination means that access to all hosts is allowed. An empty list here means that no network access is granted.", - ) - - -class RolloutConfiguration(BaseModel): - class Config: - extra = Extra.forbid - - enableProgressiveRollout: Optional[bool] = Field( - False, description="Whether to enable progressive rollout for the connector." - ) - initialPercentage: Optional[conint(ge=0, le=100)] = Field( - 0, - description="The percentage of users that should receive the new version initially.", - ) - maxPercentage: Optional[conint(ge=0, le=100)] = Field( - 50, - description="The percentage of users who should receive the release candidate during the test phase before full rollout.", - ) - advanceDelayMinutes: Optional[conint(ge=10)] = Field( - 10, - description="The number of minutes to wait before advancing the rollout percentage.", - ) - - -class StreamBreakingChangeScope(BaseModel): - class Config: - extra = Extra.forbid - - scopeType: str = Field("stream", const=True) - impactedScopes: List[str] = Field( - ..., - description="List of streams that are impacted by the breaking change.", - min_items=1, - ) - - -class SuggestedStreams(BaseModel): - class Config: - extra = Extra.allow - - streams: Optional[List[str]] = Field( - None, - description="An array of streams that this connector suggests the average user will want. SuggestedStreams not being present for the source means that all streams are suggested. An empty list here means that no streams are suggested.", - ) - - -class AirbyteInternal(BaseModel): - class Config: - extra = Extra.allow - - sl: Optional[Literal[0, 100, 200, 300]] = None - ql: Optional[Literal[0, 100, 200, 300, 400, 500, 600]] = None - isEnterprise: Optional[bool] = False - requireVersionIncrementsInPullRequests: Optional[bool] = Field( - True, - description="When false, version increment checks will be skipped for this connector", - ) - - -class GitInfo(BaseModel): - class Config: - extra = Extra.forbid - - commit_sha: Optional[str] = Field( - None, - description="The git commit sha of the last commit that modified this file.", - ) - commit_timestamp: Optional[datetime] = Field( - None, - description="The git commit timestamp of the last commit that modified this file.", - ) - commit_author: Optional[str] = Field( - None, - description="The git commit author of the last commit that modified this file.", - ) - commit_author_email: Optional[str] = Field( - None, - description="The git commit author email of the last commit that modified this file.", - ) - - -class SourceFileInfo(BaseModel): - metadata_etag: Optional[str] = None - metadata_file_path: Optional[str] = None - metadata_bucket_name: Optional[str] = None - metadata_last_modified: Optional[str] = None - registry_entry_generated_at: Optional[str] = None - - -class ConnectorMetrics(BaseModel): - all: Optional[Any] = None - cloud: Optional[Any] = None - oss: Optional[Any] = None - - -class ConnectorMetric(BaseModel): - class Config: - extra = Extra.allow - - usage: Optional[Union[str, Literal["low", "medium", "high"]]] = None - sync_success_rate: Optional[Union[str, Literal["low", "medium", "high"]]] = None - connector_version: Optional[str] = None - - -class ConnectorPackageInfo(BaseModel): - cdk_version: Optional[str] = None - - -class JobTypeResourceLimit(BaseModel): - class Config: - extra = Extra.forbid - - jobType: JobType - resourceRequirements: ResourceRequirements - - -class BreakingChangeScope(BaseModel): - __root__: StreamBreakingChangeScope = Field( - ..., - description="A scope that can be used to limit the impact of a breaking change.", - ) - - -class GeneratedFields(BaseModel): - git: Optional[GitInfo] = None - source_file_info: Optional[SourceFileInfo] = None - metrics: Optional[ConnectorMetrics] = None - sbomUrl: Optional[str] = Field(None, description="URL to the SBOM file") - - -class ActorDefinitionResourceRequirements(BaseModel): - class Config: - extra = Extra.forbid - - default: Optional[ResourceRequirements] = Field( - None, - description="if set, these are the requirements that should be set for ALL jobs run for this actor definition.", - ) - jobSpecific: Optional[List[JobTypeResourceLimit]] = None - - -class VersionBreakingChange(BaseModel): - class Config: - extra = Extra.forbid - - upgradeDeadline: date = Field( - ..., - description="The deadline by which to upgrade before the breaking change takes effect.", - ) - message: str = Field( - ..., description="Descriptive message detailing the breaking change." - ) - deadlineAction: Optional[Literal["auto_upgrade", "disable"]] = Field( - None, description="Action to do when the deadline is reached." - ) - migrationDocumentationUrl: Optional[AnyUrl] = Field( - None, - description="URL to documentation on how to migrate to the current version. Defaults to ${documentationUrl}-migrations#${version}", - ) - scopedImpact: Optional[List[BreakingChangeScope]] = Field( - None, - description="List of scopes that are impacted by the breaking change. If not specified, the breaking change cannot be scoped to reduce impact via the supported scope types.", - min_items=1, - ) - - -class ConnectorBreakingChanges(BaseModel): - class Config: - extra = Extra.forbid - - __root__: Dict[constr(regex=r"^\d+\.\d+\.\d+$"), VersionBreakingChange] = Field( - ..., - description="Each entry denotes a breaking change in a specific version of a connector that requires user action to upgrade.", - title="ConnectorBreakingChanges", - ) - - -class ConnectorRegistryDestinationDefinition(BaseModel): - class Config: - extra = Extra.allow - - destinationDefinitionId: UUID - name: str - dockerRepository: str - dockerImageTag: str - documentationUrl: str - icon: Optional[str] = None - iconUrl: Optional[str] = None - spec: Dict[str, Any] - tombstone: Optional[bool] = Field( - False, - description="if false, the configuration is active. if true, then this configuration is permanently off.", - ) - public: Optional[bool] = Field( - False, - description="true if this connector definition is available to all workspaces", - ) - custom: Optional[bool] = Field( - False, description="whether this is a custom connector definition" - ) - releaseStage: Optional[ReleaseStage] = None - supportLevel: Optional[SupportLevel] = None - releaseDate: Optional[date] = Field( - None, - description="The date when this connector was first released, in yyyy-mm-dd format.", - ) - tags: Optional[List[str]] = Field( - None, - description="An array of tags that describe the connector. E.g: language:python, keyword:rds, etc.", - ) - resourceRequirements: Optional[ActorDefinitionResourceRequirements] = None - protocolVersion: Optional[str] = Field( - None, description="the Airbyte Protocol version supported by the connector" - ) - normalizationConfig: Optional[NormalizationDestinationDefinitionConfig] = None - supportsDbt: Optional[bool] = Field( - None, - description="an optional flag indicating whether DBT is used in the normalization. If the flag value is NULL - DBT is not used.", - ) - allowedHosts: Optional[AllowedHosts] = None - releases: Optional[ConnectorRegistryReleases] = None - ab_internal: Optional[AirbyteInternal] = None - supportsRefreshes: Optional[bool] = False - supportsFileTransfer: Optional[bool] = False - supportsDataActivation: Optional[bool] = False - generated: Optional[GeneratedFields] = None - packageInfo: Optional[ConnectorPackageInfo] = None - language: Optional[str] = Field( - None, description="The language the connector is written in" - ) - - -class ConnectorRegistryReleases(BaseModel): - class Config: - extra = Extra.forbid - - releaseCandidates: Optional[ConnectorReleaseCandidates] = None - rolloutConfiguration: Optional[RolloutConfiguration] = None - breakingChanges: Optional[ConnectorBreakingChanges] = None - migrationDocumentationUrl: Optional[AnyUrl] = Field( - None, - description="URL to documentation on how to migrate from the previous version to the current version. Defaults to ${documentationUrl}-migrations", - ) - - -class ConnectorReleaseCandidates(BaseModel): - class Config: - extra = Extra.forbid - - __root__: Dict[ - constr(regex=r"^\d+\.\d+\.\d+(-[0-9A-Za-z-.]+)?$"), VersionReleaseCandidate - ] = Field( - ..., - description="Each entry denotes a release candidate version of a connector.", - ) - - -class VersionReleaseCandidate(BaseModel): - class Config: - extra = Extra.forbid - - __root__: Union[ - ConnectorRegistrySourceDefinition, ConnectorRegistryDestinationDefinition - ] = Field( - ..., - description="Contains information about a release candidate version of a connector.", - ) - - -class ConnectorRegistrySourceDefinition(BaseModel): - class Config: - extra = Extra.allow - - sourceDefinitionId: UUID - name: str - dockerRepository: str - dockerImageTag: str - documentationUrl: str - icon: Optional[str] = None - iconUrl: Optional[str] = None - sourceType: Optional[Literal["api", "file", "database", "custom"]] = None - spec: Dict[str, Any] - tombstone: Optional[bool] = Field( - False, - description="if false, the configuration is active. if true, then this configuration is permanently off.", - ) - public: Optional[bool] = Field( - False, - description="true if this connector definition is available to all workspaces", - ) - custom: Optional[bool] = Field( - False, description="whether this is a custom connector definition" - ) - releaseStage: Optional[ReleaseStage] = None - supportLevel: Optional[SupportLevel] = None - releaseDate: Optional[date] = Field( - None, - description="The date when this connector was first released, in yyyy-mm-dd format.", - ) - resourceRequirements: Optional[ActorDefinitionResourceRequirements] = None - protocolVersion: Optional[str] = Field( - None, description="the Airbyte Protocol version supported by the connector" - ) - allowedHosts: Optional[AllowedHosts] = None - suggestedStreams: Optional[SuggestedStreams] = None - maxSecondsBetweenMessages: Optional[int] = Field( - None, - description="Number of seconds allowed between 2 airbyte protocol messages. The source will timeout if this delay is reach", - ) - erdUrl: Optional[str] = Field( - None, description="The URL where you can visualize the ERD" - ) - releases: Optional[ConnectorRegistryReleases] = None - ab_internal: Optional[AirbyteInternal] = None - generated: Optional[GeneratedFields] = None - packageInfo: Optional[ConnectorPackageInfo] = None - language: Optional[str] = Field( - None, description="The language the connector is written in" - ) - supportsFileTransfer: Optional[bool] = False - supportsDataActivation: Optional[bool] = False - - -ConnectorRegistryDestinationDefinition.update_forward_refs() -ConnectorRegistryReleases.update_forward_refs() -ConnectorReleaseCandidates.update_forward_refs() -VersionReleaseCandidate.update_forward_refs() diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistryReleases.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistryReleases.py deleted file mode 100644 index 4c7b94fb8fd2..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistryReleases.py +++ /dev/null @@ -1,406 +0,0 @@ -# generated by datamodel-codegen: -# filename: ConnectorRegistryReleases.yaml - -from __future__ import annotations - -from datetime import date, datetime -from typing import Any, Dict, List, Optional, Union -from uuid import UUID - -from pydantic import AnyUrl, BaseModel, Extra, Field, conint, constr -from typing_extensions import Literal - - -class RolloutConfiguration(BaseModel): - class Config: - extra = Extra.forbid - - enableProgressiveRollout: Optional[bool] = Field( - False, description="Whether to enable progressive rollout for the connector." - ) - initialPercentage: Optional[conint(ge=0, le=100)] = Field( - 0, - description="The percentage of users that should receive the new version initially.", - ) - maxPercentage: Optional[conint(ge=0, le=100)] = Field( - 50, - description="The percentage of users who should receive the release candidate during the test phase before full rollout.", - ) - advanceDelayMinutes: Optional[conint(ge=10)] = Field( - 10, - description="The number of minutes to wait before advancing the rollout percentage.", - ) - - -class StreamBreakingChangeScope(BaseModel): - class Config: - extra = Extra.forbid - - scopeType: str = Field("stream", const=True) - impactedScopes: List[str] = Field( - ..., - description="List of streams that are impacted by the breaking change.", - min_items=1, - ) - - -class ReleaseStage(BaseModel): - __root__: Literal["alpha", "beta", "generally_available", "custom"] = Field( - ..., - description="enum that describes a connector's release stage", - title="ReleaseStage", - ) - - -class SupportLevel(BaseModel): - __root__: Literal["community", "certified", "archived"] = Field( - ..., - description="enum that describes a connector's release stage", - title="SupportLevel", - ) - - -class ResourceRequirements(BaseModel): - class Config: - extra = Extra.forbid - - cpu_request: Optional[str] = None - cpu_limit: Optional[str] = None - memory_request: Optional[str] = None - memory_limit: Optional[str] = None - - -class JobType(BaseModel): - __root__: Literal[ - "get_spec", - "check_connection", - "discover_schema", - "sync", - "reset_connection", - "connection_updater", - "replicate", - ] = Field( - ..., - description="enum that describes the different types of jobs that the platform runs.", - title="JobType", - ) - - -class AllowedHosts(BaseModel): - class Config: - extra = Extra.allow - - hosts: Optional[List[str]] = Field( - None, - description="An array of hosts that this connector can connect to. AllowedHosts not being present for the source or destination means that access to all hosts is allowed. An empty list here means that no network access is granted.", - ) - - -class SuggestedStreams(BaseModel): - class Config: - extra = Extra.allow - - streams: Optional[List[str]] = Field( - None, - description="An array of streams that this connector suggests the average user will want. SuggestedStreams not being present for the source means that all streams are suggested. An empty list here means that no streams are suggested.", - ) - - -class AirbyteInternal(BaseModel): - class Config: - extra = Extra.allow - - sl: Optional[Literal[0, 100, 200, 300]] = None - ql: Optional[Literal[0, 100, 200, 300, 400, 500, 600]] = None - isEnterprise: Optional[bool] = False - requireVersionIncrementsInPullRequests: Optional[bool] = Field( - True, - description="When false, version increment checks will be skipped for this connector", - ) - - -class GitInfo(BaseModel): - class Config: - extra = Extra.forbid - - commit_sha: Optional[str] = Field( - None, - description="The git commit sha of the last commit that modified this file.", - ) - commit_timestamp: Optional[datetime] = Field( - None, - description="The git commit timestamp of the last commit that modified this file.", - ) - commit_author: Optional[str] = Field( - None, - description="The git commit author of the last commit that modified this file.", - ) - commit_author_email: Optional[str] = Field( - None, - description="The git commit author email of the last commit that modified this file.", - ) - - -class SourceFileInfo(BaseModel): - metadata_etag: Optional[str] = None - metadata_file_path: Optional[str] = None - metadata_bucket_name: Optional[str] = None - metadata_last_modified: Optional[str] = None - registry_entry_generated_at: Optional[str] = None - - -class ConnectorMetrics(BaseModel): - all: Optional[Any] = None - cloud: Optional[Any] = None - oss: Optional[Any] = None - - -class ConnectorMetric(BaseModel): - class Config: - extra = Extra.allow - - usage: Optional[Union[str, Literal["low", "medium", "high"]]] = None - sync_success_rate: Optional[Union[str, Literal["low", "medium", "high"]]] = None - connector_version: Optional[str] = None - - -class ConnectorPackageInfo(BaseModel): - cdk_version: Optional[str] = None - - -class NormalizationDestinationDefinitionConfig(BaseModel): - class Config: - extra = Extra.allow - - normalizationRepository: str = Field( - ..., - description="a field indicating the name of the repository to be used for normalization. If the value of the flag is NULL - normalization is not used.", - ) - normalizationTag: str = Field( - ..., - description="a field indicating the tag of the docker repository to be used for normalization.", - ) - normalizationIntegrationType: str = Field( - ..., - description="a field indicating the type of integration dialect to use for normalization.", - ) - - -class BreakingChangeScope(BaseModel): - __root__: StreamBreakingChangeScope = Field( - ..., - description="A scope that can be used to limit the impact of a breaking change.", - ) - - -class JobTypeResourceLimit(BaseModel): - class Config: - extra = Extra.forbid - - jobType: JobType - resourceRequirements: ResourceRequirements - - -class GeneratedFields(BaseModel): - git: Optional[GitInfo] = None - source_file_info: Optional[SourceFileInfo] = None - metrics: Optional[ConnectorMetrics] = None - sbomUrl: Optional[str] = Field(None, description="URL to the SBOM file") - - -class VersionBreakingChange(BaseModel): - class Config: - extra = Extra.forbid - - upgradeDeadline: date = Field( - ..., - description="The deadline by which to upgrade before the breaking change takes effect.", - ) - message: str = Field( - ..., description="Descriptive message detailing the breaking change." - ) - deadlineAction: Optional[Literal["auto_upgrade", "disable"]] = Field( - None, description="Action to do when the deadline is reached." - ) - migrationDocumentationUrl: Optional[AnyUrl] = Field( - None, - description="URL to documentation on how to migrate to the current version. Defaults to ${documentationUrl}-migrations#${version}", - ) - scopedImpact: Optional[List[BreakingChangeScope]] = Field( - None, - description="List of scopes that are impacted by the breaking change. If not specified, the breaking change cannot be scoped to reduce impact via the supported scope types.", - min_items=1, - ) - - -class ActorDefinitionResourceRequirements(BaseModel): - class Config: - extra = Extra.forbid - - default: Optional[ResourceRequirements] = Field( - None, - description="if set, these are the requirements that should be set for ALL jobs run for this actor definition.", - ) - jobSpecific: Optional[List[JobTypeResourceLimit]] = None - - -class ConnectorBreakingChanges(BaseModel): - class Config: - extra = Extra.forbid - - __root__: Dict[constr(regex=r"^\d+\.\d+\.\d+$"), VersionBreakingChange] = Field( - ..., - description="Each entry denotes a breaking change in a specific version of a connector that requires user action to upgrade.", - title="ConnectorBreakingChanges", - ) - - -class ConnectorRegistryReleases(BaseModel): - class Config: - extra = Extra.forbid - - releaseCandidates: Optional[ConnectorReleaseCandidates] = None - rolloutConfiguration: Optional[RolloutConfiguration] = None - breakingChanges: Optional[ConnectorBreakingChanges] = None - migrationDocumentationUrl: Optional[AnyUrl] = Field( - None, - description="URL to documentation on how to migrate from the previous version to the current version. Defaults to ${documentationUrl}-migrations", - ) - - -class ConnectorReleaseCandidates(BaseModel): - class Config: - extra = Extra.forbid - - __root__: Dict[ - constr(regex=r"^\d+\.\d+\.\d+(-[0-9A-Za-z-.]+)?$"), VersionReleaseCandidate - ] = Field( - ..., - description="Each entry denotes a release candidate version of a connector.", - ) - - -class VersionReleaseCandidate(BaseModel): - class Config: - extra = Extra.forbid - - __root__: Union[ - ConnectorRegistrySourceDefinition, ConnectorRegistryDestinationDefinition - ] = Field( - ..., - description="Contains information about a release candidate version of a connector.", - ) - - -class ConnectorRegistrySourceDefinition(BaseModel): - class Config: - extra = Extra.allow - - sourceDefinitionId: UUID - name: str - dockerRepository: str - dockerImageTag: str - documentationUrl: str - icon: Optional[str] = None - iconUrl: Optional[str] = None - sourceType: Optional[Literal["api", "file", "database", "custom"]] = None - spec: Dict[str, Any] - tombstone: Optional[bool] = Field( - False, - description="if false, the configuration is active. if true, then this configuration is permanently off.", - ) - public: Optional[bool] = Field( - False, - description="true if this connector definition is available to all workspaces", - ) - custom: Optional[bool] = Field( - False, description="whether this is a custom connector definition" - ) - releaseStage: Optional[ReleaseStage] = None - supportLevel: Optional[SupportLevel] = None - releaseDate: Optional[date] = Field( - None, - description="The date when this connector was first released, in yyyy-mm-dd format.", - ) - resourceRequirements: Optional[ActorDefinitionResourceRequirements] = None - protocolVersion: Optional[str] = Field( - None, description="the Airbyte Protocol version supported by the connector" - ) - allowedHosts: Optional[AllowedHosts] = None - suggestedStreams: Optional[SuggestedStreams] = None - maxSecondsBetweenMessages: Optional[int] = Field( - None, - description="Number of seconds allowed between 2 airbyte protocol messages. The source will timeout if this delay is reach", - ) - erdUrl: Optional[str] = Field( - None, description="The URL where you can visualize the ERD" - ) - releases: Optional[ConnectorRegistryReleases] = None - ab_internal: Optional[AirbyteInternal] = None - generated: Optional[GeneratedFields] = None - packageInfo: Optional[ConnectorPackageInfo] = None - language: Optional[str] = Field( - None, description="The language the connector is written in" - ) - supportsFileTransfer: Optional[bool] = False - supportsDataActivation: Optional[bool] = False - - -class ConnectorRegistryDestinationDefinition(BaseModel): - class Config: - extra = Extra.allow - - destinationDefinitionId: UUID - name: str - dockerRepository: str - dockerImageTag: str - documentationUrl: str - icon: Optional[str] = None - iconUrl: Optional[str] = None - spec: Dict[str, Any] - tombstone: Optional[bool] = Field( - False, - description="if false, the configuration is active. if true, then this configuration is permanently off.", - ) - public: Optional[bool] = Field( - False, - description="true if this connector definition is available to all workspaces", - ) - custom: Optional[bool] = Field( - False, description="whether this is a custom connector definition" - ) - releaseStage: Optional[ReleaseStage] = None - supportLevel: Optional[SupportLevel] = None - releaseDate: Optional[date] = Field( - None, - description="The date when this connector was first released, in yyyy-mm-dd format.", - ) - tags: Optional[List[str]] = Field( - None, - description="An array of tags that describe the connector. E.g: language:python, keyword:rds, etc.", - ) - resourceRequirements: Optional[ActorDefinitionResourceRequirements] = None - protocolVersion: Optional[str] = Field( - None, description="the Airbyte Protocol version supported by the connector" - ) - normalizationConfig: Optional[NormalizationDestinationDefinitionConfig] = None - supportsDbt: Optional[bool] = Field( - None, - description="an optional flag indicating whether DBT is used in the normalization. If the flag value is NULL - DBT is not used.", - ) - allowedHosts: Optional[AllowedHosts] = None - releases: Optional[ConnectorRegistryReleases] = None - ab_internal: Optional[AirbyteInternal] = None - supportsRefreshes: Optional[bool] = False - supportsFileTransfer: Optional[bool] = False - supportsDataActivation: Optional[bool] = False - generated: Optional[GeneratedFields] = None - packageInfo: Optional[ConnectorPackageInfo] = None - language: Optional[str] = Field( - None, description="The language the connector is written in" - ) - - -ConnectorRegistryReleases.update_forward_refs() -ConnectorReleaseCandidates.update_forward_refs() -VersionReleaseCandidate.update_forward_refs() diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistrySourceDefinition.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistrySourceDefinition.py deleted file mode 100644 index 17f6573ad80e..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistrySourceDefinition.py +++ /dev/null @@ -1,407 +0,0 @@ -# generated by datamodel-codegen: -# filename: ConnectorRegistrySourceDefinition.yaml - -from __future__ import annotations - -from datetime import date, datetime -from typing import Any, Dict, List, Optional, Union -from uuid import UUID - -from pydantic import AnyUrl, BaseModel, Extra, Field, conint, constr -from typing_extensions import Literal - - -class ReleaseStage(BaseModel): - __root__: Literal["alpha", "beta", "generally_available", "custom"] = Field( - ..., - description="enum that describes a connector's release stage", - title="ReleaseStage", - ) - - -class SupportLevel(BaseModel): - __root__: Literal["community", "certified", "archived"] = Field( - ..., - description="enum that describes a connector's release stage", - title="SupportLevel", - ) - - -class ResourceRequirements(BaseModel): - class Config: - extra = Extra.forbid - - cpu_request: Optional[str] = None - cpu_limit: Optional[str] = None - memory_request: Optional[str] = None - memory_limit: Optional[str] = None - - -class JobType(BaseModel): - __root__: Literal[ - "get_spec", - "check_connection", - "discover_schema", - "sync", - "reset_connection", - "connection_updater", - "replicate", - ] = Field( - ..., - description="enum that describes the different types of jobs that the platform runs.", - title="JobType", - ) - - -class AllowedHosts(BaseModel): - class Config: - extra = Extra.allow - - hosts: Optional[List[str]] = Field( - None, - description="An array of hosts that this connector can connect to. AllowedHosts not being present for the source or destination means that access to all hosts is allowed. An empty list here means that no network access is granted.", - ) - - -class SuggestedStreams(BaseModel): - class Config: - extra = Extra.allow - - streams: Optional[List[str]] = Field( - None, - description="An array of streams that this connector suggests the average user will want. SuggestedStreams not being present for the source means that all streams are suggested. An empty list here means that no streams are suggested.", - ) - - -class RolloutConfiguration(BaseModel): - class Config: - extra = Extra.forbid - - enableProgressiveRollout: Optional[bool] = Field( - False, description="Whether to enable progressive rollout for the connector." - ) - initialPercentage: Optional[conint(ge=0, le=100)] = Field( - 0, - description="The percentage of users that should receive the new version initially.", - ) - maxPercentage: Optional[conint(ge=0, le=100)] = Field( - 50, - description="The percentage of users who should receive the release candidate during the test phase before full rollout.", - ) - advanceDelayMinutes: Optional[conint(ge=10)] = Field( - 10, - description="The number of minutes to wait before advancing the rollout percentage.", - ) - - -class StreamBreakingChangeScope(BaseModel): - class Config: - extra = Extra.forbid - - scopeType: str = Field("stream", const=True) - impactedScopes: List[str] = Field( - ..., - description="List of streams that are impacted by the breaking change.", - min_items=1, - ) - - -class NormalizationDestinationDefinitionConfig(BaseModel): - class Config: - extra = Extra.allow - - normalizationRepository: str = Field( - ..., - description="a field indicating the name of the repository to be used for normalization. If the value of the flag is NULL - normalization is not used.", - ) - normalizationTag: str = Field( - ..., - description="a field indicating the tag of the docker repository to be used for normalization.", - ) - normalizationIntegrationType: str = Field( - ..., - description="a field indicating the type of integration dialect to use for normalization.", - ) - - -class AirbyteInternal(BaseModel): - class Config: - extra = Extra.allow - - sl: Optional[Literal[0, 100, 200, 300]] = None - ql: Optional[Literal[0, 100, 200, 300, 400, 500, 600]] = None - isEnterprise: Optional[bool] = False - requireVersionIncrementsInPullRequests: Optional[bool] = Field( - True, - description="When false, version increment checks will be skipped for this connector", - ) - - -class GitInfo(BaseModel): - class Config: - extra = Extra.forbid - - commit_sha: Optional[str] = Field( - None, - description="The git commit sha of the last commit that modified this file.", - ) - commit_timestamp: Optional[datetime] = Field( - None, - description="The git commit timestamp of the last commit that modified this file.", - ) - commit_author: Optional[str] = Field( - None, - description="The git commit author of the last commit that modified this file.", - ) - commit_author_email: Optional[str] = Field( - None, - description="The git commit author email of the last commit that modified this file.", - ) - - -class SourceFileInfo(BaseModel): - metadata_etag: Optional[str] = None - metadata_file_path: Optional[str] = None - metadata_bucket_name: Optional[str] = None - metadata_last_modified: Optional[str] = None - registry_entry_generated_at: Optional[str] = None - - -class ConnectorMetrics(BaseModel): - all: Optional[Any] = None - cloud: Optional[Any] = None - oss: Optional[Any] = None - - -class ConnectorMetric(BaseModel): - class Config: - extra = Extra.allow - - usage: Optional[Union[str, Literal["low", "medium", "high"]]] = None - sync_success_rate: Optional[Union[str, Literal["low", "medium", "high"]]] = None - connector_version: Optional[str] = None - - -class ConnectorPackageInfo(BaseModel): - cdk_version: Optional[str] = None - - -class JobTypeResourceLimit(BaseModel): - class Config: - extra = Extra.forbid - - jobType: JobType - resourceRequirements: ResourceRequirements - - -class BreakingChangeScope(BaseModel): - __root__: StreamBreakingChangeScope = Field( - ..., - description="A scope that can be used to limit the impact of a breaking change.", - ) - - -class GeneratedFields(BaseModel): - git: Optional[GitInfo] = None - source_file_info: Optional[SourceFileInfo] = None - metrics: Optional[ConnectorMetrics] = None - sbomUrl: Optional[str] = Field(None, description="URL to the SBOM file") - - -class ActorDefinitionResourceRequirements(BaseModel): - class Config: - extra = Extra.forbid - - default: Optional[ResourceRequirements] = Field( - None, - description="if set, these are the requirements that should be set for ALL jobs run for this actor definition.", - ) - jobSpecific: Optional[List[JobTypeResourceLimit]] = None - - -class VersionBreakingChange(BaseModel): - class Config: - extra = Extra.forbid - - upgradeDeadline: date = Field( - ..., - description="The deadline by which to upgrade before the breaking change takes effect.", - ) - message: str = Field( - ..., description="Descriptive message detailing the breaking change." - ) - deadlineAction: Optional[Literal["auto_upgrade", "disable"]] = Field( - None, description="Action to do when the deadline is reached." - ) - migrationDocumentationUrl: Optional[AnyUrl] = Field( - None, - description="URL to documentation on how to migrate to the current version. Defaults to ${documentationUrl}-migrations#${version}", - ) - scopedImpact: Optional[List[BreakingChangeScope]] = Field( - None, - description="List of scopes that are impacted by the breaking change. If not specified, the breaking change cannot be scoped to reduce impact via the supported scope types.", - min_items=1, - ) - - -class ConnectorBreakingChanges(BaseModel): - class Config: - extra = Extra.forbid - - __root__: Dict[constr(regex=r"^\d+\.\d+\.\d+$"), VersionBreakingChange] = Field( - ..., - description="Each entry denotes a breaking change in a specific version of a connector that requires user action to upgrade.", - title="ConnectorBreakingChanges", - ) - - -class ConnectorRegistrySourceDefinition(BaseModel): - class Config: - extra = Extra.allow - - sourceDefinitionId: UUID - name: str - dockerRepository: str - dockerImageTag: str - documentationUrl: str - icon: Optional[str] = None - iconUrl: Optional[str] = None - sourceType: Optional[Literal["api", "file", "database", "custom"]] = None - spec: Dict[str, Any] - tombstone: Optional[bool] = Field( - False, - description="if false, the configuration is active. if true, then this configuration is permanently off.", - ) - public: Optional[bool] = Field( - False, - description="true if this connector definition is available to all workspaces", - ) - custom: Optional[bool] = Field( - False, description="whether this is a custom connector definition" - ) - releaseStage: Optional[ReleaseStage] = None - supportLevel: Optional[SupportLevel] = None - releaseDate: Optional[date] = Field( - None, - description="The date when this connector was first released, in yyyy-mm-dd format.", - ) - resourceRequirements: Optional[ActorDefinitionResourceRequirements] = None - protocolVersion: Optional[str] = Field( - None, description="the Airbyte Protocol version supported by the connector" - ) - allowedHosts: Optional[AllowedHosts] = None - suggestedStreams: Optional[SuggestedStreams] = None - maxSecondsBetweenMessages: Optional[int] = Field( - None, - description="Number of seconds allowed between 2 airbyte protocol messages. The source will timeout if this delay is reach", - ) - erdUrl: Optional[str] = Field( - None, description="The URL where you can visualize the ERD" - ) - releases: Optional[ConnectorRegistryReleases] = None - ab_internal: Optional[AirbyteInternal] = None - generated: Optional[GeneratedFields] = None - packageInfo: Optional[ConnectorPackageInfo] = None - language: Optional[str] = Field( - None, description="The language the connector is written in" - ) - supportsFileTransfer: Optional[bool] = False - supportsDataActivation: Optional[bool] = False - - -class ConnectorRegistryReleases(BaseModel): - class Config: - extra = Extra.forbid - - releaseCandidates: Optional[ConnectorReleaseCandidates] = None - rolloutConfiguration: Optional[RolloutConfiguration] = None - breakingChanges: Optional[ConnectorBreakingChanges] = None - migrationDocumentationUrl: Optional[AnyUrl] = Field( - None, - description="URL to documentation on how to migrate from the previous version to the current version. Defaults to ${documentationUrl}-migrations", - ) - - -class ConnectorReleaseCandidates(BaseModel): - class Config: - extra = Extra.forbid - - __root__: Dict[ - constr(regex=r"^\d+\.\d+\.\d+(-[0-9A-Za-z-.]+)?$"), VersionReleaseCandidate - ] = Field( - ..., - description="Each entry denotes a release candidate version of a connector.", - ) - - -class VersionReleaseCandidate(BaseModel): - class Config: - extra = Extra.forbid - - __root__: Union[ - ConnectorRegistrySourceDefinition, ConnectorRegistryDestinationDefinition - ] = Field( - ..., - description="Contains information about a release candidate version of a connector.", - ) - - -class ConnectorRegistryDestinationDefinition(BaseModel): - class Config: - extra = Extra.allow - - destinationDefinitionId: UUID - name: str - dockerRepository: str - dockerImageTag: str - documentationUrl: str - icon: Optional[str] = None - iconUrl: Optional[str] = None - spec: Dict[str, Any] - tombstone: Optional[bool] = Field( - False, - description="if false, the configuration is active. if true, then this configuration is permanently off.", - ) - public: Optional[bool] = Field( - False, - description="true if this connector definition is available to all workspaces", - ) - custom: Optional[bool] = Field( - False, description="whether this is a custom connector definition" - ) - releaseStage: Optional[ReleaseStage] = None - supportLevel: Optional[SupportLevel] = None - releaseDate: Optional[date] = Field( - None, - description="The date when this connector was first released, in yyyy-mm-dd format.", - ) - tags: Optional[List[str]] = Field( - None, - description="An array of tags that describe the connector. E.g: language:python, keyword:rds, etc.", - ) - resourceRequirements: Optional[ActorDefinitionResourceRequirements] = None - protocolVersion: Optional[str] = Field( - None, description="the Airbyte Protocol version supported by the connector" - ) - normalizationConfig: Optional[NormalizationDestinationDefinitionConfig] = None - supportsDbt: Optional[bool] = Field( - None, - description="an optional flag indicating whether DBT is used in the normalization. If the flag value is NULL - DBT is not used.", - ) - allowedHosts: Optional[AllowedHosts] = None - releases: Optional[ConnectorRegistryReleases] = None - ab_internal: Optional[AirbyteInternal] = None - supportsRefreshes: Optional[bool] = False - supportsFileTransfer: Optional[bool] = False - supportsDataActivation: Optional[bool] = False - generated: Optional[GeneratedFields] = None - packageInfo: Optional[ConnectorPackageInfo] = None - language: Optional[str] = Field( - None, description="The language the connector is written in" - ) - - -ConnectorRegistrySourceDefinition.update_forward_refs() -ConnectorRegistryReleases.update_forward_refs() -ConnectorReleaseCandidates.update_forward_refs() -VersionReleaseCandidate.update_forward_refs() diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistryV0.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistryV0.py deleted file mode 100644 index c57c9684ede9..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorRegistryV0.py +++ /dev/null @@ -1,413 +0,0 @@ -# generated by datamodel-codegen: -# filename: ConnectorRegistryV0.yaml - -from __future__ import annotations - -from datetime import date, datetime -from typing import Any, Dict, List, Optional, Union -from uuid import UUID - -from pydantic import AnyUrl, BaseModel, Extra, Field, conint, constr -from typing_extensions import Literal - - -class ReleaseStage(BaseModel): - __root__: Literal["alpha", "beta", "generally_available", "custom"] = Field( - ..., - description="enum that describes a connector's release stage", - title="ReleaseStage", - ) - - -class SupportLevel(BaseModel): - __root__: Literal["community", "certified", "archived"] = Field( - ..., - description="enum that describes a connector's release stage", - title="SupportLevel", - ) - - -class ResourceRequirements(BaseModel): - class Config: - extra = Extra.forbid - - cpu_request: Optional[str] = None - cpu_limit: Optional[str] = None - memory_request: Optional[str] = None - memory_limit: Optional[str] = None - - -class JobType(BaseModel): - __root__: Literal[ - "get_spec", - "check_connection", - "discover_schema", - "sync", - "reset_connection", - "connection_updater", - "replicate", - ] = Field( - ..., - description="enum that describes the different types of jobs that the platform runs.", - title="JobType", - ) - - -class NormalizationDestinationDefinitionConfig(BaseModel): - class Config: - extra = Extra.allow - - normalizationRepository: str = Field( - ..., - description="a field indicating the name of the repository to be used for normalization. If the value of the flag is NULL - normalization is not used.", - ) - normalizationTag: str = Field( - ..., - description="a field indicating the tag of the docker repository to be used for normalization.", - ) - normalizationIntegrationType: str = Field( - ..., - description="a field indicating the type of integration dialect to use for normalization.", - ) - - -class AllowedHosts(BaseModel): - class Config: - extra = Extra.allow - - hosts: Optional[List[str]] = Field( - None, - description="An array of hosts that this connector can connect to. AllowedHosts not being present for the source or destination means that access to all hosts is allowed. An empty list here means that no network access is granted.", - ) - - -class RolloutConfiguration(BaseModel): - class Config: - extra = Extra.forbid - - enableProgressiveRollout: Optional[bool] = Field( - False, description="Whether to enable progressive rollout for the connector." - ) - initialPercentage: Optional[conint(ge=0, le=100)] = Field( - 0, - description="The percentage of users that should receive the new version initially.", - ) - maxPercentage: Optional[conint(ge=0, le=100)] = Field( - 50, - description="The percentage of users who should receive the release candidate during the test phase before full rollout.", - ) - advanceDelayMinutes: Optional[conint(ge=10)] = Field( - 10, - description="The number of minutes to wait before advancing the rollout percentage.", - ) - - -class StreamBreakingChangeScope(BaseModel): - class Config: - extra = Extra.forbid - - scopeType: str = Field("stream", const=True) - impactedScopes: List[str] = Field( - ..., - description="List of streams that are impacted by the breaking change.", - min_items=1, - ) - - -class SuggestedStreams(BaseModel): - class Config: - extra = Extra.allow - - streams: Optional[List[str]] = Field( - None, - description="An array of streams that this connector suggests the average user will want. SuggestedStreams not being present for the source means that all streams are suggested. An empty list here means that no streams are suggested.", - ) - - -class AirbyteInternal(BaseModel): - class Config: - extra = Extra.allow - - sl: Optional[Literal[0, 100, 200, 300]] = None - ql: Optional[Literal[0, 100, 200, 300, 400, 500, 600]] = None - isEnterprise: Optional[bool] = False - requireVersionIncrementsInPullRequests: Optional[bool] = Field( - True, - description="When false, version increment checks will be skipped for this connector", - ) - - -class GitInfo(BaseModel): - class Config: - extra = Extra.forbid - - commit_sha: Optional[str] = Field( - None, - description="The git commit sha of the last commit that modified this file.", - ) - commit_timestamp: Optional[datetime] = Field( - None, - description="The git commit timestamp of the last commit that modified this file.", - ) - commit_author: Optional[str] = Field( - None, - description="The git commit author of the last commit that modified this file.", - ) - commit_author_email: Optional[str] = Field( - None, - description="The git commit author email of the last commit that modified this file.", - ) - - -class SourceFileInfo(BaseModel): - metadata_etag: Optional[str] = None - metadata_file_path: Optional[str] = None - metadata_bucket_name: Optional[str] = None - metadata_last_modified: Optional[str] = None - registry_entry_generated_at: Optional[str] = None - - -class ConnectorMetrics(BaseModel): - all: Optional[Any] = None - cloud: Optional[Any] = None - oss: Optional[Any] = None - - -class ConnectorMetric(BaseModel): - class Config: - extra = Extra.allow - - usage: Optional[Union[str, Literal["low", "medium", "high"]]] = None - sync_success_rate: Optional[Union[str, Literal["low", "medium", "high"]]] = None - connector_version: Optional[str] = None - - -class ConnectorPackageInfo(BaseModel): - cdk_version: Optional[str] = None - - -class JobTypeResourceLimit(BaseModel): - class Config: - extra = Extra.forbid - - jobType: JobType - resourceRequirements: ResourceRequirements - - -class BreakingChangeScope(BaseModel): - __root__: StreamBreakingChangeScope = Field( - ..., - description="A scope that can be used to limit the impact of a breaking change.", - ) - - -class GeneratedFields(BaseModel): - git: Optional[GitInfo] = None - source_file_info: Optional[SourceFileInfo] = None - metrics: Optional[ConnectorMetrics] = None - sbomUrl: Optional[str] = Field(None, description="URL to the SBOM file") - - -class ActorDefinitionResourceRequirements(BaseModel): - class Config: - extra = Extra.forbid - - default: Optional[ResourceRequirements] = Field( - None, - description="if set, these are the requirements that should be set for ALL jobs run for this actor definition.", - ) - jobSpecific: Optional[List[JobTypeResourceLimit]] = None - - -class VersionBreakingChange(BaseModel): - class Config: - extra = Extra.forbid - - upgradeDeadline: date = Field( - ..., - description="The deadline by which to upgrade before the breaking change takes effect.", - ) - message: str = Field( - ..., description="Descriptive message detailing the breaking change." - ) - deadlineAction: Optional[Literal["auto_upgrade", "disable"]] = Field( - None, description="Action to do when the deadline is reached." - ) - migrationDocumentationUrl: Optional[AnyUrl] = Field( - None, - description="URL to documentation on how to migrate to the current version. Defaults to ${documentationUrl}-migrations#${version}", - ) - scopedImpact: Optional[List[BreakingChangeScope]] = Field( - None, - description="List of scopes that are impacted by the breaking change. If not specified, the breaking change cannot be scoped to reduce impact via the supported scope types.", - min_items=1, - ) - - -class ConnectorBreakingChanges(BaseModel): - class Config: - extra = Extra.forbid - - __root__: Dict[constr(regex=r"^\d+\.\d+\.\d+$"), VersionBreakingChange] = Field( - ..., - description="Each entry denotes a breaking change in a specific version of a connector that requires user action to upgrade.", - title="ConnectorBreakingChanges", - ) - - -class ConnectorRegistryV0(BaseModel): - destinations: List[ConnectorRegistryDestinationDefinition] - sources: List[ConnectorRegistrySourceDefinition] - - -class ConnectorRegistryDestinationDefinition(BaseModel): - class Config: - extra = Extra.allow - - destinationDefinitionId: UUID - name: str - dockerRepository: str - dockerImageTag: str - documentationUrl: str - icon: Optional[str] = None - iconUrl: Optional[str] = None - spec: Dict[str, Any] - tombstone: Optional[bool] = Field( - False, - description="if false, the configuration is active. if true, then this configuration is permanently off.", - ) - public: Optional[bool] = Field( - False, - description="true if this connector definition is available to all workspaces", - ) - custom: Optional[bool] = Field( - False, description="whether this is a custom connector definition" - ) - releaseStage: Optional[ReleaseStage] = None - supportLevel: Optional[SupportLevel] = None - releaseDate: Optional[date] = Field( - None, - description="The date when this connector was first released, in yyyy-mm-dd format.", - ) - tags: Optional[List[str]] = Field( - None, - description="An array of tags that describe the connector. E.g: language:python, keyword:rds, etc.", - ) - resourceRequirements: Optional[ActorDefinitionResourceRequirements] = None - protocolVersion: Optional[str] = Field( - None, description="the Airbyte Protocol version supported by the connector" - ) - normalizationConfig: Optional[NormalizationDestinationDefinitionConfig] = None - supportsDbt: Optional[bool] = Field( - None, - description="an optional flag indicating whether DBT is used in the normalization. If the flag value is NULL - DBT is not used.", - ) - allowedHosts: Optional[AllowedHosts] = None - releases: Optional[ConnectorRegistryReleases] = None - ab_internal: Optional[AirbyteInternal] = None - supportsRefreshes: Optional[bool] = False - supportsFileTransfer: Optional[bool] = False - supportsDataActivation: Optional[bool] = False - generated: Optional[GeneratedFields] = None - packageInfo: Optional[ConnectorPackageInfo] = None - language: Optional[str] = Field( - None, description="The language the connector is written in" - ) - - -class ConnectorRegistryReleases(BaseModel): - class Config: - extra = Extra.forbid - - releaseCandidates: Optional[ConnectorReleaseCandidates] = None - rolloutConfiguration: Optional[RolloutConfiguration] = None - breakingChanges: Optional[ConnectorBreakingChanges] = None - migrationDocumentationUrl: Optional[AnyUrl] = Field( - None, - description="URL to documentation on how to migrate from the previous version to the current version. Defaults to ${documentationUrl}-migrations", - ) - - -class ConnectorReleaseCandidates(BaseModel): - class Config: - extra = Extra.forbid - - __root__: Dict[ - constr(regex=r"^\d+\.\d+\.\d+(-[0-9A-Za-z-.]+)?$"), VersionReleaseCandidate - ] = Field( - ..., - description="Each entry denotes a release candidate version of a connector.", - ) - - -class VersionReleaseCandidate(BaseModel): - class Config: - extra = Extra.forbid - - __root__: Union[ - ConnectorRegistrySourceDefinition, ConnectorRegistryDestinationDefinition - ] = Field( - ..., - description="Contains information about a release candidate version of a connector.", - ) - - -class ConnectorRegistrySourceDefinition(BaseModel): - class Config: - extra = Extra.allow - - sourceDefinitionId: UUID - name: str - dockerRepository: str - dockerImageTag: str - documentationUrl: str - icon: Optional[str] = None - iconUrl: Optional[str] = None - sourceType: Optional[Literal["api", "file", "database", "custom"]] = None - spec: Dict[str, Any] - tombstone: Optional[bool] = Field( - False, - description="if false, the configuration is active. if true, then this configuration is permanently off.", - ) - public: Optional[bool] = Field( - False, - description="true if this connector definition is available to all workspaces", - ) - custom: Optional[bool] = Field( - False, description="whether this is a custom connector definition" - ) - releaseStage: Optional[ReleaseStage] = None - supportLevel: Optional[SupportLevel] = None - releaseDate: Optional[date] = Field( - None, - description="The date when this connector was first released, in yyyy-mm-dd format.", - ) - resourceRequirements: Optional[ActorDefinitionResourceRequirements] = None - protocolVersion: Optional[str] = Field( - None, description="the Airbyte Protocol version supported by the connector" - ) - allowedHosts: Optional[AllowedHosts] = None - suggestedStreams: Optional[SuggestedStreams] = None - maxSecondsBetweenMessages: Optional[int] = Field( - None, - description="Number of seconds allowed between 2 airbyte protocol messages. The source will timeout if this delay is reach", - ) - erdUrl: Optional[str] = Field( - None, description="The URL where you can visualize the ERD" - ) - releases: Optional[ConnectorRegistryReleases] = None - ab_internal: Optional[AirbyteInternal] = None - generated: Optional[GeneratedFields] = None - packageInfo: Optional[ConnectorPackageInfo] = None - language: Optional[str] = Field( - None, description="The language the connector is written in" - ) - supportsFileTransfer: Optional[bool] = False - supportsDataActivation: Optional[bool] = False - - -ConnectorRegistryV0.update_forward_refs() -ConnectorRegistryDestinationDefinition.update_forward_refs() -ConnectorRegistryReleases.update_forward_refs() -ConnectorReleaseCandidates.update_forward_refs() -VersionReleaseCandidate.update_forward_refs() diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorReleases.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorReleases.py deleted file mode 100644 index 79ed85a208d9..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorReleases.py +++ /dev/null @@ -1,98 +0,0 @@ -# generated by datamodel-codegen: -# filename: ConnectorReleases.yaml - -from __future__ import annotations - -from datetime import date -from typing import Dict, List, Optional - -from pydantic import AnyUrl, BaseModel, Extra, Field, conint, constr -from typing_extensions import Literal - - -class RolloutConfiguration(BaseModel): - class Config: - extra = Extra.forbid - - enableProgressiveRollout: Optional[bool] = Field( - False, description="Whether to enable progressive rollout for the connector." - ) - initialPercentage: Optional[conint(ge=0, le=100)] = Field( - 0, - description="The percentage of users that should receive the new version initially.", - ) - maxPercentage: Optional[conint(ge=0, le=100)] = Field( - 50, - description="The percentage of users who should receive the release candidate during the test phase before full rollout.", - ) - advanceDelayMinutes: Optional[conint(ge=10)] = Field( - 10, - description="The number of minutes to wait before advancing the rollout percentage.", - ) - - -class StreamBreakingChangeScope(BaseModel): - class Config: - extra = Extra.forbid - - scopeType: str = Field("stream", const=True) - impactedScopes: List[str] = Field( - ..., - description="List of streams that are impacted by the breaking change.", - min_items=1, - ) - - -class BreakingChangeScope(BaseModel): - __root__: StreamBreakingChangeScope = Field( - ..., - description="A scope that can be used to limit the impact of a breaking change.", - ) - - -class VersionBreakingChange(BaseModel): - class Config: - extra = Extra.forbid - - upgradeDeadline: date = Field( - ..., - description="The deadline by which to upgrade before the breaking change takes effect.", - ) - message: str = Field( - ..., description="Descriptive message detailing the breaking change." - ) - deadlineAction: Optional[Literal["auto_upgrade", "disable"]] = Field( - None, description="Action to do when the deadline is reached." - ) - migrationDocumentationUrl: Optional[AnyUrl] = Field( - None, - description="URL to documentation on how to migrate to the current version. Defaults to ${documentationUrl}-migrations#${version}", - ) - scopedImpact: Optional[List[BreakingChangeScope]] = Field( - None, - description="List of scopes that are impacted by the breaking change. If not specified, the breaking change cannot be scoped to reduce impact via the supported scope types.", - min_items=1, - ) - - -class ConnectorBreakingChanges(BaseModel): - class Config: - extra = Extra.forbid - - __root__: Dict[constr(regex=r"^\d+\.\d+\.\d+$"), VersionBreakingChange] = Field( - ..., - description="Each entry denotes a breaking change in a specific version of a connector that requires user action to upgrade.", - title="ConnectorBreakingChanges", - ) - - -class ConnectorReleases(BaseModel): - class Config: - extra = Extra.forbid - - rolloutConfiguration: Optional[RolloutConfiguration] = None - breakingChanges: Optional[ConnectorBreakingChanges] = None - migrationDocumentationUrl: Optional[AnyUrl] = Field( - None, - description="URL to documentation on how to migrate from the previous version to the current version. Defaults to ${documentationUrl}-migrations", - ) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorTestSuiteOptions.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorTestSuiteOptions.py deleted file mode 100644 index a40b4094c818..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ConnectorTestSuiteOptions.py +++ /dev/null @@ -1,58 +0,0 @@ -# generated by datamodel-codegen: -# filename: ConnectorTestSuiteOptions.yaml - -from __future__ import annotations - -from typing import List, Optional - -from pydantic import BaseModel, Extra, Field -from typing_extensions import Literal - - -class SecretStore(BaseModel): - class Config: - extra = Extra.forbid - - alias: Optional[str] = Field( - None, - description="The alias of the secret store which can map to its actual secret address", - ) - type: Optional[Literal["GSM"]] = Field( - None, description="The type of the secret store" - ) - - -class TestConnections(BaseModel): - class Config: - extra = Extra.forbid - - name: str = Field(..., description="The connection name") - id: str = Field(..., description="The connection ID") - - -class Secret(BaseModel): - class Config: - extra = Extra.forbid - - name: str = Field(..., description="The secret name in the secret store") - fileName: Optional[str] = Field( - None, - description="The name of the file to which the secret value would be persisted", - ) - secretStore: SecretStore - - -class ConnectorTestSuiteOptions(BaseModel): - class Config: - extra = Extra.forbid - - suite: Literal["unitTests", "integrationTests", "acceptanceTests", "liveTests"] = ( - Field(..., description="Name of the configured test suite") - ) - testSecrets: Optional[List[Secret]] = Field( - None, description="List of secrets required to run the test suite" - ) - testConnections: Optional[List[TestConnections]] = Field( - None, - description="List of sandbox cloud connections that tests can be run against", - ) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/GeneratedFields.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/GeneratedFields.py deleted file mode 100644 index 62cfeadbe366..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/GeneratedFields.py +++ /dev/null @@ -1,62 +0,0 @@ -# generated by datamodel-codegen: -# filename: GeneratedFields.yaml - -from __future__ import annotations - -from datetime import datetime -from typing import Any, Optional, Union - -from pydantic import BaseModel, Extra, Field -from typing_extensions import Literal - - -class GitInfo(BaseModel): - class Config: - extra = Extra.forbid - - commit_sha: Optional[str] = Field( - None, - description="The git commit sha of the last commit that modified this file.", - ) - commit_timestamp: Optional[datetime] = Field( - None, - description="The git commit timestamp of the last commit that modified this file.", - ) - commit_author: Optional[str] = Field( - None, - description="The git commit author of the last commit that modified this file.", - ) - commit_author_email: Optional[str] = Field( - None, - description="The git commit author email of the last commit that modified this file.", - ) - - -class SourceFileInfo(BaseModel): - metadata_etag: Optional[str] = None - metadata_file_path: Optional[str] = None - metadata_bucket_name: Optional[str] = None - metadata_last_modified: Optional[str] = None - registry_entry_generated_at: Optional[str] = None - - -class ConnectorMetrics(BaseModel): - all: Optional[Any] = None - cloud: Optional[Any] = None - oss: Optional[Any] = None - - -class ConnectorMetric(BaseModel): - class Config: - extra = Extra.allow - - usage: Optional[Union[str, Literal["low", "medium", "high"]]] = None - sync_success_rate: Optional[Union[str, Literal["low", "medium", "high"]]] = None - connector_version: Optional[str] = None - - -class GeneratedFields(BaseModel): - git: Optional[GitInfo] = None - source_file_info: Optional[SourceFileInfo] = None - metrics: Optional[ConnectorMetrics] = None - sbomUrl: Optional[str] = Field(None, description="URL to the SBOM file") diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/GitInfo.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/GitInfo.py deleted file mode 100644 index 1e947b632188..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/GitInfo.py +++ /dev/null @@ -1,31 +0,0 @@ -# generated by datamodel-codegen: -# filename: GitInfo.yaml - -from __future__ import annotations - -from datetime import datetime -from typing import Optional - -from pydantic import BaseModel, Extra, Field - - -class GitInfo(BaseModel): - class Config: - extra = Extra.forbid - - commit_sha: Optional[str] = Field( - None, - description="The git commit sha of the last commit that modified this file.", - ) - commit_timestamp: Optional[datetime] = Field( - None, - description="The git commit timestamp of the last commit that modified this file.", - ) - commit_author: Optional[str] = Field( - None, - description="The git commit author of the last commit that modified this file.", - ) - commit_author_email: Optional[str] = Field( - None, - description="The git commit author email of the last commit that modified this file.", - ) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/JobType.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/JobType.py deleted file mode 100644 index aef4f7ad5f99..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/JobType.py +++ /dev/null @@ -1,23 +0,0 @@ -# generated by datamodel-codegen: -# filename: JobType.yaml - -from __future__ import annotations - -from pydantic import BaseModel, Field -from typing_extensions import Literal - - -class JobType(BaseModel): - __root__: Literal[ - "get_spec", - "check_connection", - "discover_schema", - "sync", - "reset_connection", - "connection_updater", - "replicate", - ] = Field( - ..., - description="enum that describes the different types of jobs that the platform runs.", - title="JobType", - ) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/NormalizationDestinationDefinitionConfig.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/NormalizationDestinationDefinitionConfig.py deleted file mode 100644 index 00a642bfaeb1..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/NormalizationDestinationDefinitionConfig.py +++ /dev/null @@ -1,24 +0,0 @@ -# generated by datamodel-codegen: -# filename: NormalizationDestinationDefinitionConfig.yaml - -from __future__ import annotations - -from pydantic import BaseModel, Extra, Field - - -class NormalizationDestinationDefinitionConfig(BaseModel): - class Config: - extra = Extra.allow - - normalizationRepository: str = Field( - ..., - description="a field indicating the name of the repository to be used for normalization. If the value of the flag is NULL - normalization is not used.", - ) - normalizationTag: str = Field( - ..., - description="a field indicating the tag of the docker repository to be used for normalization.", - ) - normalizationIntegrationType: str = Field( - ..., - description="a field indicating the type of integration dialect to use for normalization.", - ) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/RegistryOverrides.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/RegistryOverrides.py deleted file mode 100644 index eb6908bc65b2..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/RegistryOverrides.py +++ /dev/null @@ -1,111 +0,0 @@ -# generated by datamodel-codegen: -# filename: RegistryOverrides.yaml - -from __future__ import annotations - -from typing import List, Optional - -from pydantic import AnyUrl, BaseModel, Extra, Field -from typing_extensions import Literal - - -class AllowedHosts(BaseModel): - class Config: - extra = Extra.allow - - hosts: Optional[List[str]] = Field( - None, - description="An array of hosts that this connector can connect to. AllowedHosts not being present for the source or destination means that access to all hosts is allowed. An empty list here means that no network access is granted.", - ) - - -class NormalizationDestinationDefinitionConfig(BaseModel): - class Config: - extra = Extra.allow - - normalizationRepository: str = Field( - ..., - description="a field indicating the name of the repository to be used for normalization. If the value of the flag is NULL - normalization is not used.", - ) - normalizationTag: str = Field( - ..., - description="a field indicating the tag of the docker repository to be used for normalization.", - ) - normalizationIntegrationType: str = Field( - ..., - description="a field indicating the type of integration dialect to use for normalization.", - ) - - -class SuggestedStreams(BaseModel): - class Config: - extra = Extra.allow - - streams: Optional[List[str]] = Field( - None, - description="An array of streams that this connector suggests the average user will want. SuggestedStreams not being present for the source means that all streams are suggested. An empty list here means that no streams are suggested.", - ) - - -class ResourceRequirements(BaseModel): - class Config: - extra = Extra.forbid - - cpu_request: Optional[str] = None - cpu_limit: Optional[str] = None - memory_request: Optional[str] = None - memory_limit: Optional[str] = None - - -class JobType(BaseModel): - __root__: Literal[ - "get_spec", - "check_connection", - "discover_schema", - "sync", - "reset_connection", - "connection_updater", - "replicate", - ] = Field( - ..., - description="enum that describes the different types of jobs that the platform runs.", - title="JobType", - ) - - -class JobTypeResourceLimit(BaseModel): - class Config: - extra = Extra.forbid - - jobType: JobType - resourceRequirements: ResourceRequirements - - -class ActorDefinitionResourceRequirements(BaseModel): - class Config: - extra = Extra.forbid - - default: Optional[ResourceRequirements] = Field( - None, - description="if set, these are the requirements that should be set for ALL jobs run for this actor definition.", - ) - jobSpecific: Optional[List[JobTypeResourceLimit]] = None - - -class RegistryOverrides(BaseModel): - class Config: - extra = Extra.forbid - - enabled: bool - name: Optional[str] = None - dockerRepository: Optional[str] = None - dockerImageTag: Optional[str] = None - supportsDbt: Optional[bool] = None - supportsNormalization: Optional[bool] = None - license: Optional[str] = None - documentationUrl: Optional[AnyUrl] = None - connectorSubtype: Optional[str] = None - allowedHosts: Optional[AllowedHosts] = None - normalizationConfig: Optional[NormalizationDestinationDefinitionConfig] = None - suggestedStreams: Optional[SuggestedStreams] = None - resourceRequirements: Optional[ActorDefinitionResourceRequirements] = None diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ReleaseStage.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ReleaseStage.py deleted file mode 100644 index cb7c9b909b0b..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ReleaseStage.py +++ /dev/null @@ -1,15 +0,0 @@ -# generated by datamodel-codegen: -# filename: ReleaseStage.yaml - -from __future__ import annotations - -from pydantic import BaseModel, Field -from typing_extensions import Literal - - -class ReleaseStage(BaseModel): - __root__: Literal["alpha", "beta", "generally_available", "custom"] = Field( - ..., - description="enum that describes a connector's release stage", - title="ReleaseStage", - ) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/RemoteRegistries.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/RemoteRegistries.py deleted file mode 100644 index b44447eb9c76..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/RemoteRegistries.py +++ /dev/null @@ -1,23 +0,0 @@ -# generated by datamodel-codegen: -# filename: RemoteRegistries.yaml - -from __future__ import annotations - -from typing import Optional - -from pydantic import BaseModel, Extra, Field - - -class PyPi(BaseModel): - class Config: - extra = Extra.forbid - - enabled: bool - packageName: str = Field(..., description="The name of the package on PyPi.") - - -class RemoteRegistries(BaseModel): - class Config: - extra = Extra.forbid - - pypi: Optional[PyPi] = None diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ResourceRequirements.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ResourceRequirements.py deleted file mode 100644 index abc7e6173d05..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/ResourceRequirements.py +++ /dev/null @@ -1,18 +0,0 @@ -# generated by datamodel-codegen: -# filename: ResourceRequirements.yaml - -from __future__ import annotations - -from typing import Optional - -from pydantic import BaseModel, Extra - - -class ResourceRequirements(BaseModel): - class Config: - extra = Extra.forbid - - cpu_request: Optional[str] = None - cpu_limit: Optional[str] = None - memory_request: Optional[str] = None - memory_limit: Optional[str] = None diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/RolloutConfiguration.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/RolloutConfiguration.py deleted file mode 100644 index ceebd789da84..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/RolloutConfiguration.py +++ /dev/null @@ -1,29 +0,0 @@ -# generated by datamodel-codegen: -# filename: RolloutConfiguration.yaml - -from __future__ import annotations - -from typing import Optional - -from pydantic import BaseModel, Extra, Field, conint - - -class RolloutConfiguration(BaseModel): - class Config: - extra = Extra.forbid - - enableProgressiveRollout: Optional[bool] = Field( - False, description="Whether to enable progressive rollout for the connector." - ) - initialPercentage: Optional[conint(ge=0, le=100)] = Field( - 0, - description="The percentage of users that should receive the new version initially.", - ) - maxPercentage: Optional[conint(ge=0, le=100)] = Field( - 50, - description="The percentage of users who should receive the release candidate during the test phase before full rollout.", - ) - advanceDelayMinutes: Optional[conint(ge=10)] = Field( - 10, - description="The number of minutes to wait before advancing the rollout percentage.", - ) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/Secret.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/Secret.py deleted file mode 100644 index ee6498906619..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/Secret.py +++ /dev/null @@ -1,34 +0,0 @@ -# generated by datamodel-codegen: -# filename: Secret.yaml - -from __future__ import annotations - -from typing import Optional - -from pydantic import BaseModel, Extra, Field -from typing_extensions import Literal - - -class SecretStore(BaseModel): - class Config: - extra = Extra.forbid - - alias: Optional[str] = Field( - None, - description="The alias of the secret store which can map to its actual secret address", - ) - type: Optional[Literal["GSM"]] = Field( - None, description="The type of the secret store" - ) - - -class Secret(BaseModel): - class Config: - extra = Extra.forbid - - name: str = Field(..., description="The secret name in the secret store") - fileName: Optional[str] = Field( - None, - description="The name of the file to which the secret value would be persisted", - ) - secretStore: SecretStore diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SecretStore.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SecretStore.py deleted file mode 100644 index a8df2ec03b11..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SecretStore.py +++ /dev/null @@ -1,22 +0,0 @@ -# generated by datamodel-codegen: -# filename: SecretStore.yaml - -from __future__ import annotations - -from typing import Optional - -from pydantic import BaseModel, Extra, Field -from typing_extensions import Literal - - -class SecretStore(BaseModel): - class Config: - extra = Extra.forbid - - alias: Optional[str] = Field( - None, - description="The alias of the secret store which can map to its actual secret address", - ) - type: Optional[Literal["GSM"]] = Field( - None, description="The type of the secret store" - ) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SourceFileInfo.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SourceFileInfo.py deleted file mode 100644 index ad3d859338b5..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SourceFileInfo.py +++ /dev/null @@ -1,16 +0,0 @@ -# generated by datamodel-codegen: -# filename: SourceFileInfo.yaml - -from __future__ import annotations - -from typing import Optional - -from pydantic import BaseModel - - -class SourceFileInfo(BaseModel): - metadata_etag: Optional[str] = None - metadata_file_path: Optional[str] = None - metadata_bucket_name: Optional[str] = None - metadata_last_modified: Optional[str] = None - registry_entry_generated_at: Optional[str] = None diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SuggestedStreams.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SuggestedStreams.py deleted file mode 100644 index 9a3d7cdf4012..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SuggestedStreams.py +++ /dev/null @@ -1,18 +0,0 @@ -# generated by datamodel-codegen: -# filename: SuggestedStreams.yaml - -from __future__ import annotations - -from typing import List, Optional - -from pydantic import BaseModel, Extra, Field - - -class SuggestedStreams(BaseModel): - class Config: - extra = Extra.allow - - streams: Optional[List[str]] = Field( - None, - description="An array of streams that this connector suggests the average user will want. SuggestedStreams not being present for the source means that all streams are suggested. An empty list here means that no streams are suggested.", - ) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SupportLevel.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SupportLevel.py deleted file mode 100644 index 7c5e001789f3..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/SupportLevel.py +++ /dev/null @@ -1,15 +0,0 @@ -# generated by datamodel-codegen: -# filename: SupportLevel.yaml - -from __future__ import annotations - -from pydantic import BaseModel, Field -from typing_extensions import Literal - - -class SupportLevel(BaseModel): - __root__: Literal["community", "certified", "archived"] = Field( - ..., - description="enum that describes a connector's release stage", - title="SupportLevel", - ) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/TestConnections.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/TestConnections.py deleted file mode 100644 index 47f65d3462b0..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/TestConnections.py +++ /dev/null @@ -1,14 +0,0 @@ -# generated by datamodel-codegen: -# filename: TestConnections.yaml - -from __future__ import annotations - -from pydantic import BaseModel, Extra, Field - - -class TestConnections(BaseModel): - class Config: - extra = Extra.forbid - - name: str = Field(..., description="The connection name") - id: str = Field(..., description="The connection ID") diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/__init__.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/__init__.py deleted file mode 100644 index 3877faa22716..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/generated/__init__.py +++ /dev/null @@ -1,31 +0,0 @@ -# generated by generate-metadata-models -from .ActorDefinitionResourceRequirements import * -from .AirbyteInternal import * -from .AllowedHosts import * -from .ConnectorBreakingChanges import * -from .ConnectorBuildOptions import * -from .ConnectorIPCOptions import * -from .ConnectorMetadataDefinitionV0 import * -from .ConnectorMetrics import * -from .ConnectorPackageInfo import * -from .ConnectorRegistryDestinationDefinition import * -from .ConnectorRegistryReleases import * -from .ConnectorRegistrySourceDefinition import * -from .ConnectorRegistryV0 import * -from .ConnectorReleases import * -from .ConnectorTestSuiteOptions import * -from .GeneratedFields import * -from .GitInfo import * -from .JobType import * -from .NormalizationDestinationDefinitionConfig import * -from .RegistryOverrides import * -from .ReleaseStage import * -from .RemoteRegistries import * -from .ResourceRequirements import * -from .RolloutConfiguration import * -from .Secret import * -from .SecretStore import * -from .SourceFileInfo import * -from .SuggestedStreams import * -from .SupportLevel import * -from .TestConnections import * diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ActorDefinitionResourceRequirements.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ActorDefinitionResourceRequirements.yaml deleted file mode 100644 index f9ea5817c1ca..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ActorDefinitionResourceRequirements.yaml +++ /dev/null @@ -1,30 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ActorDefinitionResourceRequirements.yaml -title: ActorDefinitionResourceRequirements -description: actor definition specific resource requirements -type: object -# set to false because we need the validations on seeds to be strict. otherwise, we will just add whatever is in the seed file into the db. -additionalProperties: false -properties: - default: - description: if set, these are the requirements that should be set for ALL jobs run for this actor definition. - "$ref": ResourceRequirements.yaml - jobSpecific: - type: array - items: - "$ref": "#/definitions/JobTypeResourceLimit" -definitions: - JobTypeResourceLimit: - description: sets resource requirements for a specific job type for an actor definition. these values override the default, if both are set. - type: object - # set to false because we need the validations on seeds to be strict. otherwise, we will just add whatever is in the seed file into the db. - additionalProperties: false - required: - - jobType - - resourceRequirements - properties: - jobType: - "$ref": JobType.yaml - resourceRequirements: - "$ref": ResourceRequirements.yaml diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/AirbyteInternal.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/AirbyteInternal.yaml deleted file mode 100644 index 4d310406c8e1..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/AirbyteInternal.yaml +++ /dev/null @@ -1,32 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/AirbyteInternal.yml -title: AirbyteInternal -description: Fields for internal use only -type: object -additionalProperties: true -properties: - sl: - type: integer - enum: - - 0 - - 100 - - 200 - - 300 - ql: - type: integer - enum: - - 0 - - 100 - - 200 - - 300 - - 400 - - 500 - - 600 - isEnterprise: - type: boolean - default: false - requireVersionIncrementsInPullRequests: - type: boolean - default: true - description: When false, version increment checks will be skipped for this connector diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/AllowedHosts.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/AllowedHosts.yaml deleted file mode 100644 index e796573835e3..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/AllowedHosts.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/AllowedHosts.yaml -title: AllowedHosts -description: A connector's allowed hosts. If present, the platform will limit communication to only hosts which are listed in `AllowedHosts.hosts`. -type: object -additionalProperties: true -properties: - hosts: - type: array - description: An array of hosts that this connector can connect to. AllowedHosts not being present for the source or destination means that access to all hosts is allowed. An empty list here means that no network access is granted. - items: - type: string diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorBreakingChanges.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorBreakingChanges.yaml deleted file mode 100644 index 3751e7bb6f74..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorBreakingChanges.yaml +++ /dev/null @@ -1,65 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorBreakingChanges.yaml -title: ConnectorBreakingChanges -description: Each entry denotes a breaking change in a specific version of a connector that requires user action to upgrade. -type: object -additionalProperties: false -minProperties: 1 -patternProperties: - "^\\d+\\.\\d+\\.\\d+$": - $ref: "#/definitions/VersionBreakingChange" -definitions: - VersionBreakingChange: - description: Contains information about a breaking change, including the deadline to upgrade and a message detailing the change. - type: object - additionalProperties: false - required: - - upgradeDeadline - - message - properties: - upgradeDeadline: - description: The deadline by which to upgrade before the breaking change takes effect. - type: string - format: date - message: - description: Descriptive message detailing the breaking change. - type: string - deadlineAction: - description: Action to do when the deadline is reached. - type: string - enum: - - auto_upgrade - - disable - migrationDocumentationUrl: - description: URL to documentation on how to migrate to the current version. Defaults to ${documentationUrl}-migrations#${version} - type: string - format: uri - scopedImpact: - description: List of scopes that are impacted by the breaking change. If not specified, the breaking change cannot be scoped to reduce impact via the supported scope types. - type: array - minItems: 1 - items: - $ref: "#/definitions/BreakingChangeScope" - BreakingChangeScope: - description: A scope that can be used to limit the impact of a breaking change. - type: object - oneOf: - - $ref: "#/definitions/StreamBreakingChangeScope" - StreamBreakingChangeScope: - description: A scope that can be used to limit the impact of a breaking change to specific streams. - type: object - additionalProperties: false - required: - - scopeType - - impactedScopes - properties: - scopeType: - type: string - const: stream - impactedScopes: - description: List of streams that are impacted by the breaking change. - type: array - minItems: 1 - items: - type: string diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorBuildOptions.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorBuildOptions.yaml deleted file mode 100644 index c040dd5404be..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorBuildOptions.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorBuildOptions.yaml -title: ConnectorBuildOptions -description: metadata specific to the build process. -type: object -additionalProperties: false -properties: - baseImage: - type: string diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorIPCOptions.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorIPCOptions.yaml deleted file mode 100644 index a8041f139259..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorIPCOptions.yaml +++ /dev/null @@ -1,29 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorIPCOptions.yaml -title: ConnectorIPCOptions -type: object -required: - - dataChannel -additionalProperties: false -properties: - dataChannel: - type: object - required: - - version - - supportedSerialization - - supportedTransport - additionalProperties: false - properties: - version: - type: string - supportedSerialization: - type: array - items: - type: string - enum: ["JSONL", "PROTOBUF"] - supportedTransport: - type: array - items: - type: string - enum: ["STDIO", "SOCKET"] diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorMetadataDefinitionV0.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorMetadataDefinitionV0.yaml deleted file mode 100644 index 04d0fdce1fb0..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorMetadataDefinitionV0.yaml +++ /dev/null @@ -1,173 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/ConnectorMetadataDefinitionV0.yml - -title: ConnectorMetadataDefinitionV0 -description: describes the metadata of a connector -type: object -required: - - metadataSpecVersion - - data -additionalProperties: false -properties: - metadataSpecVersion: - type: "string" - data: - type: object - required: - - name - - definitionId - - connectorType - - dockerRepository - - dockerImageTag - - license - - documentationUrl - - githubIssueLabel - - connectorSubtype - - releaseStage - additionalProperties: false - properties: - name: - type: string - icon: - type: string - definitionId: - type: string - format: uuid - connectorBuildOptions: - "$ref": ConnectorBuildOptions.yaml - connectorTestSuitesOptions: - type: array - items: - "$ref": ConnectorTestSuiteOptions.yaml - connectorType: - type: string - enum: - - destination - - source - dockerRepository: - type: string - dockerImageTag: - type: string - supportsDbt: - type: boolean - supportsNormalization: - type: boolean - license: - type: string - documentationUrl: - type: string - format: uri - externalDocumentationUrls: - type: array - description: "An array of external vendor documentation URLs (changelogs, API references, deprecation notices, etc.)" - items: - type: object - required: - - title - - url - additionalProperties: false - properties: - title: - type: string - description: "Display title for the documentation link" - url: - type: string - format: uri - description: "URL to the external documentation" - type: - type: string - description: "Category of documentation" - enum: - - api_deprecations - - api_reference - - api_release_history - - authentication_guide - - data_model_reference - - developer_community - - migration_guide - - openapi_spec - - other - - permissions_scopes - - rate_limits - - sql_reference - - status_page - requiresLogin: - type: boolean - description: "Whether the URL requires authentication to access" - default: false - githubIssueLabel: - type: string - maxSecondsBetweenMessages: - description: Maximum delay between 2 airbyte protocol messages, in second. The source will timeout if this delay is reached - type: integer - releaseDate: - description: The date when this connector was first released, in yyyy-mm-dd format. - type: string - format: date - protocolVersion: - type: string - description: the Airbyte Protocol version supported by the connector - erdUrl: - type: string - description: The URL where you can visualize the ERD - connectorSubtype: - type: string - enum: - - api - - database - - datalake - - file - - custom - - message_queue - - unknown - - vectorstore - releaseStage: - "$ref": ReleaseStage.yaml - supportLevel: - "$ref": SupportLevel.yaml - tags: - type: array - description: "An array of tags that describe the connector. E.g: language:python, keyword:rds, etc." - items: - type: string - default: [] - registryOverrides: - anyOf: - - type: object - additionalProperties: false - properties: - oss: - anyOf: - - "$ref": RegistryOverrides.yaml - cloud: - anyOf: - - "$ref": RegistryOverrides.yaml - - allowedHosts: - "$ref": AllowedHosts.yaml - releases: - "$ref": ConnectorReleases.yaml - normalizationConfig: - "$ref": NormalizationDestinationDefinitionConfig.yaml - suggestedStreams: - "$ref": SuggestedStreams.yaml - resourceRequirements: - "$ref": ActorDefinitionResourceRequirements.yaml - ab_internal: - "$ref": AirbyteInternal.yaml - remoteRegistries: - "$ref": RemoteRegistries.yaml - supportsRefreshes: - type: boolean - default: false - generated: - "$ref": GeneratedFields.yaml - supportsFileTransfer: - type: boolean - default: false - supportsDataActivation: - type: boolean - default: false - connectorIPCOptions: - "$ref": ConnectorIPCOptions.yaml diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorMetrics.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorMetrics.yaml deleted file mode 100644 index 0684df0c0a6c..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorMetrics.yaml +++ /dev/null @@ -1,30 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/ConnectorMetrics.yaml -title: ConnectorMetrics -description: Information about the source file that generated the registry entry -type: object -properties: - all: - type: ConnectorMetric - cloud: - type: ConnectorMetric - oss: - type: ConnectorMetric -definitions: - ConnectorMetric: - type: object - properties: - usage: - oneOf: - - type: string - - type: string - enum: [low, medium, high] - sync_success_rate: - oneOf: - - type: string - - type: string - enum: [low, medium, high] - connector_version: - type: string - additionalProperties: true diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorPackageInfo.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorPackageInfo.yaml deleted file mode 100644 index 32c478fe8b97..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorPackageInfo.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/ConnectorPackageInfo.yaml -title: ConnectorPackageInfo -description: Information about the contents of the connector image -type: object -properties: - cdk_version: - type: string diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistryDestinationDefinition.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistryDestinationDefinition.yaml deleted file mode 100644 index 64333fceffea..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistryDestinationDefinition.yaml +++ /dev/null @@ -1,90 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte-platform/blob/main/airbyte-config/config-models/src/main/resources/types/ConnectorRegistryDestinationDefinition.yaml -title: ConnectorRegistryDestinationDefinition -description: describes a destination -type: object -required: - - destinationDefinitionId - - name - - dockerRepository - - dockerImageTag - - documentationUrl - - spec -additionalProperties: true -properties: - destinationDefinitionId: - type: string - format: uuid - name: - type: string - dockerRepository: - type: string - dockerImageTag: - type: string - documentationUrl: - type: string - icon: - type: string - iconUrl: - type: string - spec: - type: object - tombstone: - description: if false, the configuration is active. if true, then this - configuration is permanently off. - type: boolean - default: false - public: - description: true if this connector definition is available to all workspaces - type: boolean - default: false - custom: - description: whether this is a custom connector definition - type: boolean - default: false - releaseStage: - "$ref": ReleaseStage.yaml - supportLevel: - "$ref": SupportLevel.yaml - releaseDate: - description: The date when this connector was first released, in yyyy-mm-dd format. - type: string - format: date - tags: - type: array - description: "An array of tags that describe the connector. E.g: language:python, keyword:rds, etc." - items: - type: string - resourceRequirements: - "$ref": ActorDefinitionResourceRequirements.yaml - protocolVersion: - type: string - description: the Airbyte Protocol version supported by the connector - normalizationConfig: - "$ref": NormalizationDestinationDefinitionConfig.yaml - supportsDbt: - type: boolean - description: an optional flag indicating whether DBT is used in the normalization. If the flag value is NULL - DBT is not used. - allowedHosts: - "$ref": AllowedHosts.yaml - releases: - "$ref": ConnectorRegistryReleases.yaml - ab_internal: - "$ref": AirbyteInternal.yaml - supportsRefreshes: - type: boolean - default: false - supportsFileTransfer: - type: boolean - default: false - supportsDataActivation: - type: boolean - default: false - generated: - "$ref": GeneratedFields.yaml - packageInfo: - "$ref": ConnectorPackageInfo.yaml - language: - type: string - description: The language the connector is written in diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistryReleases.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistryReleases.yaml deleted file mode 100644 index b1b26ce792e4..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistryReleases.yaml +++ /dev/null @@ -1,35 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistryReleases.yaml -title: ConnectorRegistryReleases -description: Contains information about different types of releases for a connector. -type: object -additionalProperties: false -properties: - releaseCandidates: - $ref: "#/definitions/ConnectorReleaseCandidates" - rolloutConfiguration: - $ref: RolloutConfiguration.yaml - breakingChanges: - $ref: ConnectorBreakingChanges.yaml - migrationDocumentationUrl: - description: URL to documentation on how to migrate from the previous version to the current version. Defaults to ${documentationUrl}-migrations - type: string - format: uri -definitions: - ConnectorReleaseCandidates: - description: Each entry denotes a release candidate version of a connector. - type: object - additionalProperties: false - minProperties: 1 - maxProperties: 1 - patternProperties: - "^\\d+\\.\\d+\\.\\d+(-[0-9A-Za-z-.]+)?$": - $ref: "#/definitions/VersionReleaseCandidate" - VersionReleaseCandidate: - description: Contains information about a release candidate version of a connector. - additionalProperties: false - type: object - oneOf: - - $ref: ConnectorRegistrySourceDefinition.yaml - - $ref: ConnectorRegistryDestinationDefinition.yaml diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistrySourceDefinition.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistrySourceDefinition.yaml deleted file mode 100644 index fd71b4e3878f..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistrySourceDefinition.yaml +++ /dev/null @@ -1,92 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte-platform/blob/main/airbyte-config/config-models/src/main/resources/types/ConnectorRegistrySourceDefinition.yaml -title: ConnectorRegistrySourceDefinition -description: describes a source -type: object -required: - - sourceDefinitionId - - name - - dockerRepository - - dockerImageTag - - documentationUrl - - spec -additionalProperties: true -properties: - sourceDefinitionId: - type: string - format: uuid - name: - type: string - dockerRepository: - type: string - dockerImageTag: - type: string - documentationUrl: - type: string - icon: - type: string - iconUrl: - type: string - sourceType: - type: string - enum: - - api - - file - - database - - custom - spec: - type: object - tombstone: - description: if false, the configuration is active. if true, then this - configuration is permanently off. - type: boolean - default: false - public: - description: true if this connector definition is available to all workspaces - type: boolean - default: false - custom: - description: whether this is a custom connector definition - type: boolean - default: false - releaseStage: - "$ref": ReleaseStage.yaml - supportLevel: - "$ref": SupportLevel.yaml - releaseDate: - description: The date when this connector was first released, in yyyy-mm-dd format. - type: string - format: date - resourceRequirements: - "$ref": ActorDefinitionResourceRequirements.yaml - protocolVersion: - type: string - description: the Airbyte Protocol version supported by the connector - allowedHosts: - "$ref": AllowedHosts.yaml - suggestedStreams: - "$ref": SuggestedStreams.yaml - maxSecondsBetweenMessages: - description: Number of seconds allowed between 2 airbyte protocol messages. The source will timeout if this delay is reach - type: integer - erdUrl: - type: string - description: The URL where you can visualize the ERD - releases: - "$ref": ConnectorRegistryReleases.yaml - ab_internal: - "$ref": AirbyteInternal.yaml - generated: - "$ref": GeneratedFields.yaml - packageInfo: - "$ref": ConnectorPackageInfo.yaml - language: - type: string - description: The language the connector is written in - supportsFileTransfer: - type: boolean - default: false - supportsDataActivation: - type: boolean - default: false diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistryV0.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistryV0.yaml deleted file mode 100644 index 8e3620816d65..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorRegistryV0.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte-platform/blob/main/airbyte-config/config-models/src/main/resources/types/ConnectorRegistryV0.yaml -title: ConnectorRegistryV0 -description: describes the collection of connectors retrieved from a registry -type: object -required: - - destinations - - sources -properties: - destinations: - type: array - items: - $ref: ConnectorRegistryDestinationDefinition.yaml - sources: - type: array - items: - $ref: ConnectorRegistrySourceDefinition.yaml diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorReleases.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorReleases.yaml deleted file mode 100644 index 80f753045300..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorReleases.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorReleases.yaml -title: ConnectorReleases -description: Contains information about different types of releases for a connector. -type: object -additionalProperties: false -properties: - rolloutConfiguration: - $ref: RolloutConfiguration.yaml - breakingChanges: - $ref: ConnectorBreakingChanges.yaml - migrationDocumentationUrl: - description: URL to documentation on how to migrate from the previous version to the current version. Defaults to ${documentationUrl}-migrations - type: string - format: uri diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorTestSuiteOptions.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorTestSuiteOptions.yaml deleted file mode 100644 index 2830332ee520..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorTestSuiteOptions.yaml +++ /dev/null @@ -1,28 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ConnectorTestOptions.yaml -title: ConnectorTestSuiteOptions -description: Options for a specific connector test suite. -type: object -required: - - suite -additionalProperties: false -properties: - suite: - description: "Name of the configured test suite" - type: string - enum: - - "unitTests" - - "integrationTests" - - "acceptanceTests" - - "liveTests" - testSecrets: - description: "List of secrets required to run the test suite" - type: array - items: - "$ref": "Secret.yaml" - testConnections: - description: "List of sandbox cloud connections that tests can be run against" - type: array - items: - "$ref": "TestConnections.yaml" diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/GeneratedFields.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/GeneratedFields.yaml deleted file mode 100644 index 0fc59e75d4b5..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/GeneratedFields.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/GeneratedFields.yaml -title: GeneratedFields -description: Optional schema for fields generated at metadata upload time -type: object -properties: - git: - "$ref": GitInfo.yaml - source_file_info: - "$ref": SourceFileInfo.yaml - metrics: - "$ref": ConnectorMetrics.yaml - sbomUrl: - type: string - description: URL to the SBOM file diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/GitInfo.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/GitInfo.yaml deleted file mode 100644 index ce03d88c6f70..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/GitInfo.yaml +++ /dev/null @@ -1,21 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/GitInfo.yaml -title: GitInfo -description: Information about the author of the last commit that modified this file. DO NOT DEFINE THIS FIELD MANUALLY. It will be overwritten by the CI. -type: object -additionalProperties: false -properties: - commit_sha: - type: string - description: The git commit sha of the last commit that modified this file. - commit_timestamp: - type: string - format: date-time - description: The git commit timestamp of the last commit that modified this file. - commit_author: - type: string - description: The git commit author of the last commit that modified this file. - commit_author_email: - type: string - description: The git commit author email of the last commit that modified this file. diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/JobType.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/JobType.yaml deleted file mode 100644 index 5cac4337e2bf..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/JobType.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/JobType.yaml -title: JobType -description: enum that describes the different types of jobs that the platform runs. -type: string -enum: - - get_spec - - check_connection - - discover_schema - - sync - - reset_connection - - connection_updater - - replicate diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/NormalizationDestinationDefinitionConfig.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/NormalizationDestinationDefinitionConfig.yaml deleted file mode 100644 index caf3d79e9c15..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/NormalizationDestinationDefinitionConfig.yaml +++ /dev/null @@ -1,21 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/NormalizationDestinationDefinitionConfig.yaml -title: NormalizationDestinationDefinitionConfig -description: describes a normalization config for destination definition -type: object -required: - - normalizationRepository - - normalizationTag - - normalizationIntegrationType -additionalProperties: true -properties: - normalizationRepository: - type: string - description: a field indicating the name of the repository to be used for normalization. If the value of the flag is NULL - normalization is not used. - normalizationTag: - type: string - description: a field indicating the tag of the docker repository to be used for normalization. - normalizationIntegrationType: - type: string - description: a field indicating the type of integration dialect to use for normalization. diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/RegistryOverrides.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/RegistryOverrides.yaml deleted file mode 100644 index abd651aacc29..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/RegistryOverrides.yaml +++ /dev/null @@ -1,38 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/RegistryOverrides.yml -title: RegistryOverrides -description: describes the overrides per registry of a connector -type: object -additionalProperties: false -required: - - enabled -properties: - enabled: - type: boolean - default: false - name: - type: string - dockerRepository: - type: string - dockerImageTag: - type: string - supportsDbt: - type: boolean - supportsNormalization: - type: boolean - license: - type: string - documentationUrl: - type: string - format: uri - connectorSubtype: - type: string - allowedHosts: - $ref: AllowedHosts.yaml - normalizationConfig: - "$ref": NormalizationDestinationDefinitionConfig.yaml - suggestedStreams: - $ref: SuggestedStreams.yaml - resourceRequirements: - $ref: ActorDefinitionResourceRequirements.yaml diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ReleaseStage.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ReleaseStage.yaml deleted file mode 100644 index 0a0767efd5ef..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ReleaseStage.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte-platform/blob/main/airbyte-config/config-models/src/main/resources/types/ReleaseStage.yaml -title: ReleaseStage -description: enum that describes a connector's release stage -type: string -enum: - - alpha - - beta - - generally_available - - custom diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/RemoteRegistries.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/RemoteRegistries.yaml deleted file mode 100644 index 474dc3d0a312..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/RemoteRegistries.yaml +++ /dev/null @@ -1,25 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/RemoteRegistries.yml -title: RemoteRegistries -description: describes how the connector is published to remote registries -type: object -additionalProperties: false -properties: - pypi: - $ref: "#/definitions/PyPi" -definitions: - PyPi: - title: PyPi - description: describes the PyPi publishing options - type: object - additionalProperties: false - required: - - enabled - - packageName - properties: - enabled: - type: boolean - packageName: - type: string - description: The name of the package on PyPi. diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ResourceRequirements.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ResourceRequirements.yaml deleted file mode 100644 index aef3e6f6c9f0..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ResourceRequirements.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/ResourceRequirements.yaml -title: ResourceRequirements -description: generic configuration for pod source requirements -type: object -additionalProperties: false -properties: - cpu_request: - type: string - cpu_limit: - type: string - memory_request: - type: string - memory_limit: - type: string diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/RolloutConfiguration.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/RolloutConfiguration.yaml deleted file mode 100644 index c2811bb8ed30..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/RolloutConfiguration.yaml +++ /dev/null @@ -1,29 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/RolloutConfiguration.yaml -title: RolloutConfiguration -description: configuration for the rollout of a connector -type: object -additionalProperties: false -properties: - enableProgressiveRollout: - type: boolean - default: false - description: Whether to enable progressive rollout for the connector. - initialPercentage: - type: integer - minimum: 0 - maximum: 100 - default: 0 - description: The percentage of users that should receive the new version initially. - maxPercentage: - type: integer - minimum: 0 - maximum: 100 - default: 50 - description: The percentage of users who should receive the release candidate during the test phase before full rollout. - advanceDelayMinutes: - type: integer - minimum: 10 - default: 10 - description: The number of minutes to wait before advancing the rollout percentage. diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/Secret.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/Secret.yaml deleted file mode 100644 index a6687c0e698b..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/Secret.yaml +++ /dev/null @@ -1,19 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/Secret.yaml -title: Secret -description: An object describing a secret's metadata -type: object -required: - - name - - secretStore -additionalProperties: false -properties: - name: - type: string - description: "The secret name in the secret store" - fileName: - type: string - description: "The name of the file to which the secret value would be persisted" - secretStore: - "$ref": SecretStore.yaml diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SecretStore.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SecretStore.yaml deleted file mode 100644 index 2a85367b7985..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SecretStore.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SecretStore.yaml -title: SecretStore -description: An object describing a secret store metadata -type: object -additionalProperties: false -properties: - alias: - type: string - description: "The alias of the secret store which can map to its actual secret address" - type: - type: string - description: "The type of the secret store" - enum: - - "GSM" diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SourceFileInfo.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SourceFileInfo.yaml deleted file mode 100644 index 7345cbf5b564..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SourceFileInfo.yaml +++ /dev/null @@ -1,17 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/SourceFileInfo.yaml -title: SourceFileInfo -description: Information about the source file that generated the registry entry -type: object -properties: - metadata_etag: - type: string - metadata_file_path: - type: string - metadata_bucket_name: - type: string - metadata_last_modified: - type: string - registry_entry_generated_at: - type: string diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SuggestedStreams.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SuggestedStreams.yaml deleted file mode 100644 index 4c540ba7fe98..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SuggestedStreams.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SuggestedStreams.yaml -title: SuggestedStreams -description: A source's suggested streams. These will be suggested by default for new connections using this source. Otherwise, all streams will be selected. This is useful for when your source has a lot of streams, but the average user will only want a subset of them synced. -type: object -additionalProperties: true -properties: - streams: - type: array - description: An array of streams that this connector suggests the average user will want. SuggestedStreams not being present for the source means that all streams are suggested. An empty list here means that no streams are suggested. - items: - type: string diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SupportLevel.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SupportLevel.yaml deleted file mode 100644 index 752d99a27c29..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/SupportLevel.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors_ci/metadata_service/lib/models/src/SupportLevel.yaml -title: SupportLevel -description: enum that describes a connector's release stage -type: string -enum: - - community - - certified - - archived diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/TestConnections.yaml b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/TestConnections.yaml deleted file mode 100644 index 0ca92550ae9f..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/TestConnections.yaml +++ /dev/null @@ -1,17 +0,0 @@ ---- -"$schema": http://json-schema.org/draft-07/schema# -"$id": https://github.com/airbytehq/airbyte/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/src/TestConnections.yaml -title: TestConnections -description: List of sandbox cloud connections that tests can be run against -type: object -required: - - name - - id -additionalProperties: false -properties: - name: - type: string - description: "The connection name" - id: - type: string - description: "The connection ID" diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/transform.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/transform.py deleted file mode 100644 index 971e3e76008a..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/models/transform.py +++ /dev/null @@ -1,71 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import json - -from pydantic import BaseModel - - -def _apply_default_pydantic_kwargs(kwargs: dict) -> dict: - """A helper function to apply default kwargs to pydantic models. - - Args: - kwargs (dict): the kwargs to apply - - Returns: - dict: the kwargs with defaults applied - """ - default_kwargs = { - "by_alias": True, # Ensure that the original field name from the jsonschema is used in the event it begins with an underscore (e.g. ab_internal) - "exclude_none": True, # Exclude fields that are None - } - - return {**default_kwargs, **kwargs} - - -def to_json_sanitized_dict(pydantic_model_obj: BaseModel, **kwargs) -> dict: - """A helper function to convert a pydantic model to a sanitized dict. - - Without this pydantic dictionary may contain values that are not JSON serializable. - - Args: - pydantic_model_obj (BaseModel): a pydantic model - - Returns: - dict: a sanitized dictionary - """ - - return json.loads(to_json(pydantic_model_obj, **kwargs)) - - -def to_json(pydantic_model_obj: BaseModel, **kwargs) -> str: - """A helper function to convert a pydantic model to a json string. - - Without this pydantic dictionary may contain values that are not JSON serializable. - - Args: - pydantic_model_obj (BaseModel): a pydantic model - - Returns: - str: a json string - """ - kwargs = _apply_default_pydantic_kwargs(kwargs) - - return pydantic_model_obj.json(**kwargs) - - -def to_dict(pydantic_model_obj: BaseModel, **kwargs) -> dict: - """A helper function to convert a pydantic model to a dict. - - Without this pydantic dictionary may contain values that are not JSON serializable. - - Args: - pydantic_model_obj (BaseModel): a pydantic model - - Returns: - dict: a dict - """ - kwargs = _apply_default_pydantic_kwargs(kwargs) - - return pydantic_model_obj.dict(**kwargs) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/registry.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/registry.py deleted file mode 100644 index a421fb8b6cf8..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/registry.py +++ /dev/null @@ -1,367 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -import copy -import json -import logging -import os -from collections import defaultdict -from enum import Enum -from typing import Union - -import semver -import sentry_sdk -from google.cloud import storage -from google.oauth2 import service_account -from pydash.objects import set_with - -from metadata_service.constants import ( - ANALYTICS_BUCKET, - ANALYTICS_FOLDER, - METADATA_FOLDER, - PUBLISH_UPDATE_CHANNEL, - REGISTRIES_FOLDER, - VALID_REGISTRIES, -) -from metadata_service.helpers.gcs import get_gcs_storage_client, safe_read_gcs_file -from metadata_service.helpers.object_helpers import CaseInsensitiveKeys, default_none_to_dict -from metadata_service.helpers.slack import send_slack_message -from metadata_service.models.generated import ConnectorRegistryDestinationDefinition, ConnectorRegistrySourceDefinition, ConnectorRegistryV0 -from metadata_service.models.transform import to_json_sanitized_dict - -logger = logging.getLogger(__name__) - - -PolymorphicRegistryEntry = Union[ConnectorRegistrySourceDefinition, ConnectorRegistryDestinationDefinition] - - -class ConnectorTypes(str, Enum, metaclass=CaseInsensitiveKeys): - SOURCE = "source" - DESTINATION = "destination" - - -class ConnectorTypePrimaryKey(str, Enum, metaclass=CaseInsensitiveKeys): - SOURCE = "sourceDefinitionId" - DESTINATION = "destinationDefinitionId" - - -class StringNullJsonDecoder(json.JSONDecoder): - """A JSON decoder that converts "null" strings to None.""" - - def __init__(self, *args, **kwargs): - super().__init__(object_hook=self.object_hook, *args, **kwargs) - - def object_hook(self, obj): - return {k: (None if v == "null" else v) for k, v in obj.items()} - - -def _apply_metrics_to_registry_entry(registry_entry_dict: dict, connector_type: ConnectorTypes, latest_metrics_dict: dict) -> dict: - """Apply the metrics to the registry entry. - - Args: - registry_entry_dict (dict): The registry entry. - latest_metrics_dict (dict): The metrics. - - Returns: - dict: The registry entry with metrics. - """ - connector_id = registry_entry_dict[ConnectorTypePrimaryKey[connector_type.value]] - metrics = latest_metrics_dict.get(connector_id, {}) - - # Safely add metrics to ["generated"]["metrics"], knowing that the key may not exist, or might be None - registry_entry_dict = set_with(registry_entry_dict, "generated.metrics", metrics, default_none_to_dict) - - return registry_entry_dict - - -def _apply_release_candidate_entries(registry_entry_dict: dict, docker_repository_to_rc_registry_entry: dict) -> dict: - """Apply the optionally existing release candidate entries to the registry entry. - We need both the release candidate metadata entry and the release candidate registry entry because the metadata entry contains the rollout configuration, and the registry entry contains the actual RC registry entry. - - Args: - registry_entry_dict (dict): The registry entry. - docker_repository_to_rc_registry_entry (dict): Mapping of docker repository to release candidate registry entry. - - Returns: - dict: The registry entry with release candidates applied. - """ - registry_entry_dict = copy.deepcopy(registry_entry_dict) - if registry_entry_dict["dockerRepository"] in docker_repository_to_rc_registry_entry: - release_candidate_registry_entry = docker_repository_to_rc_registry_entry[registry_entry_dict["dockerRepository"]] - registry_entry_dict = _apply_release_candidates(registry_entry_dict, release_candidate_registry_entry) - return registry_entry_dict - - -def _apply_release_candidates( - latest_registry_entry: dict, - release_candidate_registry_entry: PolymorphicRegistryEntry, -) -> dict: - """Apply the release candidate entries to the registry entry. - - Args: - latest_registry_entry (dict): The latest registry entry. - release_candidate_registry_entry (PolymorphicRegistryEntry): The release candidate registry entry. - - Returns: - dict: The registry entry with release candidates applied. - """ - try: - if not release_candidate_registry_entry.releases.rolloutConfiguration.enableProgressiveRollout: - return latest_registry_entry - # Handle if releases or rolloutConfiguration is not present in the release candidate registry entry - except AttributeError: - return latest_registry_entry - - # If the relase candidate is older than the latest registry entry, don't apply the release candidate and return the latest registry entry - if semver.Version.parse(release_candidate_registry_entry.dockerImageTag) < semver.Version.parse( - latest_registry_entry["dockerImageTag"] - ): - return latest_registry_entry - - updated_registry_entry = copy.deepcopy(latest_registry_entry) - updated_registry_entry.setdefault("releases", {}) - updated_registry_entry["releases"]["releaseCandidates"] = { - release_candidate_registry_entry.dockerImageTag: to_json_sanitized_dict(release_candidate_registry_entry) - } - return updated_registry_entry - - -def _build_connector_registry( - latest_registry_entries: list[PolymorphicRegistryEntry], latest_connector_metrics: dict, docker_repository_to_rc_registry_entry: dict -) -> ConnectorRegistryV0: - registry_dict = {"sources": [], "destinations": []} - - for latest_registry_entry in latest_registry_entries: - connector_type = _get_connector_type_from_registry_entry(latest_registry_entry) - plural_connector_type = f"{connector_type.value}s" - - registry_entry_dict = to_json_sanitized_dict(latest_registry_entry) - - enriched_registry_entry_dict = _apply_metrics_to_registry_entry(registry_entry_dict, connector_type, latest_connector_metrics) - - enriched_registry_entry_dict = _apply_release_candidate_entries( - enriched_registry_entry_dict, docker_repository_to_rc_registry_entry - ) - - registry_dict[plural_connector_type].append(enriched_registry_entry_dict) - - return ConnectorRegistryV0.parse_obj(registry_dict) - - -def _convert_json_to_metrics_dict(jsonl_string: str) -> dict: - """Convert the jsonl string to a metrics dict. - - Args: - jsonl_string (str): The jsonl string. - - Returns: - dict: The metrics dict. - """ - metrics_dict = defaultdict(dict) - jsonl_lines = jsonl_string.splitlines() - for line in jsonl_lines: - data = json.loads(line, cls=StringNullJsonDecoder) - connector_data = data["_airbyte_data"] - connector_definition_id = connector_data["connector_definition_id"] - airbyte_platform = connector_data["airbyte_platform"] - metrics_dict[connector_definition_id][airbyte_platform] = connector_data - - return metrics_dict - - -def _get_connector_type_from_registry_entry(registry_entry: PolymorphicRegistryEntry) -> ConnectorTypes: - """Get the connector type from the registry entry. - - Args: - registry_entry (PolymorphicRegistryEntry): The registry entry. - - Returns: - ConnectorTypes: The connector type. - """ - if hasattr(registry_entry, ConnectorTypePrimaryKey.SOURCE): - return ConnectorTypes.SOURCE - elif hasattr(registry_entry, ConnectorTypePrimaryKey.DESTINATION): - return ConnectorTypes.DESTINATION - else: - raise ValueError("Registry entry is not a source or destination") - - -@sentry_sdk.trace -def _get_latest_registry_entries(bucket: storage.Bucket, registry_type: str) -> list[PolymorphicRegistryEntry]: - """Get the latest registry entries from the GCS bucket. - - Args: - bucket (storage.Bucket): The GCS bucket. - registry_type (str): The registry type. - - Returns: - list[PolymorphicRegistryEntry]: The latest registry entries. - """ - registry_type_file_name = f"{registry_type}.json" - - try: - logger.info(f"Listing blobs in the latest folder: {METADATA_FOLDER}/**/latest/{registry_type_file_name}") - blobs = bucket.list_blobs(match_glob=f"{METADATA_FOLDER}/**/latest/{registry_type_file_name}") - except Exception as e: - logger.error(f"Error listing blobs in the latest folder: {str(e)}") - return [] - - latest_registry_entries = [] - for blob in blobs: - logger.info(f"Reading blob: {blob.name}") - registry_dict = json.loads(safe_read_gcs_file(blob)) - try: - if registry_dict.get(ConnectorTypePrimaryKey.SOURCE.value): - registry_model = ConnectorRegistrySourceDefinition.parse_obj(registry_dict) - elif registry_dict.get(ConnectorTypePrimaryKey.DESTINATION.value): - registry_model = ConnectorRegistryDestinationDefinition.parse_obj(registry_dict) - else: - logger.warning(f"Failed to parse registry model for {blob.name}. Skipping.") - continue - except Exception as e: - logger.error(f"Error parsing registry model for {blob.name}: {str(e)}") - continue - latest_registry_entries.append(registry_model) - return latest_registry_entries - - -@sentry_sdk.trace -def _get_release_candidate_registry_entries(bucket: storage.Bucket, registry_type: str) -> list[PolymorphicRegistryEntry]: - """Get the release candidate registry entries from the GCS bucket. - - Args: - bucket (storage.Bucket): The GCS bucket. - registry_type (str): The registry type. - - Returns: - list[PolymorphicRegistryEntry]: The release candidate registry entries. - """ - blobs = bucket.list_blobs(match_glob=f"{METADATA_FOLDER}/**/release_candidate/{registry_type}.json") - release_candidate_registry_entries = [] - for blob in blobs: - logger.info(f"Reading blob: {blob.name}") - registry_dict = json.loads(safe_read_gcs_file(blob)) - try: - if "/source-" in blob.name: - registry_model = ConnectorRegistrySourceDefinition.parse_obj(registry_dict) - else: - registry_model = ConnectorRegistryDestinationDefinition.parse_obj(registry_dict) - except Exception as e: - logger.error(f"Error parsing registry model for {blob.name}: {str(e)}") - continue - - release_candidate_registry_entries.append(registry_model) - return release_candidate_registry_entries - - -@sentry_sdk.trace -def _get_latest_connector_metrics(bucket: storage.Bucket) -> dict: - """Get the latest connector metrics from the GCS bucket. - - Args: - bucket (storage.Bucket): The GCS bucket. - - Returns: - dict: The latest connector metrics. - """ - try: - logger.info(f"Getting blobs in the analytics folder: {ANALYTICS_FOLDER}") - blobs = bucket.list_blobs(prefix=f"{ANALYTICS_FOLDER}/") - except Exception as e: - logger.error(f"Unexpected error listing blobs at {ANALYTICS_FOLDER}: {str(e)}") - return {} - - if not blobs: - raise ValueError("No blobs found in the analytics folder") - - # Sort blobs by updated time (most recent first) - most_recent_blob = max(blobs, key=lambda blob: blob.updated) - - latest_metrics_jsonl = safe_read_gcs_file(most_recent_blob) - - if latest_metrics_jsonl is None: - logger.warning(f"No metrics found for {most_recent_blob.name}") - return {} - - try: - latest_metrics_dict = _convert_json_to_metrics_dict(latest_metrics_jsonl) - except Exception as e: - logger.error(f"Error converting json to metrics dict: {str(e)}") - return {} - - return latest_metrics_dict - - -@sentry_sdk.trace -def _persist_registry(registry: ConnectorRegistryV0, registry_name: str, bucket: storage.Bucket) -> None: - """Persist the registry to a json file on GCS bucket - - Args: - registry (ConnectorRegistryV0): The registry. - registry_name (str): The name of the registry. One of "cloud" or "oss". - bucket (storage.Bucket): The GCS bucket. - - Returns: - None - """ - - registry_file_name = f"{registry_name}_registry.json" - registry_file_path = f"{REGISTRIES_FOLDER}/{registry_file_name}" - registry_json = registry.json(exclude_none=True) - registry_json = json.dumps(json.loads(registry_json), sort_keys=True) - - try: - logger.info(f"Uploading {registry_name} registry to {registry_file_path}") - blob = bucket.blob(registry_file_path) - # In cloud, airbyte-cron polls the registry frequently, to enable faster connector updates. - # We should set a lower cache duration on the blob so that the cron receives an up-to-date view of the registry. - # However, OSS polls the registry much less frequently, so the default cache setting (1hr max-age) is fine. - if registry_name == "cloud": - blob.cache_control = "public, max-age=120" - blob.upload_from_string(registry_json.encode("utf-8"), content_type="application/json") - logger.info(f"Successfully uploaded {registry_name} registry to {registry_file_path}") - return - except Exception as e: - logger.error(f"Error persisting {registry_file_name} to json: {str(e)}") - raise e - - -def generate_and_persist_connector_registry(bucket_name: str, registry_type: str) -> None: - """Generate and persist the registry to a json file on GCS bucket. - - Args: - bucket_name (str): The name of the GCS bucket. - registry_type (str): The type of the registry. - - Returns: - tuple[bool, Optional[str]]: A tuple containing a boolean indicating success and an optional error message. - """ - if registry_type not in VALID_REGISTRIES: - raise ValueError(f"Invalid registry type: {registry_type}. Valid types are: {', '.join(VALID_REGISTRIES)}.") - - gcs_client = get_gcs_storage_client() - registry_bucket = gcs_client.bucket(bucket_name) - analytics_bucket = gcs_client.bucket(ANALYTICS_BUCKET) - - latest_registry_entries = _get_latest_registry_entries(registry_bucket, registry_type) - - release_candidate_registry_entries = _get_release_candidate_registry_entries(registry_bucket, registry_type) - - docker_repository_to_rc_registry_entry = { - release_candidate_registry_entries.dockerRepository: release_candidate_registry_entries - for release_candidate_registry_entries in release_candidate_registry_entries - } - - latest_connector_metrics = _get_latest_connector_metrics(analytics_bucket) - - connector_registry = _build_connector_registry( - latest_registry_entries, latest_connector_metrics, docker_repository_to_rc_registry_entry - ) - - try: - _persist_registry(connector_registry, registry_type, registry_bucket) - except Exception as e: - message = f"*🤖 🔴 _Registry Generation_ FAILED*:\nFailed to generate and persist {registry_type} registry." - send_slack_message(PUBLISH_UPDATE_CHANNEL, message) - raise e diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/registry_entry.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/registry_entry.py deleted file mode 100644 index fb1f01a71d78..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/registry_entry.py +++ /dev/null @@ -1,572 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - - -import copy -import datetime -import json -import logging -import os -import pathlib -from dataclasses import dataclass -from typing import List, Optional, Tuple, Union - -import pandas as pd -import sentry_sdk -import yaml -from google.cloud import storage -from pydash import set_with - -from metadata_service.constants import ( - CONNECTOR_DEPENDENCY_FILE_NAME, - CONNECTOR_DEPENDENCY_FOLDER, - CONNECTORS_PATH, - DEFAULT_ASSET_URL, - ICON_FILE_NAME, - METADATA_CDN_BASE_URL, - METADATA_FILE_NAME, - METADATA_FOLDER, - PUBLISH_UPDATE_CHANNEL, - get_public_url_for_gcs_file, -) -from metadata_service.helpers.gcs import get_gcs_storage_client, safe_read_gcs_file -from metadata_service.helpers.object_helpers import deep_copy_params, default_none_to_dict -from metadata_service.helpers.slack import send_slack_message -from metadata_service.models.generated import ( - ConnectorRegistryDestinationDefinition, - ConnectorRegistrySourceDefinition, - GeneratedFields, - SourceFileInfo, -) -from metadata_service.registry import ConnectorTypePrimaryKey, ConnectorTypes -from metadata_service.spec_cache import SpecCache - -logger = logging.getLogger(__name__) - -PYTHON_CDK_SLUG = "python" - -PolymorphicRegistryEntry = Union[ConnectorRegistrySourceDefinition, ConnectorRegistryDestinationDefinition] -TaggedRegistryEntry = Tuple[ConnectorTypes, PolymorphicRegistryEntry] - - -@dataclass(frozen=True) -class RegistryEntryInfo: - entry_blob_path: str - metadata_file_path: str - - -def _apply_metadata_overrides( - metadata_data: dict, registry_type: str, bucket_name: str, metadata_blob: storage.Blob, skip_docker_image_tag: bool = True -) -> dict: - connector_type = metadata_data["connectorType"] - - overridden_metadata_data = _apply_overrides_from_registry(metadata_data, registry_type, skip_docker_image_tag=skip_docker_image_tag) - - # remove fields that are not needed in the registry - del overridden_metadata_data["registryOverrides"] - del overridden_metadata_data["connectorType"] - - # rename field connectorSubtype to sourceType - connector_subtype = overridden_metadata_data.get("connectorSubtype") - if connector_subtype: - overridden_metadata_data["sourceType"] = overridden_metadata_data["connectorSubtype"] - del overridden_metadata_data["connectorSubtype"] - - # rename definitionId field to sourceDefinitionId or destinationDefinitionId - id_field = "sourceDefinitionId" if connector_type == "source" else "destinationDefinitionId" - overridden_metadata_data[id_field] = overridden_metadata_data["definitionId"] - del overridden_metadata_data["definitionId"] - - # add in useless fields that are currently required for porting to the actor definition spec - overridden_metadata_data["tombstone"] = False - overridden_metadata_data["custom"] = False - overridden_metadata_data["public"] = True - - # Add generated fields for source file metadata and git - overridden_metadata_data["generated"] = _apply_generated_fields(overridden_metadata_data, bucket_name, metadata_blob) - - # Add Dependency information - overridden_metadata_data["packageInfo"] = _apply_package_info_fields(overridden_metadata_data, bucket_name) - - # Add language field - overridden_metadata_data = _apply_language_field(overridden_metadata_data) - - # if there is no supportLevel, set it to "community" - if not overridden_metadata_data.get("supportLevel"): - overridden_metadata_data["supportLevel"] = "community" - - # apply ab_internal defaults - overridden_metadata_data = _apply_ab_internal_defaults(overridden_metadata_data) - - # apply icon url and releases - icon_blob = _get_icon_blob_from_gcs(bucket_name, metadata_data) - icon_url = get_public_url_for_gcs_file(icon_blob.bucket.name, icon_blob.name, METADATA_CDN_BASE_URL) - - overridden_metadata_data["iconUrl"] = icon_url - overridden_metadata_data["releases"] = _apply_connector_releases(overridden_metadata_data) - - return overridden_metadata_data - - -@deep_copy_params -def _apply_overrides_from_registry(metadata_data: dict, override_registry_key: str, skip_docker_image_tag: bool = True) -> dict: - """Apply the overrides from the registry to the metadata data. - - Args: - metadata_data: The metadata data field. - override_registry_key: The key of the registry to override the metadata with. - skip_docker_image_tag: If True (default), skip applying dockerImageTag override. - This should be True for the version being published, and False for latest - entries (which should reflect the overridden/pinned version, if applicable). - - Returns: - The metadata data field with the overrides applied. - """ - override_registry = metadata_data["registryOverrides"][override_registry_key] - del override_registry["enabled"] - - # remove any None values from the override registry - override_registry = {k: v for k, v in override_registry.items() if v is not None} - - if skip_docker_image_tag and "dockerImageTag" in override_registry: - del override_registry["dockerImageTag"] - - metadata_data.update(override_registry) - - return metadata_data - - -def _apply_generated_fields(metadata_data: dict, bucket_name: str, metadata_blob: storage.Blob) -> dict: - """Apply generated fields to the metadata data field. - - Args: - metadata_data (dict): The metadata data field. - - Returns: - dict: The metadata data field with the generated fields applied. - """ - # work on our own copy of everything - metadata_data = copy.deepcopy(metadata_data) - - generated_fields = metadata_data.get("generated") or {} - - # Add the source file metadata - # on a GCS blob, the "name" is actually the full path - generated_fields = set_with(generated_fields, "source_file_info.metadata_file_path", metadata_blob.name, default_none_to_dict) - generated_fields = set_with(generated_fields, "source_file_info.metadata_bucket_name", bucket_name, default_none_to_dict) - generated_fields = set_with( - generated_fields, "source_file_info.registry_entry_generated_at", datetime.datetime.now().isoformat(), default_none_to_dict - ) - generated_fields = set_with( - generated_fields, "source_file_info.metadata_last_modified", metadata_blob.updated.isoformat(), default_none_to_dict - ) - - return generated_fields - - -@sentry_sdk.trace -@deep_copy_params -def _apply_package_info_fields(metadata_data: dict, bucket_name: str) -> dict: - """Apply package info fields to the metadata data field. - - Args: - metadata_data (dict): The metadata data field. - bucket_name (str): The name of the GCS bucket. - - Returns: - dict: The metadata data field with the package info fields applied. - """ - - sanitized_connector_technical_name = metadata_data["dockerRepository"].replace("airbyte/", "") - connector_version = metadata_data["dockerImageTag"] - - dependencies_path = ( - f"{CONNECTOR_DEPENDENCY_FOLDER}/{sanitized_connector_technical_name}/{connector_version}/{CONNECTOR_DEPENDENCY_FILE_NAME}" - ) - - package_info_fields = metadata_data.get("packageInfo") or {} - - try: - logger.info( - f"Getting dependencies blob for `{sanitized_connector_technical_name}` `{connector_version}` at path `{dependencies_path}`" - ) - gcs_client = get_gcs_storage_client(gcs_creds=os.environ.get("GCS_CREDENTIALS")) - bucket = gcs_client.bucket(bucket_name) - dependencies_blob = bucket.blob(dependencies_path) - dependencies_blob_contents = safe_read_gcs_file(dependencies_blob) - if dependencies_blob_contents is not None: - dependencies_json = json.loads(dependencies_blob_contents) - cdk_version = None - for package in dependencies_json.get("dependencies", []): - if package.get("package_name") == "airbyte-cdk": - # Note: Prefix the version with the python slug as the python cdk is the only one we have - # versions available for. - cdk_version = f"{PYTHON_CDK_SLUG}:{package.get('version')}" - break - package_info_fields = set_with(package_info_fields, "cdk_version", cdk_version, default_none_to_dict) - except Exception as e: - logger.warning(f"Error reading dependencies file for `{sanitized_connector_technical_name}`: {e}") - raise - - logger.info("Added package info fields.") - - return package_info_fields - - -@deep_copy_params -def _apply_language_field(metadata_data: dict) -> dict: - """Transform the language tag into a top-level field, if it is not already present. - - Args: - metadata_data (dict): The metadata data field. - - Returns: - dict: The metadata data field with the language field applied. - """ - if metadata_data.get("language"): - return metadata_data - - tags = metadata_data.get("tags", []) - languages = [tag.replace("language:", "") for tag in tags if tag.startswith("language:")] - metadata_data["language"] = languages[0] if languages else None - - return metadata_data - - -@deep_copy_params -def _apply_ab_internal_defaults(metadata_data: dict) -> dict: - """Apply ab_internal defaults to the metadata data field. - - Args: - metadata_data (dict): The metadata data field. - - Returns: - dict: The metadata data field with the ab_internal defaults applied. - """ - default_ab_internal_values = { - "sl": 100, - "ql": 100, - } - - existing_ab_internal_values = metadata_data.get("ab_internal") or {} - ab_internal_values = {**default_ab_internal_values, **existing_ab_internal_values} - - metadata_data["ab_internal"] = ab_internal_values - - return metadata_data - - -@deep_copy_params -def _apply_connector_releases(metadata: dict) -> Optional[pd.DataFrame]: - documentation_url = metadata["documentationUrl"] - final_registry_releases = {} - releases = metadata.get("releases") - if releases is not None and releases.get("breakingChanges"): - # apply defaults for connector releases - final_registry_releases["migrationDocumentationUrl"] = _calculate_migration_documentation_url( - metadata["releases"], documentation_url - ) - - # releases has a dictionary field called breakingChanges, where the key is the version and the value is the data for the breaking change - # each breaking change has a migrationDocumentationUrl field that is optional, so we need to apply defaults to it - breaking_changes = metadata["releases"]["breakingChanges"] - if breaking_changes is not None: - for version, breaking_change in breaking_changes.items(): - breaking_change["migrationDocumentationUrl"] = _calculate_migration_documentation_url( - breaking_change, documentation_url, version - ) - final_registry_releases["breakingChanges"] = breaking_changes - - if releases is not None and releases.get("rolloutConfiguration"): - final_registry_releases["rolloutConfiguration"] = metadata["releases"]["rolloutConfiguration"] - return final_registry_releases - - -def _calculate_migration_documentation_url(releases_or_breaking_change: dict, documentation_url: str, version: Optional[str] = None) -> str: - """Calculate the migration documentation url for the connector releases. - - Args: - metadata_releases (dict): The connector releases. - - Returns: - str: The migration documentation url. - """ - - base_url = f"{documentation_url}-migrations" - default_migration_documentation_url = f"{base_url}#{version}" if version is not None else base_url - - return releases_or_breaking_change.get("migrationDocumentationUrl", None) or default_migration_documentation_url - - -def _get_and_parse_yaml_file(file_path: pathlib.Path) -> dict: - """Get and parse the metadata file. - - Args: - metadata_file_path (pathlib.Path): The path to the metadata file. - - Returns: - dict: The file dictionary. - """ - - try: - logger.debug(f"Getting and parsing YAML file: `{file_path}`") - with open(file_path, "r") as f: - file_dict = yaml.safe_load(f) - except Exception as e: - logger.exception(f"Error parsing file") - raise - logger.info("Parsed YAML file.") - return file_dict - - -@sentry_sdk.trace -def _get_icon_blob_from_gcs(bucket_name: str, metadata_entry: dict) -> storage.Blob: - """Get the icon blob from the GCS bucket. - - Args: - bucket (storage.Bucket): The GCS bucket. - metadata_entry (dict): The metadata entry. - - Returns: - storage.Blob: The icon blob. - """ - connector_docker_repository = metadata_entry["dockerRepository"] - icon_file_path = f"{METADATA_FOLDER}/{connector_docker_repository}/latest/{ICON_FILE_NAME}" - try: - logger.info(f"Getting icon blob for {connector_docker_repository}") - gcs_client = get_gcs_storage_client(gcs_creds=os.environ.get("GCS_CREDENTIALS")) - bucket = gcs_client.bucket(bucket_name) - icon_blob = bucket.blob(icon_file_path) - if not icon_blob.exists(): - raise ValueError(f"Icon file not found for `{connector_docker_repository}`") - except Exception as e: - logger.exception(f"Error getting icon blob") - raise - return icon_blob - - -def _get_connector_type_from_registry_entry(registry_entry: dict) -> TaggedRegistryEntry: - """Get the connector type from the registry entry. - - Args: - registry_entry (dict): The registry entry. - - Returns: - TaggedRegistryEntry: The connector type and model. - """ - if registry_entry.get(ConnectorTypePrimaryKey.SOURCE.value): - return (ConnectorTypes.SOURCE, ConnectorRegistrySourceDefinition) - elif registry_entry.get(ConnectorTypePrimaryKey.DESTINATION.value): - return (ConnectorTypes.DESTINATION, ConnectorRegistryDestinationDefinition) - else: - raise Exception("Could not determine connector type from registry entry") - - -def _get_registry_blob_information( - metadata_dict: dict, registry_type: str, metadata_data_with_overrides: dict, is_prerelease: bool -) -> List[RegistryEntryInfo]: - """ - Builds information for each registry blob: GCS path to write the registry entry into, along with - the correct "metadata blob path" for the entry. - - Args: - metadata_dict (dict): The metadata dictionary. - registry_type (str): The registry type. - - Returns: - List[RegistryEntryInfo]: Tuples of the path to write the registry entry to, and the metadata blob path to populate into the entry. - """ - docker_repository = metadata_dict["data"]["dockerRepository"] - registry_entry_paths: List[RegistryEntryInfo] = [] - - # The versioned registry entries always respect the registry overrides. - # For example, with destination-postgres: we'll push oss.json to `destination-postgres//oss.json`, - # but cloud.json goes to `destination-postgres-strict-encrypt//cloud.json`. - versioned_registry_entry_path = f"{METADATA_FOLDER}/{metadata_data_with_overrides['dockerRepository']}/{metadata_data_with_overrides['dockerImageTag']}/{registry_type}.json" - # However, the metadata blob path uses the non-overridden docker repo, for... reasons? - versioned_metadata_blob_path = f"{METADATA_FOLDER}/{docker_repository}/{metadata_data_with_overrides['dockerImageTag']}/metadata.yaml" - # We always publish the versioned registry entry. - registry_entry_paths.append(RegistryEntryInfo(versioned_registry_entry_path, versioned_metadata_blob_path)) - - # If we're not doing a prerelease, we have an extra file to push. - # Note that for these extra files, we point at a different metadata.yaml than the versioned file - # (e.g. the `latest` registry entry points at the `latest` metadata.yaml, instead of at the versioned metadata.yaml) - if not is_prerelease: - if "-rc" in metadata_dict["data"]["dockerImageTag"]: - # We're doing a release candidate publish. Push the RC registry entry. - # This intentionally uses the non-overridden docker_repository. We _always_ upload both cloud+oss registry entries - # to the non-overridden docker_repository path for the `release_candidate` entry. - release_candidate_registry_entry_path = f"{METADATA_FOLDER}/{docker_repository}/release_candidate/{registry_type}.json" - release_candidate_metadata_blob_path = f"{METADATA_FOLDER}/{docker_repository}/release_candidate/metadata.yaml" - registry_entry_paths.append(RegistryEntryInfo(release_candidate_registry_entry_path, release_candidate_metadata_blob_path)) - - else: - # This is a normal publish. Push the `latest` registry entry. - # This intentionally uses the non-overridden docker_repository. We _always_ upload both cloud+oss registry entries - # to the non-overridden docker_repository path for the `latest` entry. - latest_registry_entry_path = f"{METADATA_FOLDER}/{docker_repository}/latest/{registry_type}.json" - latest_registry_metadata_blob_path = f"{METADATA_FOLDER}/{docker_repository}/latest/metadata.yaml" - registry_entry_paths.append(RegistryEntryInfo(latest_registry_entry_path, latest_registry_metadata_blob_path)) - - return registry_entry_paths - - -@sentry_sdk.trace -def _persist_connector_registry_entry(bucket_name: str, registry_entry: PolymorphicRegistryEntry, registry_entry_path: str) -> None: - """Persist the connector registry entry to the GCS bucket. - - Args: - bucket_name (str): The name of the GCS bucket. - registry_entry (PolymorphicRegistryEntry): The registry entry. - registry_entry_path (str): The path to the registry entry. - """ - try: - logger.info(f"Persisting connector registry entry to {registry_entry_path}") - gcs_client = get_gcs_storage_client() - bucket = gcs_client.bucket(bucket_name) - registry_entry_blob = bucket.blob(registry_entry_path) - registry_entry_blob.upload_from_string(registry_entry.json(exclude_none=True)) - except Exception as e: - logger.exception(f"Error persisting connector registry entry") - raise - - -@sentry_sdk.trace -def generate_and_persist_registry_entry( - bucket_name: str, repo_metadata_file_path: pathlib.Path, registry_type: str, docker_image_tag: str, is_prerelease: bool -) -> None: - """Generate and persist the connector registry entry to the GCS bucket. - - Args: - bucket_name (str): The name of the GCS bucket. - repo_metadata_file_path (pathlib.Path): The path to the spec file. - registry_type (str): The registry type. - docker_image_tag (str): The docker image tag associated with this release. Typically a semver string (e.g. '1.2.3'), possibly with a suffix (e.g. '1.2.3-preview.abcde12') - is_prerelease (bool): Whether this is a prerelease, or a main release. - """ - # Read the repo metadata dict to bootstrap ourselves. We need the docker repository, - # so that we can read the metadata from GCS. - repo_metadata_dict = _get_and_parse_yaml_file(repo_metadata_file_path) - docker_repository = repo_metadata_dict["data"]["dockerRepository"] - - try: - # Now that we have the docker repo, read the appropriate versioned metadata from GCS. - # This metadata will differ in a few fields (e.g. in prerelease mode, dockerImageTag will contain the actual prerelease tag `1.2.3-preview.abcde12`), - # so we'll treat this as the source of truth (ish. See below for how we handle the registryOverrides field.) - gcs_client = get_gcs_storage_client(gcs_creds=os.environ.get("GCS_CREDENTIALS")) - bucket = gcs_client.bucket(bucket_name) - metadata_blob = bucket.blob(f"{METADATA_FOLDER}/{docker_repository}/{docker_image_tag}/{METADATA_FILE_NAME}") - # bucket.blob() returns a partially-loaded blob. - # reload() asks GCS to fetch the rest of the information. - # (this doesn't fetch the _contents_ of the blob, only its metadata - modified time, etc.) - metadata_blob.reload() - metadata_dict = yaml.safe_load(metadata_blob.download_as_string()) - except: - logger.exception("Error loading metadata from GCS") - message = f"*🤖 🔴 _Registry Entry Generation_ FAILED*:\nRegistry Entry: `{registry_type}.json`\nConnector: `{repo_metadata_dict['data']['dockerRepository']}`\nGCS Bucket: `{bucket_name}`." - send_slack_message(PUBLISH_UPDATE_CHANNEL, message) - raise - - message = f"*🤖 🟡 _Registry Entry Generation_ STARTED*:\nRegistry Entry: `{registry_type}.json`\nConnector: `{docker_repository}`\nGCS Bucket: `{bucket_name}`." - send_slack_message(PUBLISH_UPDATE_CHANNEL, message) - - # If the connector is not enabled on the given registry, skip generateing and persisting the registry entry. - if metadata_dict["data"]["registryOverrides"][registry_type]["enabled"]: - metadata_data = metadata_dict["data"] - try: - overridden_metadata_data = _apply_metadata_overrides( - metadata_data, registry_type, bucket_name, metadata_blob, skip_docker_image_tag=True - ) - except Exception as e: - logger.exception(f"Error applying metadata overrides") - message = f"*🤖 🔴 _Registry Entry Generation_ FAILED*:\nRegistry Entry: `{registry_type}.json`\nConnector: `{metadata_data['dockerRepository']}`\nGCS Bucket: `{bucket_name}`." - send_slack_message(PUBLISH_UPDATE_CHANNEL, message) - raise - - registry_entry_blob_paths = _get_registry_blob_information(metadata_dict, registry_type, overridden_metadata_data, is_prerelease) - - logger.info("Parsing spec file.") - spec_cache = SpecCache() - # Use the overridden values here. This enables us to read from the appropriate spec cache for strict-encrypt connectors. - cached_spec = spec_cache.find_spec_cache_with_fallback( - overridden_metadata_data["dockerRepository"], overridden_metadata_data["dockerImageTag"], registry_type - ) - overridden_metadata_data["spec"] = spec_cache.download_spec(cached_spec) - logger.info("Spec file parsed and added to metadata.") - - logger.info("Parsing registry entry model.") - _, RegistryEntryModel = _get_connector_type_from_registry_entry(overridden_metadata_data) - registry_entry_model = RegistryEntryModel.parse_obj(overridden_metadata_data) - logger.info("Registry entry model parsed.") - - # Persist the registry entry to the GCS bucket. - for registry_entry_info in registry_entry_blob_paths: - registry_entry_blob_path = registry_entry_info.entry_blob_path - metadata_blob_path = registry_entry_info.metadata_file_path - - # For latest entries, apply the dockerImageTag override (version pinning behavior) - if "/latest/" in registry_entry_blob_path: - latest_metadata = _apply_metadata_overrides( - metadata_data, registry_type, bucket_name, metadata_blob, skip_docker_image_tag=False - ) - latest_spec = spec_cache.find_spec_cache_with_fallback( - latest_metadata["dockerRepository"], latest_metadata["dockerImageTag"], registry_type - ) - latest_metadata["spec"] = spec_cache.download_spec(latest_spec) - current_registry_entry_model = RegistryEntryModel.parse_obj(latest_metadata) - else: - current_registry_entry_model = registry_entry_model - - try: - logger.info( - f"Persisting `{metadata_data['dockerRepository']}` {registry_type} registry entry to `{registry_entry_blob_path}`" - ) - - # set the correct metadata blob path on the registry entry - current_registry_entry_model = copy.deepcopy(current_registry_entry_model) - generated_fields: Optional[GeneratedFields] = current_registry_entry_model.generated - if generated_fields is not None: - source_file_info: Optional[SourceFileInfo] = generated_fields.source_file_info - if source_file_info is not None: - source_file_info.metadata_file_path = metadata_blob_path - _persist_connector_registry_entry(bucket_name, current_registry_entry_model, registry_entry_blob_path) - - message = f"*🤖 🟢 _Registry Entry Generation_ SUCCESS*:\nRegistry Entry: `{registry_type}.json`\nConnector: `{metadata_data['dockerRepository']}`\nGCS Bucket: `{bucket_name}`\nPath: `{registry_entry_blob_path}`." - send_slack_message(PUBLISH_UPDATE_CHANNEL, message) - - logger.info("Success.") - - except Exception as e: - logger.exception(f"Error persisting connector registry entry to") - - message = f"*🤖 🔴 _Registry Entry Generation_ FAILED*:\nRegistry Entry: `{registry_type}.json`\nConnector: `{metadata_data['dockerRepository']}`\nGCS Bucket: `{bucket_name}`\nPath: `{registry_entry_blob_path}`." - send_slack_message(PUBLISH_UPDATE_CHANNEL, message) - - try: - bucket.delete_blob(registry_entry_blob_path) - except Exception as cleanup_error: - logger.warning(f"Failed to clean up {registry_entry_blob_path}: {cleanup_error}") - raise - else: - logger.info( - f"Registry type {registry_type} is not enabled for `{metadata_dict['data']['dockerRepository']}`, skipping generation and upload." - ) - message = f"*🤖 ⚫ _Registry Entry Generation_ NOOP*:\n_Note: Connector is not enabled on {registry_type} registry. No action required._\nRegistry Entry: `{registry_type}.json`\nConnector: `{metadata_dict['data']['dockerRepository']}`\nGCS Bucket: `{bucket_name}`." - send_slack_message(PUBLISH_UPDATE_CHANNEL, message) - - # For latest versions that are disabled, delete any existing registry entry to remove it from the registry - if ( - "-rc" not in metadata_dict["data"]["dockerImageTag"] - and "-dev" not in metadata_dict["data"]["dockerImageTag"] - and "-preview" not in metadata_dict["data"]["dockerImageTag"] - ) and not metadata_dict["data"]["registryOverrides"][registry_type]["enabled"]: - logger.info( - f"{registry_type} is not enabled: deleting existing {registry_type} registry entry for {metadata_dict['data']['dockerRepository']} at latest path." - ) - - latest_registry_entry_path = f"{METADATA_FOLDER}/{metadata_dict['data']['dockerRepository']}/latest/{registry_type}.json" - - existing_registry_entry = bucket.blob(latest_registry_entry_path) - if existing_registry_entry.exists(): - bucket.delete_blob(latest_registry_entry_path) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/registry_report.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/registry_report.py deleted file mode 100644 index 9e4061329c28..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/registry_report.py +++ /dev/null @@ -1,353 +0,0 @@ -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -import json -import logging -from dataclasses import dataclass -from os import scandir -from typing import Any, Callable, List - -import pandas as pd -from google.cloud import storage - -from metadata_service.constants import ( - CONNECTORS_PATH, - GITHUB_REPO_NAME, - METADATA_CDN_BASE_URL, - REGISTRIES_FOLDER, - get_public_url_for_gcs_file, -) -from metadata_service.helpers.gcs import get_gcs_storage_client -from metadata_service.models.generated import ConnectorRegistryV0 -from metadata_service.models.transform import to_json_sanitized_dict -from metadata_service.templates.render import ( - ColumnInfo, - dataframe_to_table_html, - icon_image_html, - internal_level_html, - render_connector_registry_locations_html, - simple_link_html, - test_badge_html, -) - -logger = logging.getLogger(__name__) - -REPORT_FILE_NAME = "connector_registry_report" -CONNECTOR_TEST_SUMMARY_FOLDER = "test_summary" -REPORT_FOLDER = "generated_reports" -OSS_SUFFIX = "_oss" -CLOUD_SUFFIX = "_cloud" - -# 🖼️ Dataframe Columns - - -def _github_url(docker_repo_name: str, github_connector_folders: List[str]) -> str | None: - if not isinstance(docker_repo_name, str): - return None - - connector_name = docker_repo_name.replace("airbyte/", "") - if connector_name in github_connector_folders: - return f"https://github.com/{GITHUB_REPO_NAME}/blob/master/airbyte-integrations/connectors/{connector_name}" - else: - return None - - -def _issue_url(row: pd.DataFrame) -> str | None: - docker_repo = row["dockerRepository_oss"] - if not isinstance(docker_repo, str): - print(f"no docker repo: {row}") - return None - - code_name = docker_repo.split("/")[1] - issues_label = ( - f"connectors/{'source' if 'source-' in code_name else 'destination'}/" - f"{code_name.replace('source-', '').replace('destination-', '')}" - ) - return f"https://github.com/{GITHUB_REPO_NAME}/issues?q=is:open+is:issue+label:{issues_label}" - - -def _merge_docker_repo_and_version(row: pd.DataFrame, suffix: str) -> str | None: - docker_repo = row[f"dockerRepository{suffix}"] - docker_version = row[f"dockerImageTag{suffix}"] - - if not isinstance(docker_repo, str): - return None - - return f"{docker_repo}:{docker_version}" - - -def _test_summary_url(row: pd.DataFrame) -> str | None: - docker_repo_name = row["dockerRepository_oss"] - if not isinstance(docker_repo_name, str): - return None - - connector = docker_repo_name.replace("airbyte/", "") - - path = f"{REPORT_FOLDER}/{CONNECTOR_TEST_SUMMARY_FOLDER}/{connector}" - - # get_public_url_for_gcs_file ignores the bucket name if a CDN URL is provided - return get_public_url_for_gcs_file("unused", path, METADATA_CDN_BASE_URL) - - -def _ab_internal_sl(row: pd.DataFrame) -> int | None: - ab_internal = row.get("ab_internal_oss") - if not isinstance(ab_internal, dict) or "sl" not in ab_internal: - return None - sl = ab_internal["sl"] - if not isinstance(sl, int): - raise Exception(f"expected sl to be string; got {type(sl)} ({sl})") - return sl - - -def _ab_internal_ql(row: pd.DataFrame) -> int | None: - ab_internal = row.get("ab_internal_oss") - if not isinstance(ab_internal, dict) or "ql" not in ab_internal: - return None - ql = ab_internal["ql"] - if not isinstance(ql, int): - raise Exception(f"expected ql to be string; got {type(ql)} ({ql})") - return ql - - -# 📊 Dataframe Augmentation - - -def _augment_and_normalize_connector_dataframes( - cloud_df: pd.DataFrame, oss_df: pd.DataFrame, primary_key: str, connector_type: str, github_connector_folders: List[str] -) -> pd.DataFrame: - """ - Normalize the cloud and oss connector dataframes and merge them into a single dataframe. - Augment the dataframe with additional columns that indicate if the connector is in the cloud registry, oss registry, and if the metadata is valid. - """ - - # Add a column 'is_cloud' to indicate if an image/version pair is in the cloud registry - cloud_df["is_cloud"] = True - - # Add a column 'is_oss' to indicate if an image/version pair is in the oss registry - oss_df["is_oss"] = True - - # Merge the two registries on the 'image' and 'version' columns - total_registry = pd.merge(oss_df, cloud_df, how="outer", suffixes=(OSS_SUFFIX, CLOUD_SUFFIX), on=primary_key) - - # remove duplicates from the merged dataframe - total_registry = total_registry.drop_duplicates(subset=primary_key, keep="first") - - # Replace NaN values in the 'is_cloud' and 'is_oss' columns with False - total_registry[["is_cloud", "is_oss"]] = total_registry[["is_cloud", "is_oss"]].fillna(False) - - # Set connectorType to 'source' or 'destination' - total_registry["connector_type"] = connector_type - - total_registry["github_url"] = total_registry["dockerRepository_oss"].apply(lambda x: _github_url(x, github_connector_folders)) - - total_registry["issue_url"] = total_registry.apply(_issue_url, axis=1) - total_registry["test_summary_url"] = total_registry.apply(_test_summary_url, axis=1) - - # Show Internal Fields - total_registry["ab_internal_ql"] = total_registry.apply(_ab_internal_ql, axis=1) - total_registry["ab_internal_sl"] = total_registry.apply(_ab_internal_sl, axis=1) - - # Merge docker repo and version into separate columns - total_registry["docker_image_oss"] = total_registry.apply(lambda x: _merge_docker_repo_and_version(x, OSS_SUFFIX), axis=1) - total_registry["docker_image_cloud"] = total_registry.apply(lambda x: _merge_docker_repo_and_version(x, CLOUD_SUFFIX), axis=1) - total_registry["docker_images_match"] = total_registry["docker_image_oss"] == total_registry["docker_image_cloud"] - - # Rename column primary_key to 'definitionId' - total_registry.rename(columns={primary_key: "definitionId"}, inplace=True) - - return total_registry - - -# ASSETS - - -def _cloud_sources_dataframe(latest_cloud_registry: ConnectorRegistryV0) -> pd.DataFrame: - latest_cloud_registry_dict = to_json_sanitized_dict(latest_cloud_registry) - sources = latest_cloud_registry_dict["sources"] - return pd.DataFrame(sources) - - -def _oss_sources_dataframe(latest_oss_registry: ConnectorRegistryV0) -> pd.DataFrame: - latest_oss_registry_dict = to_json_sanitized_dict(latest_oss_registry) - sources = latest_oss_registry_dict["sources"] - return pd.DataFrame(sources) - - -def _cloud_destinations_dataframe(latest_cloud_registry: ConnectorRegistryV0) -> pd.DataFrame: - latest_cloud_registry_dict = to_json_sanitized_dict(latest_cloud_registry) - destinations = latest_cloud_registry_dict["destinations"] - return pd.DataFrame(destinations) - - -def _oss_destinations_dataframe(latest_oss_registry: ConnectorRegistryV0) -> pd.DataFrame: - latest_oss_registry_dict = to_json_sanitized_dict(latest_oss_registry) - destinations = latest_oss_registry_dict["destinations"] - return pd.DataFrame(destinations) - - -def _all_sources_dataframe(cloud_sources_dataframe, oss_sources_dataframe, github_connector_folders) -> pd.DataFrame: - """ - Merge the cloud and oss sources registries into a single dataframe. - """ - - return _augment_and_normalize_connector_dataframes( - cloud_df=cloud_sources_dataframe, - oss_df=oss_sources_dataframe, - primary_key="sourceDefinitionId", - connector_type="source", - github_connector_folders=github_connector_folders, - ) - - -def _all_destinations_dataframe(cloud_destinations_dataframe, oss_destinations_dataframe, github_connector_folders) -> pd.DataFrame: - """ - Merge the cloud and oss destinations registries into a single dataframe. - """ - - return _augment_and_normalize_connector_dataframes( - cloud_df=cloud_destinations_dataframe, - oss_df=oss_destinations_dataframe, - primary_key="destinationDefinitionId", - connector_type="destination", - github_connector_folders=github_connector_folders, - ) - - -def _github_connector_folders() -> List[str]: - """ - Return a list of all the folders in the github connectors directory. - """ - folder_names = [item.name for item in scandir(CONNECTORS_PATH) if item.is_dir()] - return folder_names - - -def _load_registry(bucket: storage.Bucket, filename: str) -> ConnectorRegistryV0: - latest_oss_registry_gcs_blob = bucket.blob(f"{REGISTRIES_FOLDER}/{filename}") - json_string = latest_oss_registry_gcs_blob.download_as_string().decode("utf-8") - latest_cloud_registry_dict = json.loads(json_string) - return ConnectorRegistryV0.parse_obj(latest_cloud_registry_dict) - - -def generate_and_persist_registry_report(bucket_name: str) -> None: - """Generate and persist the registry report to GCS. - - Args: - bucket_name (str): The name of the bucket to persist the registry report to. - - Returns: - None - """ - client = get_gcs_storage_client() - bucket = client.bucket(bucket_name) - - github_connector_folders = _github_connector_folders() - - latest_cloud_registry = _load_registry(bucket, "cloud_registry.json") - latest_oss_registry = _load_registry(bucket, "oss_registry.json") - - all_destinations_dataframe = _all_destinations_dataframe( - _cloud_destinations_dataframe(latest_cloud_registry), - _oss_destinations_dataframe(latest_oss_registry), - github_connector_folders, - ) - all_sources_dataframe = _all_sources_dataframe( - _cloud_sources_dataframe(latest_cloud_registry), - _oss_sources_dataframe(latest_oss_registry), - github_connector_folders, - ) - - all_connectors_dataframe = pd.concat([all_destinations_dataframe, all_sources_dataframe]) - all_connectors_dataframe.reset_index(inplace=True) - - columns_to_show: List[ColumnInfo] = [ - { - "column": "name_oss", - "title": "Connector Name", - }, - { - "column": "definitionId", - "title": "Definition Id", - }, - { - "column": "iconUrl_oss", - "title": "Icon", - "formatter": icon_image_html, - }, - { - "column": "connector_type", - "title": "Connector Type", - }, - { - "column": "releaseStage_oss", - "title": "Release Stage", - }, - { - "column": "supportLevel_oss", - "title": "Support Level", - }, - { - "column": "ab_internal_sl", - "title": "Internal SL", - "formatter": internal_level_html, - }, - { - "column": "ab_internal_ql", - "title": "Internal QL", - "formatter": internal_level_html, - }, - { - "column": "test_summary_url", - "title": "Build Status", - "formatter": test_badge_html, - }, - { - "column": "is_oss", - "title": "OSS", - }, - { - "column": "is_cloud", - "title": "Cloud", - }, - { - "column": "docker_image_oss", - "title": "Docker Image OSS", - }, - { - "column": "docker_image_cloud", - "title": "Docker Image Cloud", - }, - { - "column": "docker_images_match", - "title": "OSS and Cloud Docker Images Match", - }, - { - "column": "github_url", - "title": "Source", - "formatter": simple_link_html, - }, - { - "column": "documentationUrl_oss", - "title": "Docs", - "formatter": simple_link_html, - }, - { - "column": "issue_url", - "title": "Issues", - "formatter": simple_link_html, - }, - ] - - html_string = render_connector_registry_locations_html( - destinations_table_html=dataframe_to_table_html(all_destinations_dataframe, columns_to_show), - sources_table_html=dataframe_to_table_html(all_sources_dataframe, columns_to_show), - ) - - json_string = all_connectors_dataframe.to_json(orient="records") - - json_file_blob = bucket.blob(f"{REPORT_FOLDER}/{REPORT_FILE_NAME}.json") - html_file_blob = bucket.blob(f"{REPORT_FOLDER}/{REPORT_FILE_NAME}.html") - try: - logger.info(f"Uploading registry report to GCS: {json_file_blob.name}") - json_file_blob.upload_from_string(json_string.encode()) - html_file_blob.upload_from_string(html_string.encode()) - except Exception as e: - logger.error(f"Error uploading registry report to GCS: {e}") - raise e diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/sentry.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/sentry.py deleted file mode 100644 index a482fb29873d..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/sentry.py +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -import logging -import os - -import sentry_sdk - -sentry_logger = logging.getLogger("sentry") - - -def setup_sentry(): - """ - Setup the sentry SDK if SENTRY_DSN is defined for the environment. - - Additionally TRACES_SAMPLE_RATE can be set 0-1 otherwise will default to 0. - """ - from sentry_sdk.integrations.argv import ArgvIntegration - from sentry_sdk.integrations.atexit import AtexitIntegration - from sentry_sdk.integrations.dedupe import DedupeIntegration - from sentry_sdk.integrations.logging import LoggingIntegration - from sentry_sdk.integrations.modules import ModulesIntegration - from sentry_sdk.integrations.stdlib import StdlibIntegration - - SENTRY_DSN = os.environ.get("SENTRY_DSN") - SENTRY_ENVIRONMENT = os.environ.get("SENTRY_ENVIRONMENT") - TRACES_SAMPLE_RATE = float(os.environ.get("SENTRY_TRACES_SAMPLE_RATE", 0)) - - sentry_logger.info("Setting up Sentry with") - sentry_logger.info(f"SENTRY_DSN: {SENTRY_DSN}") - sentry_logger.info(f"SENTRY_ENVIRONMENT: {SENTRY_ENVIRONMENT}") - sentry_logger.info(f"SENTRY_TRACES_SAMPLE_RATE: {TRACES_SAMPLE_RATE}") - - if SENTRY_DSN: - sentry_sdk.init( - dsn=SENTRY_DSN, - traces_sample_rate=TRACES_SAMPLE_RATE, - environment=SENTRY_ENVIRONMENT, - default_integrations=False, - integrations=[ - AtexitIntegration(), - DedupeIntegration(), - StdlibIntegration(), - ModulesIntegration(), - ArgvIntegration(), - LoggingIntegration(), - ], - ) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/spec_cache.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/spec_cache.py deleted file mode 100644 index 6495b34f9026..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/spec_cache.py +++ /dev/null @@ -1,120 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import json -from dataclasses import dataclass -from enum import Enum -from typing import List - -from google.cloud import storage - -PROD_SPEC_CACHE_BUCKET_NAME = "io-airbyte-cloud-spec-cache" -CACHE_FOLDER = "specs" - - -class Registries(str, Enum): - OSS = "oss" - CLOUD = "cloud" - - @classmethod - def _missing_(cls, value): - """Returns the registry from the string value. (case insensitive)""" - value = value.lower() - for member in cls: - if member.lower() == value: - return member - return None - - -SPEC_FILE_NAMES = {Registries.OSS: "spec.json", Registries.CLOUD: "spec.cloud.json"} - - -@dataclass -class CachedSpec: - docker_repository: str - docker_image_tag: str - spec_cache_path: str - registry: Registries - - def __str__(self) -> str: - return self.spec_cache_path - - -def get_spec_file_name(registry: Registries) -> str: - return SPEC_FILE_NAMES[registry] - - -def get_registry_from_spec_cache_path(spec_cache_path: str) -> Registries: - """Returns the registry from the spec cache path.""" - for registry in Registries: - file_name = get_spec_file_name(registry) - if file_name in spec_cache_path: - return registry - - raise Exception(f"Could not find any registry file name in spec cache path: {spec_cache_path}") - - -def get_docker_info_from_spec_cache_path(spec_cache_path: str) -> CachedSpec: - """Returns the docker repository and tag from the spec cache path.""" - - registry = get_registry_from_spec_cache_path(spec_cache_path) - registry_file_name = get_spec_file_name(registry) - - # remove the leading "specs/" from the path using CACHE_FOLDER - without_folder = spec_cache_path.replace(f"{CACHE_FOLDER}/", "") - without_file = without_folder.replace(f"/{registry_file_name}", "") - - # split on only the last "/" to get the docker repository and tag - # this is because the docker repository can have "/" in it - docker_image_tag = without_file.split("/")[-1] - docker_repository = without_file.replace(f"/{docker_image_tag}", "") - - return CachedSpec( - docker_repository=docker_repository, docker_image_tag=docker_image_tag, spec_cache_path=spec_cache_path, registry=registry - ) - - -class SpecCache: - def __init__(self, bucket_name: str = PROD_SPEC_CACHE_BUCKET_NAME): - self.client = storage.Client.create_anonymous_client() - self.bucket = self.client.bucket(bucket_name) - self.cached_specs = self.get_all_cached_specs() - - def get_all_cached_specs(self) -> List[CachedSpec]: - """Returns a list of all the specs in the spec cache bucket.""" - - blobs = self.bucket.list_blobs(prefix=CACHE_FOLDER) - - return [get_docker_info_from_spec_cache_path(blob.name) for blob in blobs if blob.name.endswith(".json")] - - def _find_spec_cache(self, docker_repository: str, docker_image_tag: str, registry: Registries) -> CachedSpec: - """Returns the spec cache path for a given docker repository and tag.""" - - # find the spec cache path for the given docker repository and tag - for cached_spec in self.cached_specs: - if ( - cached_spec.docker_repository == docker_repository - and cached_spec.registry == registry - and cached_spec.docker_image_tag == docker_image_tag - ): - return cached_spec - - return None - - def find_spec_cache_with_fallback(self, docker_repository: str, docker_image_tag: str, registry_str: str) -> CachedSpec: - """Returns the spec cache path for a given docker repository and tag and fallback to OSS if none found""" - registry = Registries(registry_str) - - # if the registry is cloud try to return the cloud spec first - if registry == Registries.CLOUD: - spec_cache = self._find_spec_cache(docker_repository, docker_image_tag, registry) - if spec_cache: - return spec_cache - - # fallback to OSS - return self._find_spec_cache(docker_repository, docker_image_tag, Registries.OSS) - - def download_spec(self, spec: CachedSpec) -> dict: - """Downloads the spec from the spec cache bucket.""" - return json.loads(self.bucket.blob(spec.spec_cache_path).download_as_string()) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/specs_secrets_mask.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/specs_secrets_mask.py deleted file mode 100644 index 6b15a7ebd057..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/specs_secrets_mask.py +++ /dev/null @@ -1,100 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# -import json -import logging -import os -from typing import Set - -import dpath.util -import sentry_sdk -import yaml -from google.cloud import storage -from google.oauth2 import service_account - -from metadata_service.constants import PUBLISH_UPDATE_CHANNEL, REGISTRIES_FOLDER, SPECS_SECRETS_MASK_FILE_NAME, VALID_REGISTRIES -from metadata_service.helpers.gcs import get_gcs_storage_client, safe_read_gcs_file -from metadata_service.helpers.slack import send_slack_message -from metadata_service.models.generated import ConnectorRegistryV0 -from metadata_service.models.transform import to_json_sanitized_dict -from metadata_service.registry import PolymorphicRegistryEntry - -logger = logging.getLogger(__name__) - - -@sentry_sdk.trace -def _get_registries_from_gcs(bucket: storage.Bucket) -> list[ConnectorRegistryV0]: - """Get the registries from GCS and return a list of ConnectorRegistryV0 objects.""" - registries = [] - for registry in VALID_REGISTRIES: - registry_name = f"{registry}_registry.json" - try: - logger.info(f"Getting registry {registry_name} from GCS") - blob = bucket.blob(f"{REGISTRIES_FOLDER}/{registry_name}") - registry_dict = json.loads(safe_read_gcs_file(blob)) - registries.append(ConnectorRegistryV0.parse_obj(registry_dict)) - except Exception as e: - logger.error(f"Error getting registry {registry_name} from GCS: {e}") - raise e - - return registries - - -def _get_specs_secrets_from_registry_entries(entries: list[PolymorphicRegistryEntry]) -> Set[str]: - """Get the specs secrets from the registry entries and return a set of secret properties.""" - secret_properties = set() - for entry in entries: - sanitized_entry = to_json_sanitized_dict(entry) - spec_properties = sanitized_entry["spec"]["connectionSpecification"].get("properties") - if spec_properties is None: - continue - for type_path, _ in dpath.util.search(spec_properties, "**/type", yielded=True): - absolute_path = f"/{type_path}" - if "/" in type_path: - property_path, _ = absolute_path.rsplit(sep="/", maxsplit=1) - else: - property_path = absolute_path - property_definition = dpath.util.get(spec_properties, property_path) - marked_as_secret = property_definition.get("airbyte_secret", False) - if marked_as_secret: - secret_properties.add(property_path.split("/")[-1]) - - return secret_properties - - -@sentry_sdk.trace -def _persist_secrets_to_gcs(specs_secrets: Set[str], bucket: storage.Bucket) -> None: - """Persist the specs secrets to GCS.""" - specs_secrets_mask_blob = bucket.blob(f"{REGISTRIES_FOLDER}/{SPECS_SECRETS_MASK_FILE_NAME}") - - try: - logger.info(f"Uploading specs secrets mask to GCS: {specs_secrets_mask_blob.name}") - specs_secrets_mask_blob.upload_from_string(yaml.dump({"properties": sorted(list(specs_secrets))})) - except Exception as e: - logger.error(f"Error uploading specs secrets mask to GCS: {e}") - raise e - - -def generate_and_persist_specs_secrets_mask(bucket_name: str) -> None: - """Generate and persist the specs secrets mask to GCS. - - Args: - bucket_name (str): The name of the bucket to persist the specs secrets mask to. - - Returns: - None - """ - - client = get_gcs_storage_client() - bucket = client.bucket(bucket_name) - - registries = _get_registries_from_gcs(bucket) - all_entries = [entry for registry in registries for entry in registry.sources + registry.destinations] - - all_specs_secrets = _get_specs_secrets_from_registry_entries(all_entries) - - try: - _persist_secrets_to_gcs(all_specs_secrets, bucket) - except Exception as e: - message = f"*🤖 🔴 _Specs Secrets Mask Generation_ FAILED*:\nFailed to generate and persist `{SPECS_SECRETS_MASK_FILE_NAME}` to registry GCS bucket." - send_slack_message(PUBLISH_UPDATE_CHANNEL, message) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/stale_metadata_report.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/stale_metadata_report.py deleted file mode 100644 index 74950b33c22f..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/stale_metadata_report.py +++ /dev/null @@ -1,262 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -import datetime -import logging -import os -import re -import textwrap -from typing import Any, Mapping, Optional - -import pandas as pd -import requests -import yaml -from github import Auth, Github - -from metadata_service.helpers.gcs import get_gcs_storage_client -from metadata_service.helpers.slack import send_slack_message -from metadata_service.models.generated import ConnectorMetadataDefinitionV0 - -from .constants import ( - EXTENSIBILITY_TEAM_SLACK_TEAM_ID, - GITHUB_REPO_NAME, - METADATA_FILE_NAME, - METADATA_FOLDER, - PUBLISH_GRACE_PERIOD, - PUBLISH_UPDATE_CHANNEL, - STALE_REPORT_CHANNEL, -) - -logger = logging.getLogger(__name__) - - -def _is_younger_than_grace_period(last_modified_at: datetime.datetime) -> bool: - """ - Determine if a metadata entry is younger than the grace period. - - Args: - last_modified_at (datetime.datetime): The last modified date of the metadata entry. - Returns: - bool: True if the metadata entry is younger than the grace period, False otherwise. - """ - grace_period_marker = datetime.datetime.now(datetime.timezone.utc) - PUBLISH_GRACE_PERIOD - return last_modified_at > grace_period_marker - - -def _entry_should_be_on_gcs(metadata_model: ConnectorMetadataDefinitionV0) -> bool: - """ - Determine if a metadata entry should be on GCS. - - Args: - metadata_model (ConnectorMetadataDefinitionV0): A ConnectorMetadataDefinitionV0 object. - Returns: - bool: True if the metadata entry should be on GCS, False otherwise. - """ - if metadata_model.data.supportLevel and metadata_model.data.supportLevel.__root__ == "archived": - logger.info( - f"Skipping. Connector `{metadata_model.data.dockerRepository}` is archived or does not have a support level. Support level: {metadata_model.data.supportLevel.__root__}" - ) - return False - if "-rc" in metadata_model.data.dockerImageTag: - logger.info( - f"Skipping. Connector `{metadata_model.data.dockerRepository}` is a release candidate. Docker image tag: {metadata_model.data.dockerImageTag}" - ) - return False - return True - - -def _get_github_metadata_download_urls() -> list[str]: - """ - Get the download URLs for the metadata files on GitHub. - - Returns: - list[str]: A list of download URLs for the metadata files on GitHub. - """ - github_token = os.getenv("GITHUB_TOKEN") - if not github_token: - raise ValueError("GITHUB_TOKEN is not set") - auth = Auth.Token(github_token) - github_client = Github(auth=auth) - repo = github_client.get_repo(GITHUB_REPO_NAME) - - query = f"repo:{repo.full_name} filename:{METADATA_FILE_NAME}" - file_contents = github_client.search_code(query) - - logger.debug("Getting the download URL for each found metadata file.") - - metadata_download_urls = [] - for file_content in file_contents: - logger.debug(f"File content path: {file_content.path}") - if re.match(r"airbyte-integrations/connectors/(source|destination)-.+/metadata\.yaml$", file_content.path): - logger.debug(f"Getting commits for file: {file_content.path}") - commits = repo.get_commits(path=file_content.path) - last_modified_at = commits[0].commit.author.date - if not _is_younger_than_grace_period(last_modified_at): - metadata_download_urls.append(file_content.download_url) - else: - logger.info( - f"Skipping. Metadata file on Github `{file_content.path}` was modified more recently than the grace period. Last modified at: {last_modified_at}" - ) - logger.debug(f"Found {len(metadata_download_urls)} download URLs") - - return metadata_download_urls - - -def _get_and_parse_metadata_files(metadata_download_urls: list[str]) -> list[ConnectorMetadataDefinitionV0]: - """ - Get and parse the contents of the metadata files. - - Args: - metadata_download_urls (list[str]): A list of download URLs for the metadata files. - Returns: - list[ConnectorMetadataDefinitionV0]: A list of ConnectorMetadataDefinitionV0 objects. - """ - logger.debug("Downloading and parsing the contents of the metadata files.") - connector_metadata_list = [] - for metadata_download_url in metadata_download_urls: - logger.debug(f"Downloading metadata from {metadata_download_url}") - response = requests.get(metadata_download_url) - response.raise_for_status() - metadata_yaml = response.text - metadata_dict = yaml.safe_load(metadata_yaml) - try: - connector_metadata = ConnectorMetadataDefinitionV0.parse_obj(metadata_dict) - connector_metadata_list.append(connector_metadata) - except Exception as e: - logger.info(f"Skipping. Failed to parse metadata for metadata at path: {metadata_download_url}. Exception: {e}") - continue - logger.debug(f"Parsed {len(connector_metadata_list)} metadata files") - return connector_metadata_list - - -def _get_latest_metadata_versions_on_github() -> Mapping[str, Any]: - """ - Get the latest metadata versions on GitHub. - - Returns: - Mapping[str, Any]: A mapping of connector names to their latest metadata versions on GitHub. - """ - logger.info(f"Getting latest metadata versions on GitHub for {GITHUB_REPO_NAME}") - - metadata_download_urls = _get_github_metadata_download_urls() - github_connector_metadata = _get_and_parse_metadata_files(metadata_download_urls) - - latest_metadata_versions_on_github = { - connector_metadata.data.dockerRepository: connector_metadata.data.dockerImageTag - for connector_metadata in github_connector_metadata - if _entry_should_be_on_gcs(connector_metadata) - } - - logger.info(f"Found {len(latest_metadata_versions_on_github)} connectors on GitHub") - - return latest_metadata_versions_on_github - - -def _get_latest_metadata_entries_on_gcs(bucket_name: str) -> Mapping[str, Any]: - """ - Get the latest metadata entries on GCS. - - Args: - bucket_name (str): The name of the GCS bucket to check for stale metadata. - Returns: - Mapping[str, Any]: A mapping of connector names to their latest metadata versions on GCS. - """ - logger.info(f"Getting latest metadata entries on GCS for {bucket_name}") - storage_client = get_gcs_storage_client() - bucket = storage_client.bucket(bucket_name) - - try: - logger.debug(f"Listing blobs in {bucket_name} with prefix {METADATA_FOLDER}/**/latest/{METADATA_FILE_NAME}") - blobs = bucket.list_blobs(match_glob=f"{METADATA_FOLDER}/**/latest/{METADATA_FILE_NAME}") - logger.debug("Found blobs.") - except Exception as e: - logger.error(f"Error getting blobs from GCS: {e}") - raise e - - latest_metadata_entries_on_gcs = {} - for blob in blobs: - metadata_dict = yaml.safe_load(blob.download_as_bytes().decode("utf-8")) - connector_metadata = ConnectorMetadataDefinitionV0.parse_obj(metadata_dict) - latest_metadata_entries_on_gcs[connector_metadata.data.dockerRepository] = connector_metadata.data.dockerImageTag - - logger.info(f"Found {len(latest_metadata_entries_on_gcs)} connectors on GCS") - return latest_metadata_entries_on_gcs - - -def _generate_stale_metadata_report( - latest_metadata_versions_on_github: Mapping[str, Any], latest_metadata_entries_on_gcs: Mapping[str, Any] -) -> pd.DataFrame: - """ - Generate the stale metadata report. - - Args: - latest_metadata_versions_on_github (Mapping[str, Any]): A mapping of connector names to their latest metadata versions on GitHub. - latest_metadata_entries_on_gcs (Mapping[str, Any]): A mapping of connector names to their latest metadata versions on GCS. - Returns: - pd.DataFrame: A DataFrame containing the stale metadata. - """ - stale_connectors = [] - for docker_repository, github_docker_image_tag in latest_metadata_versions_on_github.items(): - gcs_docker_image_tag = latest_metadata_entries_on_gcs.get(docker_repository) - if gcs_docker_image_tag != github_docker_image_tag: - stale_connectors.append( - {"connector": docker_repository, "master_version": github_docker_image_tag, "gcs_version": gcs_docker_image_tag} - ) - - stale_connectors.sort(key=lambda x: x.get("connector")) - return pd.DataFrame(stale_connectors) - - -def _publish_stale_metadata_report( - stale_metadata_report: pd.DataFrame, latest_metadata_versions_on_github_count: int, latest_metadata_versions_on_gcs_count: int -) -> tuple[bool, Optional[str]]: - """ - Publish the stale metadata report to the specified Slack channels. - - Args: - stale_metadata_report (pd.DataFrame): A DataFrame containing the stale metadata. - latest_metadata_versions_on_github_count (int): The number of metadata files on our master branch. - latest_metadata_versions_on_gcs_count (int): The number of latest metadata files hosted in GCS. - Returns: - tuple[bool, Optional[str]]: A tuple containing a boolean indicating whether the report was published and an error message. - """ - any_stale = len(stale_metadata_report) > 0 - if any_stale: - stale_report_md = stale_metadata_report.to_markdown(index=False) - send_slack_message(STALE_REPORT_CHANNEL, f"🚨 Stale metadata detected! (cc. )") - sent, error_message = send_slack_message(STALE_REPORT_CHANNEL, stale_report_md, enable_code_block_wrapping=True) - if not sent: - logger.error(f"Failed to send stale metadata report: {error_message}") - return sent, error_message - if not any_stale: - message = textwrap.dedent( - f""" - Analyzed {latest_metadata_versions_on_github_count} metadata files on our master branch and {latest_metadata_versions_on_gcs_count} latest metadata files hosted in GCS. - All dockerImageTag value on master match the latest metadata files on GCS. - No stale metadata: GCS metadata are up to date with metadata hosted on GCS. - """ - ) - sent, error_message = send_slack_message(PUBLISH_UPDATE_CHANNEL, message) - if not sent: - logger.error(f"Failed to send success message: {error_message}") - return sent, error_message - return True, None - - -def generate_and_publish_stale_metadata_report(bucket_name: str) -> tuple[bool, Optional[str]]: - """ - Generate a stale metadata report and publish it to a Slack channel. - - Args: - bucket_name (str): The name of the GCS bucket to check for stale metadata. - Returns: - tuple[bool, Optional[str]]: A tuple containing a boolean indicating whether the report was published and an optional error message. - """ - latest_metadata_entries_on_gcs = _get_latest_metadata_entries_on_gcs(bucket_name) - latest_metadata_versions_on_github = _get_latest_metadata_versions_on_github() - stale_metadata_report = _generate_stale_metadata_report(latest_metadata_versions_on_github, latest_metadata_entries_on_gcs) - report_published, error_message = _publish_stale_metadata_report( - stale_metadata_report, len(latest_metadata_versions_on_github), len(latest_metadata_entries_on_gcs) - ) - return report_published, error_message diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/templates/base.html b/airbyte-ci/connectors/metadata_service/lib/metadata_service/templates/base.html deleted file mode 100644 index 0415d0c0afec..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/templates/base.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - {% block title %}{% endblock %} - - - - - - - {% block content%} {% endblock %} - - diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/templates/connector_registry_locations.html b/airbyte-ci/connectors/metadata_service/lib/metadata_service/templates/connector_registry_locations.html deleted file mode 100644 index 9692e4435921..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/templates/connector_registry_locations.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends 'base.html' %} - -{% block title%}Airbyte Connector Registry{% endblock %} - -{% block content %} -

Airbyte Connector Registries

-

Sources

-
- {{ sources_table_html }} -
- -

Destinations

-
- {{ destinations_table_html }} -
-{% endblock %} \ No newline at end of file diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/templates/render.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/templates/render.py deleted file mode 100644 index 03cccb1f429d..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/templates/render.py +++ /dev/null @@ -1,101 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -import json -import urllib.parse -from dataclasses import dataclass -from datetime import timedelta -from typing import Any, Callable, Hashable, List, Optional - -import pandas as pd -from jinja2 import Environment, PackageLoader - -from metadata_service.helpers.object_helpers import deep_copy_params - -# 🔗 HTML Renderers - - -def simple_link_html(url: str) -> str | None: - if not url: - return None - - return f'🔗 Link' - - -def icon_image_html(icon_url: str) -> str | None: - if not icon_url: - return None - - icon_size = "30" - return f'' - - -def test_badge_html(test_summary_url: str) -> str | None: - if not test_summary_url: - return None - - report_url = f"{test_summary_url}/index.html" - image_shield_base = "https://img.shields.io/endpoint" - icon_url = f"{test_summary_url}/badge.json" - icon_url_encoded = urllib.parse.quote(icon_url) - icon_image = f'' - return f'{icon_image}' - - -def internal_level_html(level_value: float) -> str: - # cast to int to remove decimal places - level = int(level_value) - - return f"Level {level}" - - -# Dataframe to HTML - - -@dataclass -class ColumnInfo: - column: str - title: str - formatter: Optional[Callable[[Any], str]] = None - - -def dataframe_to_table_html(df: pd.DataFrame, column_mapping: List[ColumnInfo]) -> str: - """ - Convert a dataframe to an HTML table. - """ - - # convert true and false to checkmarks and x's - df.replace({True: "✅", False: "❌"}, inplace=True) - - title_mapping = {column_info["column"]: column_info["title"] for column_info in column_mapping} - - df.rename(columns=title_mapping, inplace=True) - - # explicit type decl to satisfy the type checker - html_formatters: dict[Hashable, Callable[[Any], str]] = { - column_info["title"]: column_info["formatter"] for column_info in column_mapping if "formatter" in column_info - } - - columns = [column_info["title"] for column_info in column_mapping] - - return df.to_html( - columns=columns, - justify="left", - index=False, - formatters=html_formatters, - escape=False, - classes="styled-table", - na_rep="❌", - render_links=True, - ) - - -# Templates - - -def render_connector_registry_locations_html(destinations_table_html: str, sources_table_html: str) -> str: - # yes, we really are dynamically loading the package - env = Environment(loader=PackageLoader("metadata_service", "templates")) - template = env.get_template("connector_registry_locations.html") - return template.render(destinations_table_html=destinations_table_html, sources_table_html=sources_table_html) diff --git a/airbyte-ci/connectors/metadata_service/lib/metadata_service/validators/metadata_validator.py b/airbyte-ci/connectors/metadata_service/lib/metadata_service/validators/metadata_validator.py deleted file mode 100644 index e4ee389d3a6d..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/metadata_service/validators/metadata_validator.py +++ /dev/null @@ -1,335 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import logging -import pathlib -from dataclasses import dataclass -from typing import Callable, List, Optional, Tuple, Union - -import semver -import yaml -from pydantic import ValidationError -from pydash.objects import get - -from metadata_service.docker_hub import get_latest_version_on_dockerhub, is_image_on_docker_hub -from metadata_service.models.generated.ConnectorMetadataDefinitionV0 import ConnectorMetadataDefinitionV0 - -logger = logging.getLogger(__name__) - - -@dataclass(frozen=True) -class ValidatorOptions: - docs_path: str - prerelease_tag: Optional[str] = None - disable_dockerhub_checks: bool = False - - -ValidationResult = Tuple[bool, Optional[Union[ValidationError, str]]] -Validator = Callable[[ConnectorMetadataDefinitionV0, ValidatorOptions], ValidationResult] - -_SOURCE_DECLARATIVE_MANIFEST_DEFINITION_ID = "64a2f99c-542f-4af8-9a6f-355f1217b436" - - -def validate_metadata_images_in_dockerhub( - metadata_definition: ConnectorMetadataDefinitionV0, validator_opts: ValidatorOptions -) -> ValidationResult: - if validator_opts.disable_dockerhub_checks: - return True, None - - metadata_definition_dict = metadata_definition.dict() - base_docker_image = get(metadata_definition_dict, "data.dockerRepository") - base_docker_version = get(metadata_definition_dict, "data.dockerImageTag") - - oss_docker_image = get(metadata_definition_dict, "data.registryOverrides.oss.dockerRepository", base_docker_image) - oss_docker_version = get(metadata_definition_dict, "data.registryOverrides.oss.dockerImageTag", base_docker_version) - - cloud_docker_image = get(metadata_definition_dict, "data.registryOverrides.cloud.dockerRepository", base_docker_image) - cloud_docker_version = get(metadata_definition_dict, "data.registryOverrides.cloud.dockerImageTag", base_docker_version) - - normalization_docker_image = get(metadata_definition_dict, "data.normalizationConfig.normalizationRepository", None) - normalization_docker_version = get(metadata_definition_dict, "data.normalizationConfig.normalizationTag", None) - - breaking_changes = get(metadata_definition_dict, "data.releases.breakingChanges", None) - breaking_change_versions = breaking_changes.keys() if breaking_changes else [] - - possible_docker_images = [ - (base_docker_image, base_docker_version), - (oss_docker_image, oss_docker_version), - (cloud_docker_image, cloud_docker_version), - (normalization_docker_image, normalization_docker_version), - ] - - if not validator_opts.prerelease_tag: - possible_docker_images.extend([(base_docker_image, version) for version in breaking_change_versions]) - - # Filter out tuples with None and remove duplicates - images_to_check = list(set(filter(lambda x: None not in x, possible_docker_images))) - - print(f"Checking that the following images are on dockerhub: {images_to_check}") - for image, version in images_to_check: - if not is_image_on_docker_hub(image, version, retries=3): - return False, f"Image {image}:{version} does not exist in DockerHub" - - return True, None - - -def validate_at_least_one_language_tag( - metadata_definition: ConnectorMetadataDefinitionV0, _validator_opts: ValidatorOptions -) -> ValidationResult: - """Ensure that there is at least one tag in the data.tags field that matches language:.""" - tags = get(metadata_definition, "data.tags", []) - if not any([tag.startswith("language:") for tag in tags]): - return False, "At least one tag must be of the form language:" - - return True, None - - -def validate_all_tags_are_keyvalue_pairs( - metadata_definition: ConnectorMetadataDefinitionV0, _validator_opts: ValidatorOptions -) -> ValidationResult: - """Ensure that all tags are of the form :.""" - tags = get(metadata_definition, "data.tags", []) - for tag in tags: - if ":" not in tag: - return False, f"Tag {tag} is not of the form :" - - return True, None - - -def is_major_version(version: str) -> bool: - """Check whether the version is of format N.0.0""" - semver_version = semver.Version.parse(version) - return semver_version.minor == 0 and semver_version.patch == 0 and semver_version.prerelease is None - - -def validate_major_version_bump_has_breaking_change_entry( - metadata_definition: ConnectorMetadataDefinitionV0, _validator_opts: ValidatorOptions -) -> ValidationResult: - """Ensure that if the major version is incremented, there is a breaking change entry for that version.""" - metadata_definition_dict = metadata_definition.dict() - image_tag = get(metadata_definition_dict, "data.dockerImageTag") - - if not is_major_version(image_tag): - return True, None - - # We are updating the same version since connector builder projects have a different concept of - # versioning. - # We do not check for breaking changes for source-declarative-connector in the metadata because the conenctor isn't directly used by any workspace. - # Breaking changes are instead tracked at the CDK level - if str(metadata_definition.data.definitionId) == _SOURCE_DECLARATIVE_MANIFEST_DEFINITION_ID: - return True, None - - releases = get(metadata_definition_dict, "data.releases") - if not releases: - return ( - False, - f"When doing a major version bump ({image_tag}), there must be a 'releases' property that contains 'breakingChanges' entries.", - ) - - breaking_changes = get(metadata_definition_dict, "data.releases.breakingChanges") - if breaking_changes is None or image_tag not in breaking_changes.keys(): - return False, f"Major version {image_tag} needs a 'releases.breakingChanges' entry indicating what changed." - - return True, None - - -def validate_docs_path_exists(metadata_definition: ConnectorMetadataDefinitionV0, validator_opts: ValidatorOptions) -> ValidationResult: - """Ensure that the doc_path exists.""" - if not pathlib.Path(validator_opts.docs_path).exists(): - return False, f"Could not find {validator_opts.docs_path}." - - return True, None - - -def validate_metadata_base_images_in_dockerhub( - metadata_definition: ConnectorMetadataDefinitionV0, validator_opts: ValidatorOptions -) -> ValidationResult: - if validator_opts.disable_dockerhub_checks: - return True, None - - metadata_definition_dict = metadata_definition.dict() - - image_address = get(metadata_definition_dict, "data.connectorBuildOptions.baseImage") - if image_address is None: - return True, None - - try: - image_name, tag_with_sha_prefix, digest = image_address.split(":") - # As we query the DockerHub API we need to remove the docker.io prefix - image_name = image_name.replace("docker.io/", "") - except ValueError: - return False, f"Image {image_address} is not in the format :@" - tag = tag_with_sha_prefix.split("@")[0] - - print(f"Checking that the base images is on dockerhub: {image_address}") - - if not is_image_on_docker_hub(image_name, tag, digest, retries=3): - return False, f"Image {image_address} does not exist in DockerHub" - - return True, None - - -def validate_pypi_only_for_python( - metadata_definition: ConnectorMetadataDefinitionV0, _validator_opts: ValidatorOptions -) -> ValidationResult: - """Ensure that if pypi publishing is enabled for a connector, it has a python language tag.""" - - pypi_enabled = get(metadata_definition, "data.remoteRegistries.pypi.enabled", False) - if not pypi_enabled: - return True, None - - tags = get(metadata_definition, "data.tags", []) - if "language:python" not in tags and "language:low-code" not in tags: - return False, "If pypi publishing is enabled, the connector must have a python language tag." - - return True, None - - -def validate_docker_image_tag_is_not_decremented( - metadata_definition: ConnectorMetadataDefinitionV0, _validator_opts: ValidatorOptions -) -> ValidationResult: - if _validator_opts and _validator_opts.disable_dockerhub_checks: - return True, None - if _validator_opts and _validator_opts.prerelease_tag: - return True, None - docker_image_name = get(metadata_definition, "data.dockerRepository") - if not docker_image_name: - return False, "The dockerRepository field is not set" - docker_image_tag = get(metadata_definition, "data.dockerImageTag") - if not docker_image_tag: - return False, "The dockerImageTag field is not set." - latest_released_version = get_latest_version_on_dockerhub(docker_image_name) - # This is happening when the connector has never been released to DockerHub - if not latest_released_version: - return True, None - if docker_image_tag == latest_released_version: - return True, None - current_semver_version = semver.Version.parse(docker_image_tag) - latest_released_semver_version = semver.Version.parse(latest_released_version) - if current_semver_version < latest_released_semver_version: - return ( - False, - f"The dockerImageTag value ({current_semver_version}) can't be decremented: it should be equal to or above {latest_released_version}.", - ) - return True, None - - -def check_is_dev_version(version: str) -> bool: - """Check whether the version is a pre-release version.""" - parsed_version = semver.VersionInfo.parse(version) - return parsed_version.prerelease is not None and not "rc" in parsed_version.prerelease - - -def check_is_release_candidate_version(version: str) -> bool: - """Check whether the version is a release candidate version.""" - parsed_version = semver.VersionInfo.parse(version) - return parsed_version.prerelease is not None and "rc" in parsed_version.prerelease - - -def check_is_major_release_candidate_version(version: str) -> bool: - """Check whether the version is a major release candidate version. - Example: 2.0.0-rc.1 - """ - - if not check_is_release_candidate_version(version): - return False - - # The version is a release candidate version - parsed_version = semver.VersionInfo.parse(version) - # No major version exists. - if parsed_version.major == 0: - return False - # The current release candidate is for a major version - if parsed_version.minor == 0 and parsed_version.patch == 0: - return True - - -def validate_rc_suffix_and_rollout_configuration( - metadata_definition: ConnectorMetadataDefinitionV0, _validator_opts: ValidatorOptions -) -> ValidationResult: - # Bypass validation for pre-releases - if _validator_opts and _validator_opts.prerelease_tag: - return True, None - - docker_image_tag = get(metadata_definition, "data.dockerImageTag") - if docker_image_tag is None: - return False, "The dockerImageTag field is not set." - try: - is_major_release_candidate_version = check_is_major_release_candidate_version(docker_image_tag) - is_dev_version = check_is_dev_version(docker_image_tag) - is_rc_version = check_is_release_candidate_version(docker_image_tag) - is_prerelease = is_dev_version or is_rc_version - enabled_progressive_rollout = get(metadata_definition, "data.releases.rolloutConfiguration.enableProgressiveRollout", None) - - # Major release candidate versions are not allowed - if is_major_release_candidate_version: - return ( - False, - "The dockerImageTag has an -rc. suffix for a major version. Release candidates for major version (with breaking changes) are not allowed.", - ) - - # Release candidates must have progressive rollout configuration set (True or False). - # Note: We allow False here because the rollback pipeline intentionally sets - # enableProgressiveRollout: false on RC versions to stop progressive rollout. - # The registry code at registry.py relies on this RC + false combination. - if is_rc_version and enabled_progressive_rollout is None: - return ( - False, - "The dockerImageTag field has an -rc. suffix but the connector is not set to use progressive rollout (releases.rolloutConfiguration.enableProgressiveRollout).", - ) - - # Progressive rollout can be enabled only for release candidates - if enabled_progressive_rollout is True and not is_prerelease: - return ( - False, - "The dockerImageTag field should have an -rc. suffix as the connector is set to use progressive rollout (releases.rolloutConfiguration.enableProgressiveRollout). Example: 2.1.0-rc.1", - ) - except ValueError: - return False, f"The dockerImageTag field is not a valid semver version: {docker_image_tag}." - - return True, None - - -PRE_UPLOAD_VALIDATORS = [ - validate_all_tags_are_keyvalue_pairs, - validate_at_least_one_language_tag, - validate_major_version_bump_has_breaking_change_entry, - validate_docs_path_exists, - validate_metadata_base_images_in_dockerhub, - validate_pypi_only_for_python, - validate_docker_image_tag_is_not_decremented, - validate_rc_suffix_and_rollout_configuration, -] - - -POST_UPLOAD_VALIDATORS = PRE_UPLOAD_VALIDATORS + [ - validate_metadata_images_in_dockerhub, -] - - -def validate_and_load( - file_path: pathlib.Path, - validators_to_run: List[Validator], - validator_opts: ValidatorOptions, -) -> Tuple[Optional[ConnectorMetadataDefinitionV0], Optional[ValidationError]]: - """Load a metadata file from a path (runs jsonschema validation) and run optional extra validators. - - Returns a tuple of (metadata_model, error_message). - If the metadata file is valid, metadata_model will be populated. - Otherwise, error_message will be populated with a string describing the error. - """ - try: - # Load the metadata file - this implicitly runs jsonschema validation - metadata = yaml.safe_load(file_path.read_text()) - metadata_model = ConnectorMetadataDefinitionV0.parse_obj(metadata) - except ValidationError as e: - return None, f"Validation error: {e}" - - for validator in validators_to_run: - print(f"Running validator: {validator.__name__}") - is_valid, error = validator(metadata_model, validator_opts) - if not is_valid: - return None, f"Validation error: {error}" - - return metadata_model, None diff --git a/airbyte-ci/connectors/metadata_service/lib/package-lock.json b/airbyte-ci/connectors/metadata_service/lib/package-lock.json deleted file mode 100644 index aab3f9ca2da3..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/package-lock.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "name": "metadata-service-schema-tools", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "metadata-service-schema-tools", - "version": "1.0.0", - "dependencies": { - "@apidevtools/json-schema-ref-parser": "^11.0.0" - } - }, - "node_modules/@apidevtools/json-schema-ref-parser": { - "version": "11.9.3", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.9.3.tgz", - "integrity": "sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ==", - "license": "MIT", - "dependencies": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.15", - "js-yaml": "^4.1.0" - }, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/philsturgeon" - } - }, - "node_modules/@jsdevtools/ono": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - } - } -} diff --git a/airbyte-ci/connectors/metadata_service/lib/package.json b/airbyte-ci/connectors/metadata_service/lib/package.json deleted file mode 100644 index af159ca7c3cd..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "metadata-service-schema-tools", - "version": "1.0.0", - "description": "Schema bundling tools for Airbyte metadata service", - "private": true, - "scripts": { - "bundle-schemas": "node bin/bundle-schemas.js" - }, - "dependencies": { - "@apidevtools/json-schema-ref-parser": "^11.0.0" - } -} diff --git a/airbyte-ci/connectors/metadata_service/lib/poetry.lock b/airbyte-ci/connectors/metadata_service/lib/poetry.lock deleted file mode 100644 index 2902507d74dd..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/poetry.lock +++ /dev/null @@ -1,2294 +0,0 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. - -[[package]] -name = "argcomplete" -version = "3.6.2" -description = "Bash tab completion for argparse" -optional = false -python-versions = ">=3.8" -files = [ - {file = "argcomplete-3.6.2-py3-none-any.whl", hash = "sha256:65b3133a29ad53fb42c48cf5114752c7ab66c1c38544fdf6460f450c09b42591"}, - {file = "argcomplete-3.6.2.tar.gz", hash = "sha256:d0519b1bc867f5f4f4713c41ad0aba73a4a5f007449716b16f385f2166dc6adf"}, -] - -[package.extras] -test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] - -[[package]] -name = "attrs" -version = "25.3.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.8" -files = [ - {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, - {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, -] - -[package.extras] -benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] - -[[package]] -name = "beautifulsoup4" -version = "4.13.5" -description = "Screen-scraping library" -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "beautifulsoup4-4.13.5-py3-none-any.whl", hash = "sha256:642085eaa22233aceadff9c69651bc51e8bf3f874fb6d7104ece2beb24b47c4a"}, - {file = "beautifulsoup4-4.13.5.tar.gz", hash = "sha256:5e70131382930e7c3de33450a2f54a63d5e4b19386eab43a5b34d594268f3695"}, -] - -[package.dependencies] -soupsieve = ">1.2" -typing-extensions = ">=4.0.0" - -[package.extras] -cchardet = ["cchardet"] -chardet = ["chardet"] -charset-normalizer = ["charset-normalizer"] -html5lib = ["html5lib"] -lxml = ["lxml"] - -[[package]] -name = "black" -version = "25.1.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.9" -files = [ - {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"}, - {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"}, - {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"}, - {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"}, - {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"}, - {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"}, - {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"}, - {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"}, - {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"}, - {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"}, - {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"}, - {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"}, - {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"}, - {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"}, - {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"}, - {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"}, - {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"}, - {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"}, - {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"}, - {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"}, - {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"}, - {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.10)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "cachetools" -version = "5.5.2" -description = "Extensible memoizing collections and decorators" -optional = false -python-versions = ">=3.7" -files = [ - {file = "cachetools-5.5.2-py3-none-any.whl", hash = "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a"}, - {file = "cachetools-5.5.2.tar.gz", hash = "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4"}, -] - -[[package]] -name = "certifi" -version = "2025.8.3" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.7" -files = [ - {file = "certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"}, - {file = "certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407"}, -] - -[[package]] -name = "cffi" -version = "1.17.1" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -files = [ - {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, - {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, - {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, - {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, - {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, - {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, - {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, - {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, - {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, - {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, - {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, - {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, - {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, - {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, - {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, - {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, -] - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "chardet" -version = "5.2.0" -description = "Universal encoding detector for Python 3" -optional = false -python-versions = ">=3.7" -files = [ - {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, - {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, -] - -[[package]] -name = "charset-normalizer" -version = "3.4.3" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7" -files = [ - {file = "charset_normalizer-3.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-win32.whl", hash = "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f"}, - {file = "charset_normalizer-3.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-win32.whl", hash = "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849"}, - {file = "charset_normalizer-3.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37"}, - {file = "charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce"}, - {file = "charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce"}, - {file = "charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-win32.whl", hash = "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557"}, - {file = "charset_normalizer-3.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-win32.whl", hash = "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432"}, - {file = "charset_normalizer-3.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca"}, - {file = "charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a"}, - {file = "charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14"}, -] - -[[package]] -name = "click" -version = "8.2.1" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.10" -files = [ - {file = "click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b"}, - {file = "click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "cryptography" -version = "45.0.6" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false -python-versions = "!=3.9.0,!=3.9.1,>=3.7" -files = [ - {file = "cryptography-45.0.6-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:048e7ad9e08cf4c0ab07ff7f36cc3115924e22e2266e034450a890d9e312dd74"}, - {file = "cryptography-45.0.6-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:44647c5d796f5fc042bbc6d61307d04bf29bccb74d188f18051b635f20a9c75f"}, - {file = "cryptography-45.0.6-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e40b80ecf35ec265c452eea0ba94c9587ca763e739b8e559c128d23bff7ebbbf"}, - {file = "cryptography-45.0.6-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:00e8724bdad672d75e6f069b27970883179bd472cd24a63f6e620ca7e41cc0c5"}, - {file = "cryptography-45.0.6-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a3085d1b319d35296176af31c90338eeb2ddac8104661df79f80e1d9787b8b2"}, - {file = "cryptography-45.0.6-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1b7fa6a1c1188c7ee32e47590d16a5a0646270921f8020efc9a511648e1b2e08"}, - {file = "cryptography-45.0.6-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:275ba5cc0d9e320cd70f8e7b96d9e59903c815ca579ab96c1e37278d231fc402"}, - {file = "cryptography-45.0.6-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:f4028f29a9f38a2025abedb2e409973709c660d44319c61762202206ed577c42"}, - {file = "cryptography-45.0.6-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ee411a1b977f40bd075392c80c10b58025ee5c6b47a822a33c1198598a7a5f05"}, - {file = "cryptography-45.0.6-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e2a21a8eda2d86bb604934b6b37691585bd095c1f788530c1fcefc53a82b3453"}, - {file = "cryptography-45.0.6-cp311-abi3-win32.whl", hash = "sha256:d063341378d7ee9c91f9d23b431a3502fc8bfacd54ef0a27baa72a0843b29159"}, - {file = "cryptography-45.0.6-cp311-abi3-win_amd64.whl", hash = "sha256:833dc32dfc1e39b7376a87b9a6a4288a10aae234631268486558920029b086ec"}, - {file = "cryptography-45.0.6-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:3436128a60a5e5490603ab2adbabc8763613f638513ffa7d311c900a8349a2a0"}, - {file = "cryptography-45.0.6-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0d9ef57b6768d9fa58e92f4947cea96ade1233c0e236db22ba44748ffedca394"}, - {file = "cryptography-45.0.6-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ea3c42f2016a5bbf71825537c2ad753f2870191134933196bee408aac397b3d9"}, - {file = "cryptography-45.0.6-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:20ae4906a13716139d6d762ceb3e0e7e110f7955f3bc3876e3a07f5daadec5f3"}, - {file = "cryptography-45.0.6-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dac5ec199038b8e131365e2324c03d20e97fe214af051d20c49db129844e8b3"}, - {file = "cryptography-45.0.6-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:18f878a34b90d688982e43f4b700408b478102dd58b3e39de21b5ebf6509c301"}, - {file = "cryptography-45.0.6-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:5bd6020c80c5b2b2242d6c48487d7b85700f5e0038e67b29d706f98440d66eb5"}, - {file = "cryptography-45.0.6-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:eccddbd986e43014263eda489abbddfbc287af5cddfd690477993dbb31e31016"}, - {file = "cryptography-45.0.6-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:550ae02148206beb722cfe4ef0933f9352bab26b087af00e48fdfb9ade35c5b3"}, - {file = "cryptography-45.0.6-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5b64e668fc3528e77efa51ca70fadcd6610e8ab231e3e06ae2bab3b31c2b8ed9"}, - {file = "cryptography-45.0.6-cp37-abi3-win32.whl", hash = "sha256:780c40fb751c7d2b0c6786ceee6b6f871e86e8718a8ff4bc35073ac353c7cd02"}, - {file = "cryptography-45.0.6-cp37-abi3-win_amd64.whl", hash = "sha256:20d15aed3ee522faac1a39fbfdfee25d17b1284bafd808e1640a74846d7c4d1b"}, - {file = "cryptography-45.0.6-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:705bb7c7ecc3d79a50f236adda12ca331c8e7ecfbea51edd931ce5a7a7c4f012"}, - {file = "cryptography-45.0.6-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:826b46dae41a1155a0c0e66fafba43d0ede1dc16570b95e40c4d83bfcf0a451d"}, - {file = "cryptography-45.0.6-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:cc4d66f5dc4dc37b89cfef1bd5044387f7a1f6f0abb490815628501909332d5d"}, - {file = "cryptography-45.0.6-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:f68f833a9d445cc49f01097d95c83a850795921b3f7cc6488731e69bde3288da"}, - {file = "cryptography-45.0.6-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:3b5bf5267e98661b9b888a9250d05b063220dfa917a8203744454573c7eb79db"}, - {file = "cryptography-45.0.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2384f2ab18d9be88a6e4f8972923405e2dbb8d3e16c6b43f15ca491d7831bd18"}, - {file = "cryptography-45.0.6-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fc022c1fa5acff6def2fc6d7819bbbd31ccddfe67d075331a65d9cfb28a20983"}, - {file = "cryptography-45.0.6-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:3de77e4df42ac8d4e4d6cdb342d989803ad37707cf8f3fbf7b088c9cbdd46427"}, - {file = "cryptography-45.0.6-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:599c8d7df950aa68baa7e98f7b73f4f414c9f02d0e8104a30c0182a07732638b"}, - {file = "cryptography-45.0.6-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:31a2b9a10530a1cb04ffd6aa1cd4d3be9ed49f7d77a4dafe198f3b382f41545c"}, - {file = "cryptography-45.0.6-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:e5b3dda1b00fb41da3af4c5ef3f922a200e33ee5ba0f0bc9ecf0b0c173958385"}, - {file = "cryptography-45.0.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:629127cfdcdc6806dfe234734d7cb8ac54edaf572148274fa377a7d3405b0043"}, - {file = "cryptography-45.0.6.tar.gz", hash = "sha256:5c966c732cf6e4a276ce83b6e4c729edda2df6929083a952cc7da973c539c719"}, -] - -[package.dependencies] -cffi = {version = ">=1.14", markers = "platform_python_implementation != \"PyPy\""} - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-inline-tabs", "sphinx-rtd-theme (>=3.0.0)"] -docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] -pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] -sdist = ["build (>=1.0.0)"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi (>=2024)", "cryptography-vectors (==45.0.6)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] -test-randomorder = ["pytest-randomly"] - -[[package]] -name = "datamodel-code-generator" -version = "0.17.2" -description = "Datamodel Code Generator" -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "datamodel_code_generator-0.17.2-py3-none-any.whl", hash = "sha256:b42b8b4da4055ea96ddf303efecfa37316bb025e88513fffc4dad960cb56b43c"}, - {file = "datamodel_code_generator-0.17.2.tar.gz", hash = "sha256:e88e000b254b07937a45902e95c08c9edec21eee3492c3a3ad4b6a4115345924"}, -] - -[package.dependencies] -argcomplete = ">=1.10,<4.0" -black = ">=19.10b0" -genson = ">=1.2.1,<2.0" -inflect = ">=4.1.0,<6.0" -isort = ">=4.3.21,<6.0" -jinja2 = ">=2.10.1,<4.0" -openapi-spec-validator = ">=0.2.8,<=0.5.1" -packaging = "*" -prance = ">=0.18.2,<1.0" -pydantic = {version = ">=1.10.0,<2.0", extras = ["email"], markers = "python_version >= \"3.11\""} -PySnooper = ">=0.4.1,<2.0.0" -toml = ">=0.10.0,<1.0.0" -typed-ast = {version = ">=1.5.0", markers = "python_full_version >= \"3.9.8\""} - -[package.extras] -http = ["httpx"] - -[[package]] -name = "dnspython" -version = "2.7.0" -description = "DNS toolkit" -optional = false -python-versions = ">=3.9" -files = [ - {file = "dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86"}, - {file = "dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1"}, -] - -[package.extras] -dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "hypercorn (>=0.16.0)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "quart-trio (>=0.11.0)", "sphinx (>=7.2.0)", "sphinx-rtd-theme (>=2.0.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"] -dnssec = ["cryptography (>=43)"] -doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"] -doq = ["aioquic (>=1.0.0)"] -idna = ["idna (>=3.7)"] -trio = ["trio (>=0.23)"] -wmi = ["wmi (>=1.5.1)"] - -[[package]] -name = "dpath" -version = "2.2.0" -description = "Filesystem-like pathing and searching for dictionaries" -optional = false -python-versions = ">=3.7" -files = [ - {file = "dpath-2.2.0-py3-none-any.whl", hash = "sha256:b330a375ded0a0d2ed404440f6c6a715deae5313af40bbb01c8a41d891900576"}, - {file = "dpath-2.2.0.tar.gz", hash = "sha256:34f7e630dc55ea3f219e555726f5da4b4b25f2200319c8e6902c394258dd6a3e"}, -] - -[[package]] -name = "email-validator" -version = "2.3.0" -description = "A robust email address syntax and deliverability validation library." -optional = false -python-versions = ">=3.8" -files = [ - {file = "email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4"}, - {file = "email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426"}, -] - -[package.dependencies] -dnspython = ">=2.0.0" -idna = ">=2.0.0" - -[[package]] -name = "future" -version = "1.0.0" -description = "Clean single-source support for Python 3 and 2" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "future-1.0.0-py3-none-any.whl", hash = "sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216"}, - {file = "future-1.0.0.tar.gz", hash = "sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05"}, -] - -[[package]] -name = "gax-google-logging-v2" -version = "0.8.3" -description = "GAX library for the Google Logging API" -optional = false -python-versions = "*" -files = [ - {file = "gax-google-logging-v2-0.8.3.tar.gz", hash = "sha256:c36cbb93e070b3b535e9fffff6879efe447e525dff75b62eb4564def515e1a18"}, -] - -[package.dependencies] -google-gax = ">=0.12.5,<0.13.0" -googleapis-common-protos = ">=1.1.0" -grpc-google-logging-v2 = ">=0.8.1,<0.9.0" -oauth2client = ">=1.4.11" - -[[package]] -name = "gax-google-pubsub-v1" -version = "0.8.3" -description = "DEPRECATED" -optional = false -python-versions = "*" -files = [ - {file = "gax-google-pubsub-v1-0.8.3.tar.gz", hash = "sha256:943df4aa05cf0302fa1616197d05e29adb62be2c0f55f80d8345439d72471526"}, -] - -[package.dependencies] -google-gax = ">=0.12.5,<0.13.0" -googleapis-common-protos = ">=1.1.0" -grpc-google-pubsub-v1 = ">=0.8.1,<0.9.0" -oauth2client = ">=1.4.11" - -[[package]] -name = "gcloud" -version = "0.18.3" -description = "API Client library for Google Cloud" -optional = false -python-versions = "*" -files = [ - {file = "gcloud-0.18.3.tar.gz", hash = "sha256:0af2dec59fce20561752f86e42d981c6a255e306a6c5e5d1fa3d358a8857e4fb"}, -] - -[package.dependencies] -gax-google-logging-v2 = ">=0.8.0,<0.9dev" -gax-google-pubsub-v1 = ">=0.8.0,<0.9dev" -google-gax = ">=0.12.3,<0.13dev" -googleapis-common-protos = "*" -grpc-google-logging-v2 = ">=0.8.0,<0.9dev" -grpc-google-pubsub-v1 = ">=0.8.0,<0.9dev" -grpcio = ">=1.0rc1" -httplib2 = ">=0.9.1" -oauth2client = ">=2.0.1" -protobuf = ">=3.0.0b2,<3.0.0.b2.post1 || >3.0.0.b2.post1" -six = "*" - -[package.extras] -grpc = ["gax-google-logging-v2 (>=0.8.0,<0.9dev)", "gax-google-pubsub-v1 (>=0.8.0,<0.9dev)", "google-gax (>=0.12.3,<0.13dev)", "grpc-google-logging-v2 (>=0.8.0,<0.9dev)", "grpc-google-pubsub-v1 (>=0.8.0,<0.9dev)", "grpcio (>=1.0rc1)"] - -[[package]] -name = "genson" -version = "1.3.0" -description = "GenSON is a powerful, user-friendly JSON Schema generator." -optional = false -python-versions = "*" -files = [ - {file = "genson-1.3.0-py3-none-any.whl", hash = "sha256:468feccd00274cc7e4c09e84b08704270ba8d95232aa280f65b986139cec67f7"}, - {file = "genson-1.3.0.tar.gz", hash = "sha256:e02db9ac2e3fd29e65b5286f7135762e2cd8a986537c075b06fc5f1517308e37"}, -] - -[[package]] -name = "gitdb" -version = "4.0.12" -description = "Git Object Database" -optional = false -python-versions = ">=3.7" -files = [ - {file = "gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf"}, - {file = "gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571"}, -] - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[[package]] -name = "gitpython" -version = "3.1.45" -description = "GitPython is a Python library used to interact with Git repositories" -optional = false -python-versions = ">=3.7" -files = [ - {file = "gitpython-3.1.45-py3-none-any.whl", hash = "sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77"}, - {file = "gitpython-3.1.45.tar.gz", hash = "sha256:85b0ee964ceddf211c41b9f27a49086010a190fd8132a24e21f362a4b36a791c"}, -] - -[package.dependencies] -gitdb = ">=4.0.1,<5" - -[package.extras] -doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] -test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions"] - -[[package]] -name = "google" -version = "3.0.0" -description = "Python bindings to the Google search engine." -optional = false -python-versions = "*" -files = [ - {file = "google-3.0.0-py2.py3-none-any.whl", hash = "sha256:889cf695f84e4ae2c55fbc0cfdaf4c1e729417fa52ab1db0485202ba173e4935"}, - {file = "google-3.0.0.tar.gz", hash = "sha256:143530122ee5130509ad5e989f0512f7cb218b2d4eddbafbad40fd10e8d8ccbe"}, -] - -[package.dependencies] -beautifulsoup4 = "*" - -[[package]] -name = "google-api-core" -version = "2.25.1" -description = "Google API client core library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "google_api_core-2.25.1-py3-none-any.whl", hash = "sha256:8a2a56c1fef82987a524371f99f3bd0143702fecc670c72e600c1cda6bf8dbb7"}, - {file = "google_api_core-2.25.1.tar.gz", hash = "sha256:d2aaa0b13c78c61cb3f4282c464c046e45fbd75755683c9c525e6e8f7ed0a5e8"}, -] - -[package.dependencies] -google-auth = ">=2.14.1,<3.0.0" -googleapis-common-protos = ">=1.56.2,<2.0.0" -proto-plus = [ - {version = ">=1.22.3,<2.0.0", markers = "python_version < \"3.13\""}, - {version = ">=1.25.0,<2.0.0", markers = "python_version >= \"3.13\""}, -] -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0" -requests = ">=2.18.0,<3.0.0" - -[package.extras] -async-rest = ["google-auth[aiohttp] (>=2.35.0,<3.0.0)"] -grpc = ["grpcio (>=1.33.2,<2.0.0)", "grpcio (>=1.49.1,<2.0.0)", "grpcio-status (>=1.33.2,<2.0.0)", "grpcio-status (>=1.49.1,<2.0.0)"] -grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.0)"] -grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.0)"] - -[[package]] -name = "google-auth" -version = "2.40.3" -description = "Google Authentication Library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "google_auth-2.40.3-py2.py3-none-any.whl", hash = "sha256:1370d4593e86213563547f97a92752fc658456fe4514c809544f330fed45a7ca"}, - {file = "google_auth-2.40.3.tar.gz", hash = "sha256:500c3a29adedeb36ea9cf24b8d10858e152f2412e3ca37829b3fa18e33d63b77"}, -] - -[package.dependencies] -cachetools = ">=2.0.0,<6.0" -pyasn1-modules = ">=0.2.1" -rsa = ">=3.1.4,<5" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0)", "requests (>=2.20.0,<3.0.0)"] -enterprise-cert = ["cryptography", "pyopenssl"] -pyjwt = ["cryptography (<39.0.0)", "cryptography (>=38.0.3)", "pyjwt (>=2.0)"] -pyopenssl = ["cryptography (<39.0.0)", "cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] -reauth = ["pyu2f (>=0.1.5)"] -requests = ["requests (>=2.20.0,<3.0.0)"] -testing = ["aiohttp (<3.10.0)", "aiohttp (>=3.6.2,<4.0.0)", "aioresponses", "cryptography (<39.0.0)", "cryptography (>=38.0.3)", "flask", "freezegun", "grpcio", "mock", "oauth2client", "packaging", "pyjwt (>=2.0)", "pyopenssl (<24.3.0)", "pyopenssl (>=20.0.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-localserver", "pyu2f (>=0.1.5)", "requests (>=2.20.0,<3.0.0)", "responses", "urllib3"] -urllib3 = ["packaging", "urllib3"] - -[[package]] -name = "google-cloud-core" -version = "2.4.3" -description = "Google Cloud API client core library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "google_cloud_core-2.4.3-py2.py3-none-any.whl", hash = "sha256:5130f9f4c14b4fafdff75c79448f9495cfade0d8775facf1b09c3bf67e027f6e"}, - {file = "google_cloud_core-2.4.3.tar.gz", hash = "sha256:1fab62d7102844b278fe6dead3af32408b1df3eb06f5c7e8634cbd40edc4da53"}, -] - -[package.dependencies] -google-api-core = ">=1.31.6,<2.0.dev0 || >2.3.0,<3.0.0dev" -google-auth = ">=1.25.0,<3.0dev" - -[package.extras] -grpc = ["grpcio (>=1.38.0,<2.0dev)", "grpcio-status (>=1.38.0,<2.0.dev0)"] - -[[package]] -name = "google-cloud-storage" -version = "2.19.0" -description = "Google Cloud Storage API client library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "google_cloud_storage-2.19.0-py2.py3-none-any.whl", hash = "sha256:aeb971b5c29cf8ab98445082cbfe7b161a1f48ed275822f59ed3f1524ea54fba"}, - {file = "google_cloud_storage-2.19.0.tar.gz", hash = "sha256:cd05e9e7191ba6cb68934d8eb76054d9be4562aa89dbc4236feee4d7d51342b2"}, -] - -[package.dependencies] -google-api-core = ">=2.15.0,<3.0.0dev" -google-auth = ">=2.26.1,<3.0dev" -google-cloud-core = ">=2.3.0,<3.0dev" -google-crc32c = ">=1.0,<2.0dev" -google-resumable-media = ">=2.7.2" -requests = ">=2.18.0,<3.0.0dev" - -[package.extras] -protobuf = ["protobuf (<6.0.0dev)"] -tracing = ["opentelemetry-api (>=1.1.0)"] - -[[package]] -name = "google-crc32c" -version = "1.7.1" -description = "A python wrapper of the C library 'Google CRC32C'" -optional = false -python-versions = ">=3.9" -files = [ - {file = "google_crc32c-1.7.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:b07d48faf8292b4db7c3d64ab86f950c2e94e93a11fd47271c28ba458e4a0d76"}, - {file = "google_crc32c-1.7.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:7cc81b3a2fbd932a4313eb53cc7d9dde424088ca3a0337160f35d91826880c1d"}, - {file = "google_crc32c-1.7.1-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1c67ca0a1f5b56162951a9dae987988679a7db682d6f97ce0f6381ebf0fbea4c"}, - {file = "google_crc32c-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc5319db92daa516b653600794d5b9f9439a9a121f3e162f94b0e1891c7933cb"}, - {file = "google_crc32c-1.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcdf5a64adb747610140572ed18d011896e3b9ae5195f2514b7ff678c80f1603"}, - {file = "google_crc32c-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:754561c6c66e89d55754106739e22fdaa93fafa8da7221b29c8b8e8270c6ec8a"}, - {file = "google_crc32c-1.7.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:6fbab4b935989e2c3610371963ba1b86afb09537fd0c633049be82afe153ac06"}, - {file = "google_crc32c-1.7.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:ed66cbe1ed9cbaaad9392b5259b3eba4a9e565420d734e6238813c428c3336c9"}, - {file = "google_crc32c-1.7.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee6547b657621b6cbed3562ea7826c3e11cab01cd33b74e1f677690652883e77"}, - {file = "google_crc32c-1.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d68e17bad8f7dd9a49181a1f5a8f4b251c6dbc8cc96fb79f1d321dfd57d66f53"}, - {file = "google_crc32c-1.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:6335de12921f06e1f774d0dd1fbea6bf610abe0887a1638f64d694013138be5d"}, - {file = "google_crc32c-1.7.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:2d73a68a653c57281401871dd4aeebbb6af3191dcac751a76ce430df4d403194"}, - {file = "google_crc32c-1.7.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:22beacf83baaf59f9d3ab2bbb4db0fb018da8e5aebdce07ef9f09fce8220285e"}, - {file = "google_crc32c-1.7.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19eafa0e4af11b0a4eb3974483d55d2d77ad1911e6cf6f832e1574f6781fd337"}, - {file = "google_crc32c-1.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d86616faaea68101195c6bdc40c494e4d76f41e07a37ffdef270879c15fb65"}, - {file = "google_crc32c-1.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:b7491bdc0c7564fcf48c0179d2048ab2f7c7ba36b84ccd3a3e1c3f7a72d3bba6"}, - {file = "google_crc32c-1.7.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:df8b38bdaf1629d62d51be8bdd04888f37c451564c2042d36e5812da9eff3c35"}, - {file = "google_crc32c-1.7.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:e42e20a83a29aa2709a0cf271c7f8aefaa23b7ab52e53b322585297bb94d4638"}, - {file = "google_crc32c-1.7.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:905a385140bf492ac300026717af339790921f411c0dfd9aa5a9e69a08ed32eb"}, - {file = "google_crc32c-1.7.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b211ddaf20f7ebeec5c333448582c224a7c90a9d98826fbab82c0ddc11348e6"}, - {file = "google_crc32c-1.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:0f99eaa09a9a7e642a61e06742856eec8b19fc0037832e03f941fe7cf0c8e4db"}, - {file = "google_crc32c-1.7.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32d1da0d74ec5634a05f53ef7df18fc646666a25efaaca9fc7dcfd4caf1d98c3"}, - {file = "google_crc32c-1.7.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e10554d4abc5238823112c2ad7e4560f96c7bf3820b202660373d769d9e6e4c9"}, - {file = "google_crc32c-1.7.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:9fc196f0b8d8bd2789352c6a522db03f89e83a0ed6b64315923c396d7a932315"}, - {file = "google_crc32c-1.7.1-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:bb5e35dcd8552f76eed9461a23de1030920a3c953c1982f324be8f97946e7127"}, - {file = "google_crc32c-1.7.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f2226b6a8da04f1d9e61d3e357f2460b9551c5e6950071437e122c958a18ae14"}, - {file = "google_crc32c-1.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f2b3522222746fff0e04a9bd0a23ea003ba3cccc8cf21385c564deb1f223242"}, - {file = "google_crc32c-1.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3bda0fcb632d390e3ea8b6b07bf6b4f4a66c9d02dcd6fbf7ba00a197c143f582"}, - {file = "google_crc32c-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:713121af19f1a617054c41f952294764e0c5443d5a5d9034b2cd60f5dd7e0349"}, - {file = "google_crc32c-1.7.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8e9afc74168b0b2232fb32dd202c93e46b7d5e4bf03e66ba5dc273bb3559589"}, - {file = "google_crc32c-1.7.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa8136cc14dd27f34a3221c0f16fd42d8a40e4778273e61a3c19aedaa44daf6b"}, - {file = "google_crc32c-1.7.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85fef7fae11494e747c9fd1359a527e5970fc9603c90764843caabd3a16a0a48"}, - {file = "google_crc32c-1.7.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6efb97eb4369d52593ad6f75e7e10d053cf00c48983f7a973105bc70b0ac4d82"}, - {file = "google_crc32c-1.7.1.tar.gz", hash = "sha256:2bff2305f98846f3e825dbeec9ee406f89da7962accdb29356e4eadc251bd472"}, -] - -[package.extras] -testing = ["pytest"] - -[[package]] -name = "google-gax" -version = "0.12.5" -description = "Google API Extensions" -optional = false -python-versions = "*" -files = [ - {file = "google-gax-0.12.5.tar.gz", hash = "sha256:63312a04cb87ca50e857245f05c582b2171807a30e61cef85006b983bf659cb9"}, -] - -[package.dependencies] -future = ">=0.15.2" -grpcio = ">=1.0rc1" -oauth2client = ">=1.5.2" -ply = "3.8" -protobuf = ">=3.0.0b3" - -[[package]] -name = "google-resumable-media" -version = "2.7.2" -description = "Utilities for Google Media Downloads and Resumable Uploads" -optional = false -python-versions = ">=3.7" -files = [ - {file = "google_resumable_media-2.7.2-py2.py3-none-any.whl", hash = "sha256:3ce7551e9fe6d99e9a126101d2536612bb73486721951e9562fee0f90c6ababa"}, - {file = "google_resumable_media-2.7.2.tar.gz", hash = "sha256:5280aed4629f2b60b847b0d42f9857fd4935c11af266744df33d8074cae92fe0"}, -] - -[package.dependencies] -google-crc32c = ">=1.0,<2.0dev" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)", "google-auth (>=1.22.0,<2.0dev)"] -requests = ["requests (>=2.18.0,<3.0.0dev)"] - -[[package]] -name = "googleapis-common-protos" -version = "1.70.0" -description = "Common protobufs used in Google APIs" -optional = false -python-versions = ">=3.7" -files = [ - {file = "googleapis_common_protos-1.70.0-py3-none-any.whl", hash = "sha256:b8bfcca8c25a2bb253e0e0b0adaf8c00773e5e6af6fd92397576680b807e0fd8"}, - {file = "googleapis_common_protos-1.70.0.tar.gz", hash = "sha256:0e1b44e0ea153e6594f9f394fef15193a68aaaea2d843f83e2742717ca753257"}, -] - -[package.dependencies] -protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0" - -[package.extras] -grpc = ["grpcio (>=1.44.0,<2.0.0)"] - -[[package]] -name = "grpc-google-logging-v2" -version = "0.8.1" -description = "GRPC library for the google-logging-v2 service" -optional = false -python-versions = "*" -files = [ - {file = "grpc-google-logging-v2-0.8.1.tar.gz", hash = "sha256:4b6b4e603860b134b2cb8732bb4d1f2cec963d553497dcf70b3f5ecc99d7fb4f"}, -] - -[package.dependencies] -googleapis-common-protos = ">=1.1.0" -grpcio = ">=1.0rc1" -oauth2client = ">=1.4.11" - -[[package]] -name = "grpc-google-pubsub-v1" -version = "0.8.1" -description = "GRPC library for the google-pubsub-v1 service" -optional = false -python-versions = "*" -files = [ - {file = "grpc-google-pubsub-v1-0.8.1.tar.gz", hash = "sha256:ab5a3a239a9678012cdc00a9b9a8fe8c75fca9a0035da41da3078145e9d967b9"}, -] - -[package.dependencies] -googleapis-common-protos = ">=1.1.0" -grpcio = ">=1.0rc1" -oauth2client = ">=1.4.11" - -[[package]] -name = "grpcio" -version = "1.74.0" -description = "HTTP/2-based RPC framework" -optional = false -python-versions = ">=3.9" -files = [ - {file = "grpcio-1.74.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:85bd5cdf4ed7b2d6438871adf6afff9af7096486fcf51818a81b77ef4dd30907"}, - {file = "grpcio-1.74.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:68c8ebcca945efff9d86d8d6d7bfb0841cf0071024417e2d7f45c5e46b5b08eb"}, - {file = "grpcio-1.74.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:e154d230dc1bbbd78ad2fdc3039fa50ad7ffcf438e4eb2fa30bce223a70c7486"}, - {file = "grpcio-1.74.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8978003816c7b9eabe217f88c78bc26adc8f9304bf6a594b02e5a49b2ef9c11"}, - {file = "grpcio-1.74.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3d7bd6e3929fd2ea7fbc3f562e4987229ead70c9ae5f01501a46701e08f1ad9"}, - {file = "grpcio-1.74.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:136b53c91ac1d02c8c24201bfdeb56f8b3ac3278668cbb8e0ba49c88069e1bdc"}, - {file = "grpcio-1.74.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fe0f540750a13fd8e5da4b3eaba91a785eea8dca5ccd2bc2ffe978caa403090e"}, - {file = "grpcio-1.74.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4e4181bfc24413d1e3a37a0b7889bea68d973d4b45dd2bc68bb766c140718f82"}, - {file = "grpcio-1.74.0-cp310-cp310-win32.whl", hash = "sha256:1733969040989f7acc3d94c22f55b4a9501a30f6aaacdbccfaba0a3ffb255ab7"}, - {file = "grpcio-1.74.0-cp310-cp310-win_amd64.whl", hash = "sha256:9e912d3c993a29df6c627459af58975b2e5c897d93287939b9d5065f000249b5"}, - {file = "grpcio-1.74.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:69e1a8180868a2576f02356565f16635b99088da7df3d45aaa7e24e73a054e31"}, - {file = "grpcio-1.74.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:8efe72fde5500f47aca1ef59495cb59c885afe04ac89dd11d810f2de87d935d4"}, - {file = "grpcio-1.74.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:a8f0302f9ac4e9923f98d8e243939a6fb627cd048f5cd38595c97e38020dffce"}, - {file = "grpcio-1.74.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f609a39f62a6f6f05c7512746798282546358a37ea93c1fcbadf8b2fed162e3"}, - {file = "grpcio-1.74.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c98e0b7434a7fa4e3e63f250456eaef52499fba5ae661c58cc5b5477d11e7182"}, - {file = "grpcio-1.74.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:662456c4513e298db6d7bd9c3b8df6f75f8752f0ba01fb653e252ed4a59b5a5d"}, - {file = "grpcio-1.74.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3d14e3c4d65e19d8430a4e28ceb71ace4728776fd6c3ce34016947474479683f"}, - {file = "grpcio-1.74.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bf949792cee20d2078323a9b02bacbbae002b9e3b9e2433f2741c15bdeba1c4"}, - {file = "grpcio-1.74.0-cp311-cp311-win32.whl", hash = "sha256:55b453812fa7c7ce2f5c88be3018fb4a490519b6ce80788d5913f3f9d7da8c7b"}, - {file = "grpcio-1.74.0-cp311-cp311-win_amd64.whl", hash = "sha256:86ad489db097141a907c559988c29718719aa3e13370d40e20506f11b4de0d11"}, - {file = "grpcio-1.74.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:8533e6e9c5bd630ca98062e3a1326249e6ada07d05acf191a77bc33f8948f3d8"}, - {file = "grpcio-1.74.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:2918948864fec2a11721d91568effffbe0a02b23ecd57f281391d986847982f6"}, - {file = "grpcio-1.74.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:60d2d48b0580e70d2e1954d0d19fa3c2e60dd7cbed826aca104fff518310d1c5"}, - {file = "grpcio-1.74.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3601274bc0523f6dc07666c0e01682c94472402ac2fd1226fd96e079863bfa49"}, - {file = "grpcio-1.74.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:176d60a5168d7948539def20b2a3adcce67d72454d9ae05969a2e73f3a0feee7"}, - {file = "grpcio-1.74.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e759f9e8bc908aaae0412642afe5416c9f983a80499448fcc7fab8692ae044c3"}, - {file = "grpcio-1.74.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9e7c4389771855a92934b2846bd807fc25a3dfa820fd912fe6bd8136026b2707"}, - {file = "grpcio-1.74.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cce634b10aeab37010449124814b05a62fb5f18928ca878f1bf4750d1f0c815b"}, - {file = "grpcio-1.74.0-cp312-cp312-win32.whl", hash = "sha256:885912559974df35d92219e2dc98f51a16a48395f37b92865ad45186f294096c"}, - {file = "grpcio-1.74.0-cp312-cp312-win_amd64.whl", hash = "sha256:42f8fee287427b94be63d916c90399ed310ed10aadbf9e2e5538b3e497d269bc"}, - {file = "grpcio-1.74.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:2bc2d7d8d184e2362b53905cb1708c84cb16354771c04b490485fa07ce3a1d89"}, - {file = "grpcio-1.74.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:c14e803037e572c177ba54a3e090d6eb12efd795d49327c5ee2b3bddb836bf01"}, - {file = "grpcio-1.74.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:f6ec94f0e50eb8fa1744a731088b966427575e40c2944a980049798b127a687e"}, - {file = "grpcio-1.74.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:566b9395b90cc3d0d0c6404bc8572c7c18786ede549cdb540ae27b58afe0fb91"}, - {file = "grpcio-1.74.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1ea6176d7dfd5b941ea01c2ec34de9531ba494d541fe2057c904e601879f249"}, - {file = "grpcio-1.74.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:64229c1e9cea079420527fa8ac45d80fc1e8d3f94deaa35643c381fa8d98f362"}, - {file = "grpcio-1.74.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:0f87bddd6e27fc776aacf7ebfec367b6d49cad0455123951e4488ea99d9b9b8f"}, - {file = "grpcio-1.74.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:3b03d8f2a07f0fea8c8f74deb59f8352b770e3900d143b3d1475effcb08eec20"}, - {file = "grpcio-1.74.0-cp313-cp313-win32.whl", hash = "sha256:b6a73b2ba83e663b2480a90b82fdae6a7aa6427f62bf43b29912c0cfd1aa2bfa"}, - {file = "grpcio-1.74.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd3c71aeee838299c5887230b8a1822795325ddfea635edd82954c1eaa831e24"}, - {file = "grpcio-1.74.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:4bc5fca10aaf74779081e16c2bcc3d5ec643ffd528d9e7b1c9039000ead73bae"}, - {file = "grpcio-1.74.0-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:6bab67d15ad617aff094c382c882e0177637da73cbc5532d52c07b4ee887a87b"}, - {file = "grpcio-1.74.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:655726919b75ab3c34cdad39da5c530ac6fa32696fb23119e36b64adcfca174a"}, - {file = "grpcio-1.74.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a2b06afe2e50ebfd46247ac3ba60cac523f54ec7792ae9ba6073c12daf26f0a"}, - {file = "grpcio-1.74.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f251c355167b2360537cf17bea2cf0197995e551ab9da6a0a59b3da5e8704f9"}, - {file = "grpcio-1.74.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8f7b5882fb50632ab1e48cb3122d6df55b9afabc265582808036b6e51b9fd6b7"}, - {file = "grpcio-1.74.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:834988b6c34515545b3edd13e902c1acdd9f2465d386ea5143fb558f153a7176"}, - {file = "grpcio-1.74.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:22b834cef33429ca6cc28303c9c327ba9a3fafecbf62fae17e9a7b7163cc43ac"}, - {file = "grpcio-1.74.0-cp39-cp39-win32.whl", hash = "sha256:7d95d71ff35291bab3f1c52f52f474c632db26ea12700c2ff0ea0532cb0b5854"}, - {file = "grpcio-1.74.0-cp39-cp39-win_amd64.whl", hash = "sha256:ecde9ab49f58433abe02f9ed076c7b5be839cf0153883a6d23995937a82392fa"}, - {file = "grpcio-1.74.0.tar.gz", hash = "sha256:80d1f4fbb35b0742d3e3d3bb654b7381cd5f015f8497279a1e9c21ba623e01b1"}, -] - -[package.extras] -protobuf = ["grpcio-tools (>=1.74.0)"] - -[[package]] -name = "httplib2" -version = "0.22.0" -description = "A comprehensive HTTP client library." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "httplib2-0.22.0-py3-none-any.whl", hash = "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc"}, - {file = "httplib2-0.22.0.tar.gz", hash = "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81"}, -] - -[package.dependencies] -pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0.2,<3.0.3 || >3.0.3,<4", markers = "python_version > \"3.0\""} - -[[package]] -name = "idna" -version = "3.10" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.6" -files = [ - {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, - {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, -] - -[package.extras] -all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] - -[[package]] -name = "importlib-resources" -version = "5.13.0" -description = "Read resources from Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "importlib_resources-5.13.0-py3-none-any.whl", hash = "sha256:9f7bd0c97b79972a6cce36a366356d16d5e13b09679c11a58f1014bfdf8e64b2"}, - {file = "importlib_resources-5.13.0.tar.gz", hash = "sha256:82d5c6cca930697dbbd86c93333bb2c2e72861d4789a11c2662b933e5ad2b528"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] - -[[package]] -name = "inflect" -version = "5.6.2" -description = "Correctly generate plurals, singular nouns, ordinals, indefinite articles; convert numbers to words" -optional = false -python-versions = ">=3.7" -files = [ - {file = "inflect-5.6.2-py3-none-any.whl", hash = "sha256:b45d91a4a28a4e617ff1821117439b06eaa86e2a4573154af0149e9be6687238"}, - {file = "inflect-5.6.2.tar.gz", hash = "sha256:aadc7ed73928f5e014129794bbac03058cca35d0a973a5fc4eb45c7fa26005f9"}, -] - -[package.extras] -docs = ["jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx"] -testing = ["pygments", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] - -[[package]] -name = "iniconfig" -version = "2.1.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.8" -files = [ - {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, - {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, -] - -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - -[[package]] -name = "jinja2" -version = "3.1.6" -description = "A very fast and expressive template engine." -optional = false -python-versions = ">=3.7" -files = [ - {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, - {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "jsonschema" -version = "4.17.3" -description = "An implementation of JSON Schema validation for Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, - {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, -] - -[package.dependencies] -attrs = ">=17.4.0" -pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" - -[package.extras] -format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] - -[[package]] -name = "jsonschema-spec" -version = "0.1.6" -description = "JSONSchema Spec with object-oriented paths" -optional = false -python-versions = ">=3.7.0,<4.0.0" -files = [ - {file = "jsonschema_spec-0.1.6-py3-none-any.whl", hash = "sha256:f2206d18c89d1824c1f775ba14ed039743b41a9167bd2c5bdb774b66b3ca0bbf"}, - {file = "jsonschema_spec-0.1.6.tar.gz", hash = "sha256:90215863b56e212086641956b20127ccbf6d8a3a38343dad01d6a74d19482f76"}, -] - -[package.dependencies] -jsonschema = ">=4.0.0,<4.18.0" -pathable = ">=0.4.1,<0.5.0" -PyYAML = ">=5.1" -requests = ">=2.31.0,<3.0.0" - -[[package]] -name = "lazy-object-proxy" -version = "1.12.0" -description = "A fast and thorough lazy object proxy." -optional = false -python-versions = ">=3.9" -files = [ - {file = "lazy_object_proxy-1.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61d5e3310a4aa5792c2b599a7a78ccf8687292c8eb09cf187cca8f09cf6a7519"}, - {file = "lazy_object_proxy-1.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1ca33565f698ac1aece152a10f432415d1a2aa9a42dfe23e5ba2bc255ab91f6"}, - {file = "lazy_object_proxy-1.12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d01c7819a410f7c255b20799b65d36b414379a30c6f1684c7bd7eb6777338c1b"}, - {file = "lazy_object_proxy-1.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:029d2b355076710505c9545aef5ab3f750d89779310e26ddf2b7b23f6ea03cd8"}, - {file = "lazy_object_proxy-1.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc6e3614eca88b1c8a625fc0a47d0d745e7c3255b21dac0e30b3037c5e3deeb8"}, - {file = "lazy_object_proxy-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:be5fe974e39ceb0d6c9db0663c0464669cf866b2851c73971409b9566e880eab"}, - {file = "lazy_object_proxy-1.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1cf69cd1a6c7fe2dbcc3edaa017cf010f4192e53796538cc7d5e1fedbfa4bcff"}, - {file = "lazy_object_proxy-1.12.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:efff4375a8c52f55a145dc8487a2108c2140f0bec4151ab4e1843e52eb9987ad"}, - {file = "lazy_object_proxy-1.12.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1192e8c2f1031a6ff453ee40213afa01ba765b3dc861302cd91dbdb2e2660b00"}, - {file = "lazy_object_proxy-1.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3605b632e82a1cbc32a1e5034278a64db555b3496e0795723ee697006b980508"}, - {file = "lazy_object_proxy-1.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a61095f5d9d1a743e1e20ec6d6db6c2ca511961777257ebd9b288951b23b44fa"}, - {file = "lazy_object_proxy-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:997b1d6e10ecc6fb6fe0f2c959791ae59599f41da61d652f6c903d1ee58b7370"}, - {file = "lazy_object_proxy-1.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8ee0d6027b760a11cc18281e702c0309dd92da458a74b4c15025d7fc490deede"}, - {file = "lazy_object_proxy-1.12.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4ab2c584e3cc8be0dfca422e05ad30a9abe3555ce63e9ab7a559f62f8dbc6ff9"}, - {file = "lazy_object_proxy-1.12.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:14e348185adbd03ec17d051e169ec45686dcd840a3779c9d4c10aabe2ca6e1c0"}, - {file = "lazy_object_proxy-1.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c4fcbe74fb85df8ba7825fa05eddca764138da752904b378f0ae5ab33a36c308"}, - {file = "lazy_object_proxy-1.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:563d2ec8e4d4b68ee7848c5ab4d6057a6d703cb7963b342968bb8758dda33a23"}, - {file = "lazy_object_proxy-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:53c7fd99eb156bbb82cbc5d5188891d8fdd805ba6c1e3b92b90092da2a837073"}, - {file = "lazy_object_proxy-1.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:86fd61cb2ba249b9f436d789d1356deae69ad3231dc3c0f17293ac535162672e"}, - {file = "lazy_object_proxy-1.12.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:81d1852fb30fab81696f93db1b1e55a5d1ff7940838191062f5f56987d5fcc3e"}, - {file = "lazy_object_proxy-1.12.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be9045646d83f6c2664c1330904b245ae2371b5c57a3195e4028aedc9f999655"}, - {file = "lazy_object_proxy-1.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:67f07ab742f1adfb3966c40f630baaa7902be4222a17941f3d85fd1dae5565ff"}, - {file = "lazy_object_proxy-1.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:75ba769017b944fcacbf6a80c18b2761a1795b03f8899acdad1f1c39db4409be"}, - {file = "lazy_object_proxy-1.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:7b22c2bbfb155706b928ac4d74c1a63ac8552a55ba7fff4445155523ea4067e1"}, - {file = "lazy_object_proxy-1.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4a79b909aa16bde8ae606f06e6bbc9d3219d2e57fb3e0076e17879072b742c65"}, - {file = "lazy_object_proxy-1.12.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:338ab2f132276203e404951205fe80c3fd59429b3a724e7b662b2eb539bb1be9"}, - {file = "lazy_object_proxy-1.12.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c40b3c9faee2e32bfce0df4ae63f4e73529766893258eca78548bac801c8f66"}, - {file = "lazy_object_proxy-1.12.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:717484c309df78cedf48396e420fa57fc8a2b1f06ea889df7248fdd156e58847"}, - {file = "lazy_object_proxy-1.12.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a6b7ea5ea1ffe15059eb44bcbcb258f97bcb40e139b88152c40d07b1a1dfc9ac"}, - {file = "lazy_object_proxy-1.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:08c465fb5cd23527512f9bd7b4c7ba6cec33e28aad36fbbe46bf7b858f9f3f7f"}, - {file = "lazy_object_proxy-1.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c9defba70ab943f1df98a656247966d7729da2fe9c2d5d85346464bf320820a3"}, - {file = "lazy_object_proxy-1.12.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6763941dbf97eea6b90f5b06eb4da9418cc088fce0e3883f5816090f9afcde4a"}, - {file = "lazy_object_proxy-1.12.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fdc70d81235fc586b9e3d1aeef7d1553259b62ecaae9db2167a5d2550dcc391a"}, - {file = "lazy_object_proxy-1.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0a83c6f7a6b2bfc11ef3ed67f8cbe99f8ff500b05655d8e7df9aab993a6abc95"}, - {file = "lazy_object_proxy-1.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:256262384ebd2a77b023ad02fbcc9326282bcfd16484d5531154b02bc304f4c5"}, - {file = "lazy_object_proxy-1.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:7601ec171c7e8584f8ff3f4e440aa2eebf93e854f04639263875b8c2971f819f"}, - {file = "lazy_object_proxy-1.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ae575ad9b674d0029fc077c5231b3bc6b433a3d1a62a8c363df96974b5534728"}, - {file = "lazy_object_proxy-1.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31020c84005d3daa4cc0fa5a310af2066efe6b0d82aeebf9ab199292652ff036"}, - {file = "lazy_object_proxy-1.12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:800f32b00a47c27446a2b767df7538e6c66a3488632c402b4fb2224f9794f3c0"}, - {file = "lazy_object_proxy-1.12.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:15400b18893f345857b9e18b9bd87bd06aba84af6ed086187add70aeaa3f93f1"}, - {file = "lazy_object_proxy-1.12.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3d3964fbd326578bcdfffd017ef101b6fb0484f34e731fe060ba9b8816498c36"}, - {file = "lazy_object_proxy-1.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:424a8ab6695400845c39f13c685050eab69fa0bbac5790b201cd27375e5e41d7"}, - {file = "lazy_object_proxy-1.12.0-pp39.pp310.pp311.graalpy311-none-any.whl", hash = "sha256:c3b2e0af1f7f77c4263759c4824316ce458fabe0fceadcd24ef8ca08b2d1e402"}, - {file = "lazy_object_proxy-1.12.0.tar.gz", hash = "sha256:1f5a462d92fd0cfb82f1fab28b51bfb209fabbe6aabf7f0d51472c0c124c0c61"}, -] - -[[package]] -name = "markupsafe" -version = "3.0.2" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.9" -files = [ - {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, - {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, -] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.8" -files = [ - {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, - {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, -] - -[[package]] -name = "numpy" -version = "2.3.2" -description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.11" -files = [ - {file = "numpy-2.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:852ae5bed3478b92f093e30f785c98e0cb62fa0a939ed057c31716e18a7a22b9"}, - {file = "numpy-2.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7a0e27186e781a69959d0230dd9909b5e26024f8da10683bd6344baea1885168"}, - {file = "numpy-2.3.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:f0a1a8476ad77a228e41619af2fa9505cf69df928e9aaa165746584ea17fed2b"}, - {file = "numpy-2.3.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cbc95b3813920145032412f7e33d12080f11dc776262df1712e1638207dde9e8"}, - {file = "numpy-2.3.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f75018be4980a7324edc5930fe39aa391d5734531b1926968605416ff58c332d"}, - {file = "numpy-2.3.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20b8200721840f5621b7bd03f8dcd78de33ec522fc40dc2641aa09537df010c3"}, - {file = "numpy-2.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f91e5c028504660d606340a084db4b216567ded1056ea2b4be4f9d10b67197f"}, - {file = "numpy-2.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fb1752a3bb9a3ad2d6b090b88a9a0ae1cd6f004ef95f75825e2f382c183b2097"}, - {file = "numpy-2.3.2-cp311-cp311-win32.whl", hash = "sha256:4ae6863868aaee2f57503c7a5052b3a2807cf7a3914475e637a0ecd366ced220"}, - {file = "numpy-2.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:240259d6564f1c65424bcd10f435145a7644a65a6811cfc3201c4a429ba79170"}, - {file = "numpy-2.3.2-cp311-cp311-win_arm64.whl", hash = "sha256:4209f874d45f921bde2cff1ffcd8a3695f545ad2ffbef6d3d3c6768162efab89"}, - {file = "numpy-2.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bc3186bea41fae9d8e90c2b4fb5f0a1f5a690682da79b92574d63f56b529080b"}, - {file = "numpy-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f4f0215edb189048a3c03bd5b19345bdfa7b45a7a6f72ae5945d2a28272727f"}, - {file = "numpy-2.3.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:8b1224a734cd509f70816455c3cffe13a4f599b1bf7130f913ba0e2c0b2006c0"}, - {file = "numpy-2.3.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3dcf02866b977a38ba3ec10215220609ab9667378a9e2150615673f3ffd6c73b"}, - {file = "numpy-2.3.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:572d5512df5470f50ada8d1972c5f1082d9a0b7aa5944db8084077570cf98370"}, - {file = "numpy-2.3.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8145dd6d10df13c559d1e4314df29695613575183fa2e2d11fac4c208c8a1f73"}, - {file = "numpy-2.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:103ea7063fa624af04a791c39f97070bf93b96d7af7eb23530cd087dc8dbe9dc"}, - {file = "numpy-2.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc927d7f289d14f5e037be917539620603294454130b6de200091e23d27dc9be"}, - {file = "numpy-2.3.2-cp312-cp312-win32.whl", hash = "sha256:d95f59afe7f808c103be692175008bab926b59309ade3e6d25009e9a171f7036"}, - {file = "numpy-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:9e196ade2400c0c737d93465327d1ae7c06c7cb8a1756121ebf54b06ca183c7f"}, - {file = "numpy-2.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:ee807923782faaf60d0d7331f5e86da7d5e3079e28b291973c545476c2b00d07"}, - {file = "numpy-2.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c8d9727f5316a256425892b043736d63e89ed15bbfe6556c5ff4d9d4448ff3b3"}, - {file = "numpy-2.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:efc81393f25f14d11c9d161e46e6ee348637c0a1e8a54bf9dedc472a3fae993b"}, - {file = "numpy-2.3.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:dd937f088a2df683cbb79dda9a772b62a3e5a8a7e76690612c2737f38c6ef1b6"}, - {file = "numpy-2.3.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:11e58218c0c46c80509186e460d79fbdc9ca1eb8d8aee39d8f2dc768eb781089"}, - {file = "numpy-2.3.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5ad4ebcb683a1f99f4f392cc522ee20a18b2bb12a2c1c42c3d48d5a1adc9d3d2"}, - {file = "numpy-2.3.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:938065908d1d869c7d75d8ec45f735a034771c6ea07088867f713d1cd3bbbe4f"}, - {file = "numpy-2.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:66459dccc65d8ec98cc7df61307b64bf9e08101f9598755d42d8ae65d9a7a6ee"}, - {file = "numpy-2.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a7af9ed2aa9ec5950daf05bb11abc4076a108bd3c7db9aa7251d5f107079b6a6"}, - {file = "numpy-2.3.2-cp313-cp313-win32.whl", hash = "sha256:906a30249315f9c8e17b085cc5f87d3f369b35fedd0051d4a84686967bdbbd0b"}, - {file = "numpy-2.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:c63d95dc9d67b676e9108fe0d2182987ccb0f11933c1e8959f42fa0da8d4fa56"}, - {file = "numpy-2.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:b05a89f2fb84d21235f93de47129dd4f11c16f64c87c33f5e284e6a3a54e43f2"}, - {file = "numpy-2.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4e6ecfeddfa83b02318f4d84acf15fbdbf9ded18e46989a15a8b6995dfbf85ab"}, - {file = "numpy-2.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:508b0eada3eded10a3b55725b40806a4b855961040180028f52580c4729916a2"}, - {file = "numpy-2.3.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:754d6755d9a7588bdc6ac47dc4ee97867271b17cee39cb87aef079574366db0a"}, - {file = "numpy-2.3.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a9f66e7d2b2d7712410d3bc5684149040ef5f19856f20277cd17ea83e5006286"}, - {file = "numpy-2.3.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de6ea4e5a65d5a90c7d286ddff2b87f3f4ad61faa3db8dabe936b34c2275b6f8"}, - {file = "numpy-2.3.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3ef07ec8cbc8fc9e369c8dcd52019510c12da4de81367d8b20bc692aa07573a"}, - {file = "numpy-2.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:27c9f90e7481275c7800dc9c24b7cc40ace3fdb970ae4d21eaff983a32f70c91"}, - {file = "numpy-2.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:07b62978075b67eee4065b166d000d457c82a1efe726cce608b9db9dd66a73a5"}, - {file = "numpy-2.3.2-cp313-cp313t-win32.whl", hash = "sha256:c771cfac34a4f2c0de8e8c97312d07d64fd8f8ed45bc9f5726a7e947270152b5"}, - {file = "numpy-2.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:72dbebb2dcc8305c431b2836bcc66af967df91be793d63a24e3d9b741374c450"}, - {file = "numpy-2.3.2-cp313-cp313t-win_arm64.whl", hash = "sha256:72c6df2267e926a6d5286b0a6d556ebe49eae261062059317837fda12ddf0c1a"}, - {file = "numpy-2.3.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:448a66d052d0cf14ce9865d159bfc403282c9bc7bb2a31b03cc18b651eca8b1a"}, - {file = "numpy-2.3.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:546aaf78e81b4081b2eba1d105c3b34064783027a06b3ab20b6eba21fb64132b"}, - {file = "numpy-2.3.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:87c930d52f45df092f7578889711a0768094debf73cfcde105e2d66954358125"}, - {file = "numpy-2.3.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:8dc082ea901a62edb8f59713c6a7e28a85daddcb67454c839de57656478f5b19"}, - {file = "numpy-2.3.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af58de8745f7fa9ca1c0c7c943616c6fe28e75d0c81f5c295810e3c83b5be92f"}, - {file = "numpy-2.3.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed5527c4cf10f16c6d0b6bee1f89958bccb0ad2522c8cadc2efd318bcd545f5"}, - {file = "numpy-2.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:095737ed986e00393ec18ec0b21b47c22889ae4b0cd2d5e88342e08b01141f58"}, - {file = "numpy-2.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5e40e80299607f597e1a8a247ff8d71d79c5b52baa11cc1cce30aa92d2da6e0"}, - {file = "numpy-2.3.2-cp314-cp314-win32.whl", hash = "sha256:7d6e390423cc1f76e1b8108c9b6889d20a7a1f59d9a60cac4a050fa734d6c1e2"}, - {file = "numpy-2.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:b9d0878b21e3918d76d2209c924ebb272340da1fb51abc00f986c258cd5e957b"}, - {file = "numpy-2.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:2738534837c6a1d0c39340a190177d7d66fdf432894f469728da901f8f6dc910"}, - {file = "numpy-2.3.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:4d002ecf7c9b53240be3bb69d80f86ddbd34078bae04d87be81c1f58466f264e"}, - {file = "numpy-2.3.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:293b2192c6bcce487dbc6326de5853787f870aeb6c43f8f9c6496db5b1781e45"}, - {file = "numpy-2.3.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:0a4f2021a6da53a0d580d6ef5db29947025ae8b35b3250141805ea9a32bbe86b"}, - {file = "numpy-2.3.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:9c144440db4bf3bb6372d2c3e49834cc0ff7bb4c24975ab33e01199e645416f2"}, - {file = "numpy-2.3.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f92d6c2a8535dc4fe4419562294ff957f83a16ebdec66df0805e473ffaad8bd0"}, - {file = "numpy-2.3.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cefc2219baa48e468e3db7e706305fcd0c095534a192a08f31e98d83a7d45fb0"}, - {file = "numpy-2.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:76c3e9501ceb50b2ff3824c3589d5d1ab4ac857b0ee3f8f49629d0de55ecf7c2"}, - {file = "numpy-2.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:122bf5ed9a0221b3419672493878ba4967121514b1d7d4656a7580cd11dddcbf"}, - {file = "numpy-2.3.2-cp314-cp314t-win32.whl", hash = "sha256:6f1ae3dcb840edccc45af496f312528c15b1f79ac318169d094e85e4bb35fdf1"}, - {file = "numpy-2.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:087ffc25890d89a43536f75c5fe8770922008758e8eeeef61733957041ed2f9b"}, - {file = "numpy-2.3.2-cp314-cp314t-win_arm64.whl", hash = "sha256:092aeb3449833ea9c0bf0089d70c29ae480685dd2377ec9cdbbb620257f84631"}, - {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:14a91ebac98813a49bc6aa1a0dfc09513dcec1d97eaf31ca21a87221a1cdcb15"}, - {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:71669b5daae692189540cffc4c439468d35a3f84f0c88b078ecd94337f6cb0ec"}, - {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:69779198d9caee6e547adb933941ed7520f896fd9656834c300bdf4dd8642712"}, - {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:2c3271cc4097beb5a60f010bcc1cc204b300bb3eafb4399376418a83a1c6373c"}, - {file = "numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8446acd11fe3dc1830568c941d44449fd5cb83068e5c70bd5a470d323d448296"}, - {file = "numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa098a5ab53fa407fded5870865c6275a5cd4101cfdef8d6fafc48286a96e981"}, - {file = "numpy-2.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6936aff90dda378c09bea075af0d9c675fe3a977a9d2402f95a87f440f59f619"}, - {file = "numpy-2.3.2.tar.gz", hash = "sha256:e0486a11ec30cdecb53f184d496d1c6a20786c81e55e41640270130056f8ee48"}, -] - -[[package]] -name = "oauth2client" -version = "4.1.3" -description = "OAuth 2.0 client library" -optional = false -python-versions = "*" -files = [ - {file = "oauth2client-4.1.3-py2.py3-none-any.whl", hash = "sha256:b8a81cc5d60e2d364f0b1b98f958dbd472887acaf1a5b05e21c28c31a2d6d3ac"}, - {file = "oauth2client-4.1.3.tar.gz", hash = "sha256:d486741e451287f69568a4d26d70d9acd73a2bbfa275746c535b4209891cccc6"}, -] - -[package.dependencies] -httplib2 = ">=0.9.1" -pyasn1 = ">=0.1.7" -pyasn1-modules = ">=0.0.5" -rsa = ">=3.1.4" -six = ">=1.6.1" - -[[package]] -name = "openapi-schema-validator" -version = "0.3.4" -description = "OpenAPI schema validation for Python" -optional = false -python-versions = ">=3.7.0,<4.0.0" -files = [ - {file = "openapi-schema-validator-0.3.4.tar.gz", hash = "sha256:7cf27585dd7970b7257cefe48e1a3a10d4e34421831bdb472d96967433bc27bd"}, - {file = "openapi_schema_validator-0.3.4-py3-none-any.whl", hash = "sha256:34fbd14b7501abe25e64d7b4624a9db02cde1a578d285b3da6f34b290cdf0b3a"}, -] - -[package.dependencies] -attrs = ">=19.2.0" -jsonschema = ">=4.0.0,<5.0.0" - -[package.extras] -isodate = ["isodate"] -rfc3339-validator = ["rfc3339-validator"] -strict-rfc3339 = ["strict-rfc3339"] - -[[package]] -name = "openapi-spec-validator" -version = "0.5.1" -description = "OpenAPI 2.0 (aka Swagger) and OpenAPI 3 spec validator" -optional = false -python-versions = ">=3.7.0,<4.0.0" -files = [ - {file = "openapi-spec-validator-0.5.1.tar.gz", hash = "sha256:8248634bad1f23cac5d5a34e193ab36e23914057ca69e91a1ede5af75552c465"}, - {file = "openapi_spec_validator-0.5.1-py3-none-any.whl", hash = "sha256:4a8aee1e45b1ac868e07ab25e18828fe9837baddd29a8e20fdb3d3c61c8eea3d"}, -] - -[package.dependencies] -importlib-resources = ">=5.8.0,<6.0.0" -jsonschema = ">=4.0.0,<5.0.0" -jsonschema-spec = ">=0.1.1,<0.2.0" -lazy-object-proxy = ">=1.7.1,<2.0.0" -openapi-schema-validator = ">=0.3.2,<0.4.0" -PyYAML = ">=5.1" - -[package.extras] -requests = ["requests"] - -[[package]] -name = "packaging" -version = "25.0" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, - {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, -] - -[[package]] -name = "pandas" -version = "2.3.2" -description = "Powerful data structures for data analysis, time series, and statistics" -optional = false -python-versions = ">=3.9" -files = [ - {file = "pandas-2.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52bc29a946304c360561974c6542d1dd628ddafa69134a7131fdfd6a5d7a1a35"}, - {file = "pandas-2.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:220cc5c35ffaa764dd5bb17cf42df283b5cb7fdf49e10a7b053a06c9cb48ee2b"}, - {file = "pandas-2.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42c05e15111221384019897df20c6fe893b2f697d03c811ee67ec9e0bb5a3424"}, - {file = "pandas-2.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc03acc273c5515ab69f898df99d9d4f12c4d70dbfc24c3acc6203751d0804cf"}, - {file = "pandas-2.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d25c20a03e8870f6339bcf67281b946bd20b86f1a544ebbebb87e66a8d642cba"}, - {file = "pandas-2.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21bb612d148bb5860b7eb2c10faacf1a810799245afd342cf297d7551513fbb6"}, - {file = "pandas-2.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:b62d586eb25cb8cb70a5746a378fc3194cb7f11ea77170d59f889f5dfe3cec7a"}, - {file = "pandas-2.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1333e9c299adcbb68ee89a9bb568fc3f20f9cbb419f1dd5225071e6cddb2a743"}, - {file = "pandas-2.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:76972bcbd7de8e91ad5f0ca884a9f2c477a2125354af624e022c49e5bd0dfff4"}, - {file = "pandas-2.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b98bdd7c456a05eef7cd21fd6b29e3ca243591fe531c62be94a2cc987efb5ac2"}, - {file = "pandas-2.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d81573b3f7db40d020983f78721e9bfc425f411e616ef019a10ebf597aedb2e"}, - {file = "pandas-2.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e190b738675a73b581736cc8ec71ae113d6c3768d0bd18bffa5b9a0927b0b6ea"}, - {file = "pandas-2.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c253828cb08f47488d60f43c5fc95114c771bbfff085da54bfc79cb4f9e3a372"}, - {file = "pandas-2.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:9467697b8083f9667b212633ad6aa4ab32436dcbaf4cd57325debb0ddef2012f"}, - {file = "pandas-2.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fbb977f802156e7a3f829e9d1d5398f6192375a3e2d1a9ee0803e35fe70a2b9"}, - {file = "pandas-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b9b52693123dd234b7c985c68b709b0b009f4521000d0525f2b95c22f15944b"}, - {file = "pandas-2.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bd281310d4f412733f319a5bc552f86d62cddc5f51d2e392c8787335c994175"}, - {file = "pandas-2.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96d31a6b4354e3b9b8a2c848af75d31da390657e3ac6f30c05c82068b9ed79b9"}, - {file = "pandas-2.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:df4df0b9d02bb873a106971bb85d448378ef14b86ba96f035f50bbd3688456b4"}, - {file = "pandas-2.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:213a5adf93d020b74327cb2c1b842884dbdd37f895f42dcc2f09d451d949f811"}, - {file = "pandas-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:8c13b81a9347eb8c7548f53fd9a4f08d4dfe996836543f805c987bafa03317ae"}, - {file = "pandas-2.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0c6ecbac99a354a051ef21c5307601093cb9e0f4b1855984a084bfec9302699e"}, - {file = "pandas-2.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c6f048aa0fd080d6a06cc7e7537c09b53be6642d330ac6f54a600c3ace857ee9"}, - {file = "pandas-2.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0064187b80a5be6f2f9c9d6bdde29372468751dfa89f4211a3c5871854cfbf7a"}, - {file = "pandas-2.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ac8c320bded4718b298281339c1a50fb00a6ba78cb2a63521c39bec95b0209b"}, - {file = "pandas-2.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:114c2fe4f4328cf98ce5716d1532f3ab79c5919f95a9cfee81d9140064a2e4d6"}, - {file = "pandas-2.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:48fa91c4dfb3b2b9bfdb5c24cd3567575f4e13f9636810462ffed8925352be5a"}, - {file = "pandas-2.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:12d039facec710f7ba305786837d0225a3444af7bbd9c15c32ca2d40d157ed8b"}, - {file = "pandas-2.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c624b615ce97864eb588779ed4046186f967374185c047070545253a52ab2d57"}, - {file = "pandas-2.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0cee69d583b9b128823d9514171cabb6861e09409af805b54459bd0c821a35c2"}, - {file = "pandas-2.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2319656ed81124982900b4c37f0e0c58c015af9a7bbc62342ba5ad07ace82ba9"}, - {file = "pandas-2.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b37205ad6f00d52f16b6d09f406434ba928c1a1966e2771006a9033c736d30d2"}, - {file = "pandas-2.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:837248b4fc3a9b83b9c6214699a13f069dc13510a6a6d7f9ba33145d2841a012"}, - {file = "pandas-2.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d2c3554bd31b731cd6490d94a28f3abb8dd770634a9e06eb6d2911b9827db370"}, - {file = "pandas-2.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:88080a0ff8a55eac9c84e3ff3c7665b3b5476c6fbc484775ca1910ce1c3e0b87"}, - {file = "pandas-2.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d4a558c7620340a0931828d8065688b3cc5b4c8eb674bcaf33d18ff4a6870b4a"}, - {file = "pandas-2.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45178cf09d1858a1509dc73ec261bf5b25a625a389b65be2e47b559905f0ab6a"}, - {file = "pandas-2.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77cefe00e1b210f9c76c697fedd8fdb8d3dd86563e9c8adc9fa72b90f5e9e4c2"}, - {file = "pandas-2.3.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:13bd629c653856f00c53dc495191baa59bcafbbf54860a46ecc50d3a88421a96"}, - {file = "pandas-2.3.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:36d627906fd44b5fd63c943264e11e96e923f8de77d6016dc2f667b9ad193438"}, - {file = "pandas-2.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:a9d7ec92d71a420185dec44909c32e9a362248c4ae2238234b76d5be37f208cc"}, - {file = "pandas-2.3.2.tar.gz", hash = "sha256:ab7b58f8f82706890924ccdfb5f48002b83d2b5a3845976a9fb705d36c34dcdb"}, -] - -[package.dependencies] -numpy = [ - {version = ">=1.23.2", markers = "python_version == \"3.11\""}, - {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, -] -python-dateutil = ">=2.8.2" -pytz = ">=2020.1" -tzdata = ">=2022.7" - -[package.extras] -all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] -aws = ["s3fs (>=2022.11.0)"] -clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] -compression = ["zstandard (>=0.19.0)"] -computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] -consortium-standard = ["dataframe-api-compat (>=0.1.7)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] -feather = ["pyarrow (>=10.0.1)"] -fss = ["fsspec (>=2022.11.0)"] -gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] -hdf5 = ["tables (>=3.8.0)"] -html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] -mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] -output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] -parquet = ["pyarrow (>=10.0.1)"] -performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] -plot = ["matplotlib (>=3.6.3)"] -postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] -pyarrow = ["pyarrow (>=10.0.1)"] -spss = ["pyreadstat (>=1.2.0)"] -sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] -test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] -xml = ["lxml (>=4.9.2)"] - -[[package]] -name = "pastel" -version = "0.2.1" -description = "Bring colors to your terminal." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "pastel-0.2.1-py2.py3-none-any.whl", hash = "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364"}, - {file = "pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d"}, -] - -[[package]] -name = "pathable" -version = "0.4.4" -description = "Object-oriented paths" -optional = false -python-versions = "<4.0.0,>=3.7.0" -files = [ - {file = "pathable-0.4.4-py3-none-any.whl", hash = "sha256:5ae9e94793b6ef5a4cbe0a7ce9dbbefc1eec38df253763fd0aeeacf2762dbbc2"}, - {file = "pathable-0.4.4.tar.gz", hash = "sha256:6905a3cd17804edfac7875b5f6c9142a218c7caef78693c2dbbbfbac186d88b2"}, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "platformdirs" -version = "4.4.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.9" -files = [ - {file = "platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85"}, - {file = "platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.14.1)"] - -[[package]] -name = "pluggy" -version = "1.6.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.9" -files = [ - {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, - {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["coverage", "pytest", "pytest-benchmark"] - -[[package]] -name = "ply" -version = "3.8" -description = "Python Lex & Yacc" -optional = false -python-versions = "*" -files = [ - {file = "ply-3.8.tar.gz", hash = "sha256:e7d1bdff026beb159c9942f7a17e102c375638d9478a7ecd4cc0c76afd8de0b8"}, -] - -[[package]] -name = "poethepoet" -version = "0.20.0" -description = "A task runner that works well with poetry." -optional = false -python-versions = ">=3.8" -files = [ - {file = "poethepoet-0.20.0-py3-none-any.whl", hash = "sha256:cb37be15f3895ccc65ddf188c2e3d8fb79e26cc9d469a6098cb1c6f994659f6f"}, - {file = "poethepoet-0.20.0.tar.gz", hash = "sha256:ca5a2a955f52dfb0a53fad3c989ef0b69ce3d5ec0f6bfa9b1da1f9e32d262e20"}, -] - -[package.dependencies] -pastel = ">=0.2.1,<0.3.0" -tomli = ">=1.2.2" - -[package.extras] -poetry-plugin = ["poetry (>=1.0,<2.0)"] - -[[package]] -name = "prance" -version = "0.22.2.22.0" -description = "Resolving Swagger/OpenAPI 2.0 and 3.0.0 Parser" -optional = false -python-versions = ">=3.8" -files = [ - {file = "prance-0.22.2.22.0-py3-none-any.whl", hash = "sha256:57deeb67b7e93ef27c1c17845bf3ccb4af288ccfb5748c7e01779c01a8507f27"}, - {file = "prance-0.22.2.22.0.tar.gz", hash = "sha256:9a83f8a4f5fe0f2d896d238d4bec6b5788b10b94155414b3d88c21c1579b85bf"}, -] - -[package.dependencies] -chardet = ">=3.0" -packaging = ">=21.3" -requests = ">=2.25" -"ruamel.yaml" = ">=0.17.10" -six = ">=1.15,<2.0" - -[package.extras] -cli = ["click (>=7.0)"] -dev = ["bumpversion (>=0.6)", "pytest (>=6.1)", "pytest-cov (>=2.11)", "sphinx (>=3.4)", "towncrier (>=19.2)", "tox (>=3.4)"] -flex = ["flex (>=6.13,<7.0)"] -icu = ["PyICU (>=2.4,<3.0)"] -osv = ["openapi-spec-validator (>=0.5.1,<0.6.0)"] -ssv = ["swagger-spec-validator (>=2.4,<3.0)"] - -[[package]] -name = "proto-plus" -version = "1.26.1" -description = "Beautiful, Pythonic protocol buffers" -optional = false -python-versions = ">=3.7" -files = [ - {file = "proto_plus-1.26.1-py3-none-any.whl", hash = "sha256:13285478c2dcf2abb829db158e1047e2f1e8d63a077d94263c2b88b043c75a66"}, - {file = "proto_plus-1.26.1.tar.gz", hash = "sha256:21a515a4c4c0088a773899e23c7bbade3d18f9c66c73edd4c7ee3816bc96a012"}, -] - -[package.dependencies] -protobuf = ">=3.19.0,<7.0.0" - -[package.extras] -testing = ["google-api-core (>=1.31.5)"] - -[[package]] -name = "protobuf" -version = "6.32.0" -description = "" -optional = false -python-versions = ">=3.9" -files = [ - {file = "protobuf-6.32.0-cp310-abi3-win32.whl", hash = "sha256:84f9e3c1ff6fb0308dbacb0950d8aa90694b0d0ee68e75719cb044b7078fe741"}, - {file = "protobuf-6.32.0-cp310-abi3-win_amd64.whl", hash = "sha256:a8bdbb2f009cfc22a36d031f22a625a38b615b5e19e558a7b756b3279723e68e"}, - {file = "protobuf-6.32.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d52691e5bee6c860fff9a1c86ad26a13afbeb4b168cd4445c922b7e2cf85aaf0"}, - {file = "protobuf-6.32.0-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:501fe6372fd1c8ea2a30b4d9be8f87955a64d6be9c88a973996cef5ef6f0abf1"}, - {file = "protobuf-6.32.0-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:75a2aab2bd1aeb1f5dc7c5f33bcb11d82ea8c055c9becbb41c26a8c43fd7092c"}, - {file = "protobuf-6.32.0-cp39-cp39-win32.whl", hash = "sha256:7db8ed09024f115ac877a1427557b838705359f047b2ff2f2b2364892d19dacb"}, - {file = "protobuf-6.32.0-cp39-cp39-win_amd64.whl", hash = "sha256:15eba1b86f193a407607112ceb9ea0ba9569aed24f93333fe9a497cf2fda37d3"}, - {file = "protobuf-6.32.0-py3-none-any.whl", hash = "sha256:ba377e5b67b908c8f3072a57b63e2c6a4cbd18aea4ed98d2584350dbf46f2783"}, - {file = "protobuf-6.32.0.tar.gz", hash = "sha256:a81439049127067fc49ec1d36e25c6ee1d1a2b7be930675f919258d03c04e7d2"}, -] - -[[package]] -name = "pyasn1" -version = "0.6.1" -description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"}, - {file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"}, -] - -[[package]] -name = "pyasn1-modules" -version = "0.4.2" -description = "A collection of ASN.1-based protocols modules" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a"}, - {file = "pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6"}, -] - -[package.dependencies] -pyasn1 = ">=0.6.1,<0.7.0" - -[[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, -] - -[[package]] -name = "pydantic" -version = "1.10.22" -description = "Data validation and settings management using python type hints" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pydantic-1.10.22-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:57889565ccc1e5b7b73343329bbe6198ebc472e3ee874af2fa1865cfe7048228"}, - {file = "pydantic-1.10.22-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:90729e22426de79bc6a3526b4c45ec4400caf0d4f10d7181ba7f12c01bb3897d"}, - {file = "pydantic-1.10.22-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8684d347f351554ec94fdcb507983d3116dc4577fb8799fed63c65869a2d10"}, - {file = "pydantic-1.10.22-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c8dad498ceff2d9ef1d2e2bc6608f5b59b8e1ba2031759b22dfb8c16608e1802"}, - {file = "pydantic-1.10.22-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fac529cc654d4575cf8de191cce354b12ba705f528a0a5c654de6d01f76cd818"}, - {file = "pydantic-1.10.22-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4148232aded8dd1dd13cf910a01b32a763c34bd79a0ab4d1ee66164fcb0b7b9d"}, - {file = "pydantic-1.10.22-cp310-cp310-win_amd64.whl", hash = "sha256:ece68105d9e436db45d8650dc375c760cc85a6793ae019c08769052902dca7db"}, - {file = "pydantic-1.10.22-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8e530a8da353f791ad89e701c35787418605d35085f4bdda51b416946070e938"}, - {file = "pydantic-1.10.22-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:654322b85642e9439d7de4c83cb4084ddd513df7ff8706005dada43b34544946"}, - {file = "pydantic-1.10.22-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8bece75bd1b9fc1c32b57a32831517943b1159ba18b4ba32c0d431d76a120ae"}, - {file = "pydantic-1.10.22-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eccb58767f13c6963dcf96d02cb8723ebb98b16692030803ac075d2439c07b0f"}, - {file = "pydantic-1.10.22-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7778e6200ff8ed5f7052c1516617423d22517ad36cc7a3aedd51428168e3e5e8"}, - {file = "pydantic-1.10.22-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bffe02767d27c39af9ca7dc7cd479c00dda6346bb62ffc89e306f665108317a2"}, - {file = "pydantic-1.10.22-cp311-cp311-win_amd64.whl", hash = "sha256:23bc19c55427091b8e589bc08f635ab90005f2dc99518f1233386f46462c550a"}, - {file = "pydantic-1.10.22-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:92d0f97828a075a71d9efc65cf75db5f149b4d79a38c89648a63d2932894d8c9"}, - {file = "pydantic-1.10.22-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6af5a2811b6b95b58b829aeac5996d465a5f0c7ed84bd871d603cf8646edf6ff"}, - {file = "pydantic-1.10.22-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6cf06d8d40993e79af0ab2102ef5da77b9ddba51248e4cb27f9f3f591fbb096e"}, - {file = "pydantic-1.10.22-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:184b7865b171a6057ad97f4a17fbac81cec29bd103e996e7add3d16b0d95f609"}, - {file = "pydantic-1.10.22-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:923ad861677ab09d89be35d36111156063a7ebb44322cdb7b49266e1adaba4bb"}, - {file = "pydantic-1.10.22-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:82d9a3da1686443fb854c8d2ab9a473251f8f4cdd11b125522efb4d7c646e7bc"}, - {file = "pydantic-1.10.22-cp312-cp312-win_amd64.whl", hash = "sha256:1612604929af4c602694a7f3338b18039d402eb5ddfbf0db44f1ebfaf07f93e7"}, - {file = "pydantic-1.10.22-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b259dc89c9abcd24bf42f31951fb46c62e904ccf4316393f317abeeecda39978"}, - {file = "pydantic-1.10.22-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9238aa0964d80c0908d2f385e981add58faead4412ca80ef0fa352094c24e46d"}, - {file = "pydantic-1.10.22-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f8029f05b04080e3f1a550575a1bca747c0ea4be48e2d551473d47fd768fc1b"}, - {file = "pydantic-1.10.22-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5c06918894f119e0431a36c9393bc7cceeb34d1feeb66670ef9b9ca48c073937"}, - {file = "pydantic-1.10.22-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e205311649622ee8fc1ec9089bd2076823797f5cd2c1e3182dc0e12aab835b35"}, - {file = "pydantic-1.10.22-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:815f0a73d5688d6dd0796a7edb9eca7071bfef961a7b33f91e618822ae7345b7"}, - {file = "pydantic-1.10.22-cp313-cp313-win_amd64.whl", hash = "sha256:9dfce71d42a5cde10e78a469e3d986f656afc245ab1b97c7106036f088dd91f8"}, - {file = "pydantic-1.10.22-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3ecaf8177b06aac5d1f442db1288e3b46d9f05f34fd17fdca3ad34105328b61a"}, - {file = "pydantic-1.10.22-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb36c2de9ea74bd7f66b5481dea8032d399affd1cbfbb9bb7ce539437f1fce62"}, - {file = "pydantic-1.10.22-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6b8d14a256be3b8fff9286d76c532f1a7573fbba5f189305b22471c6679854d"}, - {file = "pydantic-1.10.22-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:1c33269e815db4324e71577174c29c7aa30d1bba51340ce6be976f6f3053a4c6"}, - {file = "pydantic-1.10.22-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:8661b3ab2735b2a9ccca2634738534a795f4a10bae3ab28ec0a10c96baa20182"}, - {file = "pydantic-1.10.22-cp37-cp37m-win_amd64.whl", hash = "sha256:22bdd5fe70d4549995981c55b970f59de5c502d5656b2abdfcd0a25be6f3763e"}, - {file = "pydantic-1.10.22-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e3f33d1358aa4bc2795208cc29ff3118aeaad0ea36f0946788cf7cadeccc166b"}, - {file = "pydantic-1.10.22-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:813f079f9cd136cac621f3f9128a4406eb8abd2ad9fdf916a0731d91c6590017"}, - {file = "pydantic-1.10.22-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab618ab8dca6eac7f0755db25f6aba3c22c40e3463f85a1c08dc93092d917704"}, - {file = "pydantic-1.10.22-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d128e1aaa38db88caca920d5822c98fc06516a09a58b6d3d60fa5ea9099b32cc"}, - {file = "pydantic-1.10.22-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:cc97bbc25def7025e55fc9016080773167cda2aad7294e06a37dda04c7d69ece"}, - {file = "pydantic-1.10.22-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dda5d7157d543b1fa565038cae6e952549d0f90071c839b3740fb77c820fab8"}, - {file = "pydantic-1.10.22-cp38-cp38-win_amd64.whl", hash = "sha256:a093fe44fe518cb445d23119511a71f756f8503139d02fcdd1173f7b76c95ffe"}, - {file = "pydantic-1.10.22-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ec54c89b2568b258bb30d7348ac4d82bec1b58b377fb56a00441e2ac66b24587"}, - {file = "pydantic-1.10.22-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d8f1d1a1532e4f3bcab4e34e8d2197a7def4b67072acd26cfa60e92d75803a48"}, - {file = "pydantic-1.10.22-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ad83ca35508c27eae1005b6b61f369f78aae6d27ead2135ec156a2599910121"}, - {file = "pydantic-1.10.22-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53cdb44b78c420f570ff16b071ea8cd5a477635c6b0efc343c8a91e3029bbf1a"}, - {file = "pydantic-1.10.22-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:16d0a5ae9d98264186ce31acdd7686ec05fd331fab9d68ed777d5cb2d1514e5e"}, - {file = "pydantic-1.10.22-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8aee040e25843f036192b1a1af62117504a209a043aa8db12e190bb86ad7e611"}, - {file = "pydantic-1.10.22-cp39-cp39-win_amd64.whl", hash = "sha256:7f691eec68dbbfca497d3c11b92a3e5987393174cbedf03ec7a4184c35c2def6"}, - {file = "pydantic-1.10.22-py3-none-any.whl", hash = "sha256:343037d608bcbd34df937ac259708bfc83664dadf88afe8516c4f282d7d471a9"}, - {file = "pydantic-1.10.22.tar.gz", hash = "sha256:ee1006cebd43a8e7158fb7190bb8f4e2da9649719bff65d0c287282ec38dec6d"}, -] - -[package.dependencies] -email-validator = {version = ">=1.0.3", optional = true, markers = "extra == \"email\""} -typing-extensions = ">=4.2.0" - -[package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] - -[[package]] -name = "pydash" -version = "6.0.2" -description = "The kitchen sink of Python utility libraries for doing \"stuff\" in a functional way. Based on the Lo-Dash Javascript library." -optional = false -python-versions = ">=3.7" -files = [ - {file = "pydash-6.0.2-py3-none-any.whl", hash = "sha256:6d3ce5cbbc8ca3533c12782ac201c2ec756d1e1703ec3efc88f2b95d1ed2bb31"}, - {file = "pydash-6.0.2.tar.gz", hash = "sha256:35caa588e01d293713655e0870544d25128cd414c5e19477a0d63adc2b2ca03e"}, -] - -[package.extras] -dev = ["Sphinx", "black", "build", "coverage", "docformatter", "flake8", "flake8-black", "flake8-bugbear", "flake8-isort", "importlib-metadata (<5)", "invoke", "isort", "pylint", "pytest", "pytest-cov", "sphinx-rtd-theme", "tox", "twine", "wheel"] - -[[package]] -name = "pygithub" -version = "2.7.0" -description = "Use the full Github API v3" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pygithub-2.7.0-py3-none-any.whl", hash = "sha256:40ecbfe26dc55cc34ab4b0ffa1d455e6f816ef9a2bc8d6f5ad18ce572f163700"}, - {file = "pygithub-2.7.0.tar.gz", hash = "sha256:7cd6eafabb09b5369afba3586d86b1f1ad6f1326d2ff01bc47bb26615dce4cbb"}, -] - -[package.dependencies] -pyjwt = {version = ">=2.4.0", extras = ["crypto"]} -pynacl = ">=1.4.0" -requests = ">=2.14.0" -typing-extensions = ">=4.5.0" -urllib3 = ">=1.26.0" - -[[package]] -name = "pygments" -version = "2.19.2" -description = "Pygments is a syntax highlighting package written in Python." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, - {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, -] - -[package.extras] -windows-terminal = ["colorama (>=0.4.6)"] - -[[package]] -name = "pyjwt" -version = "2.10.1" -description = "JSON Web Token implementation in Python" -optional = false -python-versions = ">=3.9" -files = [ - {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"}, - {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"}, -] - -[package.dependencies] -cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"crypto\""} - -[package.extras] -crypto = ["cryptography (>=3.4.0)"] -dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"] -docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] - -[[package]] -name = "pynacl" -version = "1.5.0" -description = "Python binding to the Networking and Cryptography (NaCl) library" -optional = false -python-versions = ">=3.6" -files = [ - {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, - {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, -] - -[package.dependencies] -cffi = ">=1.4.1" - -[package.extras] -docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] -tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] - -[[package]] -name = "pyparsing" -version = "3.2.3" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -optional = false -python-versions = ">=3.9" -files = [ - {file = "pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf"}, - {file = "pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be"}, -] - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - -[[package]] -name = "pyrsistent" -version = "0.20.0" -description = "Persistent/Functional/Immutable data structures" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyrsistent-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c3aba3e01235221e5b229a6c05f585f344734bd1ad42a8ac51493d74722bbce"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1beb78af5423b879edaf23c5591ff292cf7c33979734c99aa66d5914ead880f"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21cc459636983764e692b9eba7144cdd54fdec23ccdb1e8ba392a63666c60c34"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5ac696f02b3fc01a710427585c855f65cd9c640e14f52abe52020722bb4906b"}, - {file = "pyrsistent-0.20.0-cp310-cp310-win32.whl", hash = "sha256:0724c506cd8b63c69c7f883cc233aac948c1ea946ea95996ad8b1380c25e1d3f"}, - {file = "pyrsistent-0.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:8441cf9616d642c475684d6cf2520dd24812e996ba9af15e606df5f6fd9d04a7"}, - {file = "pyrsistent-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0f3b1bcaa1f0629c978b355a7c37acd58907390149b7311b5db1b37648eb6958"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cdd7ef1ea7a491ae70d826b6cc64868de09a1d5ff9ef8d574250d0940e275b8"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cae40a9e3ce178415040a0383f00e8d68b569e97f31928a3a8ad37e3fde6df6a"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6288b3fa6622ad8a91e6eb759cfc48ff3089e7c17fb1d4c59a919769314af224"}, - {file = "pyrsistent-0.20.0-cp311-cp311-win32.whl", hash = "sha256:7d29c23bdf6e5438c755b941cef867ec2a4a172ceb9f50553b6ed70d50dfd656"}, - {file = "pyrsistent-0.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:59a89bccd615551391f3237e00006a26bcf98a4d18623a19909a2c48b8e986ee"}, - {file = "pyrsistent-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:09848306523a3aba463c4b49493a760e7a6ca52e4826aa100ee99d8d39b7ad1e"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a14798c3005ec892bbada26485c2eea3b54109cb2533713e355c806891f63c5e"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b14decb628fac50db5e02ee5a35a9c0772d20277824cfe845c8a8b717c15daa3"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e2c116cc804d9b09ce9814d17df5edf1df0c624aba3b43bc1ad90411487036d"}, - {file = "pyrsistent-0.20.0-cp312-cp312-win32.whl", hash = "sha256:e78d0c7c1e99a4a45c99143900ea0546025e41bb59ebc10182e947cf1ece9174"}, - {file = "pyrsistent-0.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:4021a7f963d88ccd15b523787d18ed5e5269ce57aa4037146a2377ff607ae87d"}, - {file = "pyrsistent-0.20.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:79ed12ba79935adaac1664fd7e0e585a22caa539dfc9b7c7c6d5ebf91fb89054"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f920385a11207dc372a028b3f1e1038bb244b3ec38d448e6d8e43c6b3ba20e98"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f5c2d012671b7391803263419e31b5c7c21e7c95c8760d7fc35602353dee714"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef3992833fbd686ee783590639f4b8343a57f1f75de8633749d984dc0eb16c86"}, - {file = "pyrsistent-0.20.0-cp38-cp38-win32.whl", hash = "sha256:881bbea27bbd32d37eb24dd320a5e745a2a5b092a17f6debc1349252fac85423"}, - {file = "pyrsistent-0.20.0-cp38-cp38-win_amd64.whl", hash = "sha256:6d270ec9dd33cdb13f4d62c95c1a5a50e6b7cdd86302b494217137f760495b9d"}, - {file = "pyrsistent-0.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ca52d1ceae015859d16aded12584c59eb3825f7b50c6cfd621d4231a6cc624ce"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b318ca24db0f0518630e8b6f3831e9cba78f099ed5c1d65ffe3e023003043ba0"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed2c3216a605dc9a6ea50c7e84c82906e3684c4e80d2908208f662a6cbf9022"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e14c95c16211d166f59c6611533d0dacce2e25de0f76e4c140fde250997b3ca"}, - {file = "pyrsistent-0.20.0-cp39-cp39-win32.whl", hash = "sha256:f058a615031eea4ef94ead6456f5ec2026c19fb5bd6bfe86e9665c4158cf802f"}, - {file = "pyrsistent-0.20.0-cp39-cp39-win_amd64.whl", hash = "sha256:58b8f6366e152092194ae68fefe18b9f0b4f89227dfd86a07770c3d86097aebf"}, - {file = "pyrsistent-0.20.0-py3-none-any.whl", hash = "sha256:c55acc4733aad6560a7f5f818466631f07efc001fd023f34a6c203f8b6df0f0b"}, - {file = "pyrsistent-0.20.0.tar.gz", hash = "sha256:4c48f78f62ab596c679086084d0dd13254ae4f3d6c72a83ffdf5ebdef8f265a4"}, -] - -[[package]] -name = "pysnooper" -version = "1.2.3" -description = "A poor man's debugger for Python." -optional = false -python-versions = "*" -files = [ - {file = "PySnooper-1.2.3-py2.py3-none-any.whl", hash = "sha256:546372f0e72da89f8d1b89e758b7c05a478d65288569a1ca2cc1620e7b1b1944"}, - {file = "pysnooper-1.2.3.tar.gz", hash = "sha256:1fa1425444a7af45108aaed860b5ca8b62b25bba25b0b037c059ba353d8f1e74"}, -] - -[package.extras] -tests = ["pytest"] - -[[package]] -name = "pytest" -version = "8.4.1" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.9" -files = [ - {file = "pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7"}, - {file = "pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c"}, -] - -[package.dependencies] -colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} -iniconfig = ">=1" -packaging = ">=20" -pluggy = ">=1.5,<2" -pygments = ">=2.7.2" - -[package.extras] -dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "pytest-mock" -version = "3.14.1" -description = "Thin-wrapper around the mock package for easier use with pytest" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pytest_mock-3.14.1-py3-none-any.whl", hash = "sha256:178aefcd11307d874b4cd3100344e7e2d888d9791a6a1d9bfe90fbc1b74fd1d0"}, - {file = "pytest_mock-3.14.1.tar.gz", hash = "sha256:159e9edac4c451ce77a5cdb9fc5d1100708d2dd4ba3c3df572f14097351af80e"}, -] - -[package.dependencies] -pytest = ">=6.2.5" - -[package.extras] -dev = ["pre-commit", "pytest-asyncio", "tox"] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, - {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "pytz" -version = "2025.2" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -files = [ - {file = "pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00"}, - {file = "pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3"}, -] - -[[package]] -name = "pyyaml" -version = "6.0.2" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, - {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, - {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, - {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, - {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, - {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, - {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, - {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, - {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, - {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, - {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, - {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, - {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, - {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, - {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, - {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, - {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, -] - -[[package]] -name = "requests" -version = "2.32.5" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.9" -files = [ - {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"}, - {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset_normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "rsa" -version = "4.9.1" -description = "Pure-Python RSA implementation" -optional = false -python-versions = "<4,>=3.6" -files = [ - {file = "rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762"}, - {file = "rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75"}, -] - -[package.dependencies] -pyasn1 = ">=0.1.3" - -[[package]] -name = "ruamel-yaml" -version = "0.18.15" -description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" -optional = false -python-versions = ">=3.8" -files = [ - {file = "ruamel.yaml-0.18.15-py3-none-any.whl", hash = "sha256:148f6488d698b7a5eded5ea793a025308b25eca97208181b6a026037f391f701"}, - {file = "ruamel.yaml-0.18.15.tar.gz", hash = "sha256:dbfca74b018c4c3fba0b9cc9ee33e53c371194a9000e694995e620490fd40700"}, -] - -[package.dependencies] -"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.14\""} - -[package.extras] -docs = ["mercurial (>5.7)", "ryd"] -jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] - -[[package]] -name = "ruamel-yaml-clib" -version = "0.2.12" -description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" -optional = false -python-versions = ">=3.9" -files = [ - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:11f891336688faf5156a36293a9c362bdc7c88f03a8a027c2c1d8e0bcde998e5"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:a606ef75a60ecf3d924613892cc603b154178ee25abb3055db5062da811fd969"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd5415dded15c3822597455bc02bcd66e81ef8b7a48cb71a33628fc9fdde39df"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a52d48f4e7bf9005e8f0a89209bf9a73f7190ddf0489eee5eb51377385f59f2a"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl", hash = "sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl", hash = "sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1492a6051dab8d912fc2adeef0e8c72216b24d57bd896ea607cb90bb0c4981d3"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:943f32bc9dedb3abff9879edc134901df92cfce2c3d5c9348f172f62eb2d771d"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c3829bb364fdb8e0332c9931ecf57d9be3519241323c5274bd82f709cebc0c"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b82a7c94a498853aa0b272fd5bc67f29008da798d4f93a2f9f289feb8426a58d"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:e7e3736715fbf53e9be2a79eb4db68e4ed857017344d697e8b9749444ae57475"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7e75b4965e1d4690e93021adfcecccbca7d61c7bddd8e22406ef2ff20d74ef"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f6f3eac23941b32afccc23081e1f50612bdbe4e982012ef4f5797986828cd01"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:fc4b630cd3fa2cf7fce38afa91d7cfe844a9f75d7f0f36393fa98815e911d987"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bc5f1e1c28e966d61d2519f2a3d451ba989f9ea0f2307de7bc45baa526de9e45"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a0e060aace4c24dcaf71023bbd7d42674e3b230f7e7b97317baf1e953e5b519"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2f1c3765db32be59d18ab3953f43ab62a761327aafc1594a2a1fbe038b8b8a7"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d85252669dc32f98ebcd5d36768f5d4faeaeaa2d655ac0473be490ecdae3c285"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e143ada795c341b56de9418c58d028989093ee611aa27ffb9b7f609c00d813ed"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2c59aa6170b990d8d2719323e628aaf36f3bfbc1c26279c0eeeb24d05d2d11c7"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win32.whl", hash = "sha256:beffaed67936fbbeffd10966a4eb53c402fafd3d6833770516bf7314bc6ffa12"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win_amd64.whl", hash = "sha256:040ae85536960525ea62868b642bdb0c2cc6021c9f9d507810c0c604e66f5a7b"}, - {file = "ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f"}, -] - -[[package]] -name = "semver" -version = "3.0.4" -description = "Python helper for Semantic Versioning (https://semver.org)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "semver-3.0.4-py3-none-any.whl", hash = "sha256:9c824d87ba7f7ab4a1890799cec8596f15c1241cb473404ea1cb0c55e4b04746"}, - {file = "semver-3.0.4.tar.gz", hash = "sha256:afc7d8c584a5ed0a11033af086e8af226a9c0b206f313e0301f8dd7b6b589602"}, -] - -[[package]] -name = "sentry-sdk" -version = "1.45.1" -description = "Python client for Sentry (https://sentry.io)" -optional = false -python-versions = "*" -files = [ - {file = "sentry_sdk-1.45.1-py2.py3-none-any.whl", hash = "sha256:608887855ccfe39032bfd03936e3a1c4f4fc99b3a4ac49ced54a4220de61c9c1"}, - {file = "sentry_sdk-1.45.1.tar.gz", hash = "sha256:a16c997c0f4e3df63c0fc5e4207ccb1ab37900433e0f72fef88315d317829a26"}, -] - -[package.dependencies] -certifi = "*" -urllib3 = {version = ">=1.26.11", markers = "python_version >= \"3.6\""} - -[package.extras] -aiohttp = ["aiohttp (>=3.5)"] -arq = ["arq (>=0.23)"] -asyncpg = ["asyncpg (>=0.23)"] -beam = ["apache-beam (>=2.12)"] -bottle = ["bottle (>=0.12.13)"] -celery = ["celery (>=3)"] -celery-redbeat = ["celery-redbeat (>=2)"] -chalice = ["chalice (>=1.16.0)"] -clickhouse-driver = ["clickhouse-driver (>=0.2.0)"] -django = ["django (>=1.8)"] -falcon = ["falcon (>=1.4)"] -fastapi = ["fastapi (>=0.79.0)"] -flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"] -grpcio = ["grpcio (>=1.21.1)"] -httpx = ["httpx (>=0.16.0)"] -huey = ["huey (>=2)"] -loguru = ["loguru (>=0.5)"] -openai = ["openai (>=1.0.0)", "tiktoken (>=0.3.0)"] -opentelemetry = ["opentelemetry-distro (>=0.35b0)"] -opentelemetry-experimental = ["opentelemetry-distro (>=0.40b0,<1.0)", "opentelemetry-instrumentation-aiohttp-client (>=0.40b0,<1.0)", "opentelemetry-instrumentation-django (>=0.40b0,<1.0)", "opentelemetry-instrumentation-fastapi (>=0.40b0,<1.0)", "opentelemetry-instrumentation-flask (>=0.40b0,<1.0)", "opentelemetry-instrumentation-requests (>=0.40b0,<1.0)", "opentelemetry-instrumentation-sqlite3 (>=0.40b0,<1.0)", "opentelemetry-instrumentation-urllib (>=0.40b0,<1.0)"] -pure-eval = ["asttokens", "executing", "pure-eval"] -pymongo = ["pymongo (>=3.1)"] -pyspark = ["pyspark (>=2.4.4)"] -quart = ["blinker (>=1.1)", "quart (>=0.16.1)"] -rq = ["rq (>=0.6)"] -sanic = ["sanic (>=0.8)"] -sqlalchemy = ["sqlalchemy (>=1.2)"] -starlette = ["starlette (>=0.19.1)"] -starlite = ["starlite (>=1.48)"] -tornado = ["tornado (>=5)"] - -[[package]] -name = "six" -version = "1.17.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, - {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, -] - -[[package]] -name = "slack-sdk" -version = "3.36.0" -description = "The Slack API Platform SDK for Python" -optional = false -python-versions = ">=3.6" -files = [ - {file = "slack_sdk-3.36.0-py2.py3-none-any.whl", hash = "sha256:6c96887d7175fc1b0b2777b73bb65f39b5b8bee9bd8acfec071d64014f9e2d10"}, - {file = "slack_sdk-3.36.0.tar.gz", hash = "sha256:8586022bdbdf9f8f8d32f394540436c53b1e7c8da9d21e1eab4560ba70cfcffa"}, -] - -[package.extras] -optional = ["SQLAlchemy (>=1.4,<3)", "aiodns (>1.0)", "aiohttp (>=3.7.3,<4)", "boto3 (<=2)", "websocket-client (>=1,<2)", "websockets (>=9.1,<16)"] - -[[package]] -name = "smmap" -version = "5.0.2" -description = "A pure Python implementation of a sliding window memory map manager" -optional = false -python-versions = ">=3.7" -files = [ - {file = "smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e"}, - {file = "smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5"}, -] - -[[package]] -name = "soupsieve" -version = "2.7" -description = "A modern CSS selector implementation for Beautiful Soup." -optional = false -python-versions = ">=3.8" -files = [ - {file = "soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4"}, - {file = "soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a"}, -] - -[[package]] -name = "tabulate" -version = "0.9.0" -description = "Pretty-print tabular data" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"}, - {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"}, -] - -[package.extras] -widechars = ["wcwidth"] - -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] - -[[package]] -name = "tomli" -version = "2.2.1" -description = "A lil' TOML parser" -optional = false -python-versions = ">=3.8" -files = [ - {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, - {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, - {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, - {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, - {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, - {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, - {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, - {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, - {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, - {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, - {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, - {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, - {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, - {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, -] - -[[package]] -name = "typed-ast" -version = "1.5.5" -description = "a fork of Python 2 and 3 ast modules with type comment support" -optional = false -python-versions = ">=3.6" -files = [ - {file = "typed_ast-1.5.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4bc1efe0ce3ffb74784e06460f01a223ac1f6ab31c6bc0376a21184bf5aabe3b"}, - {file = "typed_ast-1.5.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5f7a8c46a8b333f71abd61d7ab9255440d4a588f34a21f126bbfc95f6049e686"}, - {file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:597fc66b4162f959ee6a96b978c0435bd63791e31e4f410622d19f1686d5e769"}, - {file = "typed_ast-1.5.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d41b7a686ce653e06c2609075d397ebd5b969d821b9797d029fccd71fdec8e04"}, - {file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5fe83a9a44c4ce67c796a1b466c270c1272e176603d5e06f6afbc101a572859d"}, - {file = "typed_ast-1.5.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d5c0c112a74c0e5db2c75882a0adf3133adedcdbfd8cf7c9d6ed77365ab90a1d"}, - {file = "typed_ast-1.5.5-cp310-cp310-win_amd64.whl", hash = "sha256:e1a976ed4cc2d71bb073e1b2a250892a6e968ff02aa14c1f40eba4f365ffec02"}, - {file = "typed_ast-1.5.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c631da9710271cb67b08bd3f3813b7af7f4c69c319b75475436fcab8c3d21bee"}, - {file = "typed_ast-1.5.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b445c2abfecab89a932b20bd8261488d574591173d07827c1eda32c457358b18"}, - {file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc95ffaaab2be3b25eb938779e43f513e0e538a84dd14a5d844b8f2932593d88"}, - {file = "typed_ast-1.5.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61443214d9b4c660dcf4b5307f15c12cb30bdfe9588ce6158f4a005baeb167b2"}, - {file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6eb936d107e4d474940469e8ec5b380c9b329b5f08b78282d46baeebd3692dc9"}, - {file = "typed_ast-1.5.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e48bf27022897577d8479eaed64701ecaf0467182448bd95759883300ca818c8"}, - {file = "typed_ast-1.5.5-cp311-cp311-win_amd64.whl", hash = "sha256:83509f9324011c9a39faaef0922c6f720f9623afe3fe220b6d0b15638247206b"}, - {file = "typed_ast-1.5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:44f214394fc1af23ca6d4e9e744804d890045d1643dd7e8229951e0ef39429b5"}, - {file = "typed_ast-1.5.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:118c1ce46ce58fda78503eae14b7664163aa735b620b64b5b725453696f2a35c"}, - {file = "typed_ast-1.5.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be4919b808efa61101456e87f2d4c75b228f4e52618621c77f1ddcaae15904fa"}, - {file = "typed_ast-1.5.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:fc2b8c4e1bc5cd96c1a823a885e6b158f8451cf6f5530e1829390b4d27d0807f"}, - {file = "typed_ast-1.5.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:16f7313e0a08c7de57f2998c85e2a69a642e97cb32f87eb65fbfe88381a5e44d"}, - {file = "typed_ast-1.5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:2b946ef8c04f77230489f75b4b5a4a6f24c078be4aed241cfabe9cbf4156e7e5"}, - {file = "typed_ast-1.5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2188bc33d85951ea4ddad55d2b35598b2709d122c11c75cffd529fbc9965508e"}, - {file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0635900d16ae133cab3b26c607586131269f88266954eb04ec31535c9a12ef1e"}, - {file = "typed_ast-1.5.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57bfc3cf35a0f2fdf0a88a3044aafaec1d2f24d8ae8cd87c4f58d615fb5b6311"}, - {file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:fe58ef6a764de7b4b36edfc8592641f56e69b7163bba9f9c8089838ee596bfb2"}, - {file = "typed_ast-1.5.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d09d930c2d1d621f717bb217bf1fe2584616febb5138d9b3e8cdd26506c3f6d4"}, - {file = "typed_ast-1.5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:d40c10326893ecab8a80a53039164a224984339b2c32a6baf55ecbd5b1df6431"}, - {file = "typed_ast-1.5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fd946abf3c31fb50eee07451a6aedbfff912fcd13cf357363f5b4e834cc5e71a"}, - {file = "typed_ast-1.5.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ed4a1a42df8a3dfb6b40c3d2de109e935949f2f66b19703eafade03173f8f437"}, - {file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:045f9930a1550d9352464e5149710d56a2aed23a2ffe78946478f7b5416f1ede"}, - {file = "typed_ast-1.5.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:381eed9c95484ceef5ced626355fdc0765ab51d8553fec08661dce654a935db4"}, - {file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bfd39a41c0ef6f31684daff53befddae608f9daf6957140228a08e51f312d7e6"}, - {file = "typed_ast-1.5.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8c524eb3024edcc04e288db9541fe1f438f82d281e591c548903d5b77ad1ddd4"}, - {file = "typed_ast-1.5.5-cp38-cp38-win_amd64.whl", hash = "sha256:7f58fabdde8dcbe764cef5e1a7fcb440f2463c1bbbec1cf2a86ca7bc1f95184b"}, - {file = "typed_ast-1.5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:042eb665ff6bf020dd2243307d11ed626306b82812aba21836096d229fdc6a10"}, - {file = "typed_ast-1.5.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:622e4a006472b05cf6ef7f9f2636edc51bda670b7bbffa18d26b255269d3d814"}, - {file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1efebbbf4604ad1283e963e8915daa240cb4bf5067053cf2f0baadc4d4fb51b8"}, - {file = "typed_ast-1.5.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0aefdd66f1784c58f65b502b6cf8b121544680456d1cebbd300c2c813899274"}, - {file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:48074261a842acf825af1968cd912f6f21357316080ebaca5f19abbb11690c8a"}, - {file = "typed_ast-1.5.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:429ae404f69dc94b9361bb62291885894b7c6fb4640d561179548c849f8492ba"}, - {file = "typed_ast-1.5.5-cp39-cp39-win_amd64.whl", hash = "sha256:335f22ccb244da2b5c296e6f96b06ee9bed46526db0de38d2f0e5a6597b81155"}, - {file = "typed_ast-1.5.5.tar.gz", hash = "sha256:94282f7a354f36ef5dbce0ef3467ebf6a258e370ab33d5b40c249fa996e590dd"}, -] - -[[package]] -name = "typing-extensions" -version = "4.15.0" -description = "Backported and Experimental Type Hints for Python 3.9+" -optional = false -python-versions = ">=3.9" -files = [ - {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, - {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, -] - -[[package]] -name = "tzdata" -version = "2025.2" -description = "Provider of IANA time zone data" -optional = false -python-versions = ">=2" -files = [ - {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"}, - {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"}, -] - -[[package]] -name = "urllib3" -version = "2.5.0" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.9" -files = [ - {file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"}, - {file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[metadata] -lock-version = "2.0" -python-versions = "^3.11" -content-hash = "468237967c29b95282f2be2fe3b1f49d09a9939353db086e1f1f3184265f9e81" diff --git a/airbyte-ci/connectors/metadata_service/lib/pyproject.toml b/airbyte-ci/connectors/metadata_service/lib/pyproject.toml deleted file mode 100644 index 90768fa94571..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/pyproject.toml +++ /dev/null @@ -1,56 +0,0 @@ -[tool.poetry] -name = "metadata-service" -version = "0.28.1" -description = "" -authors = ["Airbyte "] -readme = "README.md" -packages = [{ include = "metadata_service" }] - -[tool.poetry.dependencies] -python = "^3.11" -pydantic = "^1.10.6" -click = "^8.1.3" -google = "^3.0.0" -pyyaml = "^6.0" -gcloud = "^0.18.3" -google-cloud-storage = "^2.8.0" -pydash = "^6.0.2" -semver = "^3.0.1" -gitpython = "^3.1.40" -pygithub = "^2.7.0" -pandas = "^2.3.1" -tabulate = "^0.9.0" -slack-sdk = "^3.36.0" -dpath = "^2.2.0" -sentry-sdk = "^1.28.1" -jinja2 = "^3.1.2" - - -[tool.poetry.group.dev.dependencies] -pytest = "^8" -datamodel-code-generator = "^0.17.1" -pytest-mock = "^3.10.0" -poethepoet = "^0.20.0" - -[tool.poetry.scripts] -metadata_service = "metadata_service.commands:metadata_service" - -[tool.poe.tasks] -generate-models = { shell = "npm ci --silent && ./bin/generate-metadata-models.sh" } -replicate-prod = "gsutil -m rsync -r -d gs://prod-airbyte-cloud-connector-metadata-service gs://$TARGET_BUCKET" -copy-connector-from-prod = "gsutil -m rsync -r -d gs://prod-airbyte-cloud-connector-metadata-service/metadata/$CONNECTOR/$VERSION gs://$TARGET_BUCKET/metadata/$CONNECTOR/$VERSION" -promote-connector-to-latest = "gsutil -m rsync -r -d gs://$TARGET_BUCKET/metadata/$CONNECTOR/$VERSION gs://$TARGET_BUCKET/metadata/$CONNECTOR/latest" -test = "pytest tests" - -[tool.airbyte_ci] -python_versions = ["3.11"] -optional_poetry_groups = ["dev"] -poe_tasks = ["test"] - -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" - -[tool.ruff] -target-version = "py311" -line-length = 140 diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/conftest.py b/airbyte-ci/connectors/metadata_service/lib/tests/conftest.py deleted file mode 100644 index ba779e55c2eb..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/conftest.py +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -import pytest - -pytest_plugins = [ - "tests.fixtures", -] - - -def pytest_addoption(parser): - parser.addoption("--skipslow", action="store_true", default=False, help="skip slow tests") - - -def pytest_configure(config): - config.addinivalue_line("markers", "slow: mark test as slow to run") - - -def pytest_collection_modifyitems(config, items): - if config.getoption("--skipslow"): - skip_slow = pytest.mark.skip(reason="--skipslow option has been provided and this test is marked as slow") - for item in items: - if "slow" in item.keywords: - item.add_marker(skip_slow) diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/__init__.py b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/__init__.py deleted file mode 100644 index 71d7203499ae..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/__init__.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -import os -from typing import Callable, List - -import pytest -from metadata_service.constants import DOC_FILE_NAME - - -def list_all_paths_in_fixture_directory(folder_name: str) -> List[str]: - file_path = os.path.join(os.path.dirname(__file__), folder_name) - - # If folder_name has subdirectories, os.walk will return a list of tuples, - # one for folder_name and one for each of its subdirectories. - fixture_files = [] - for root, dirs, files in os.walk(file_path): - fixture_files.extend(os.path.join(root, file_name) for file_name in files) - return fixture_files - - -@pytest.fixture(scope="session") -def valid_metadata_yaml_files() -> List[str]: - files = list_all_paths_in_fixture_directory("metadata_validate/valid") - if not files: - pytest.fail("No files found in metadata_validate/valid") - return files - - -@pytest.fixture(scope="session") -def invalid_metadata_yaml_files() -> List[str]: - files = list_all_paths_in_fixture_directory("metadata_validate/invalid") - if not files: - pytest.fail("No files found in metadata_validate/invalid") - return files - - -@pytest.fixture(scope="session") -def valid_metadata_upload_files() -> List[str]: - files = list_all_paths_in_fixture_directory("metadata_upload/valid") - if not files: - pytest.fail("No files found in metadata_upload/valid") - return files - - -@pytest.fixture(scope="session") -def invalid_metadata_upload_files() -> List[str]: - files = list_all_paths_in_fixture_directory("metadata_upload/invalid") - if not files: - pytest.fail("No files found in metadata_upload/invalid") - return files - - -@pytest.fixture(scope="session") -def get_fixture_path() -> Callable[[str], str]: - def _get_fixture_path(fixture_name: str) -> str: - return os.path.join(os.path.dirname(__file__), fixture_name) - - return _get_fixture_path diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/doc.md b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/doc.md deleted file mode 100644 index 3ee6db6d8d87..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/doc.md +++ /dev/null @@ -1 +0,0 @@ -# The test doc for metadata_validate diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_cloud_repo_does_not_exist.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_cloud_repo_does_not_exist.yaml deleted file mode 100644 index 5870cbd3c1f4..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_cloud_repo_does_not_exist.yaml +++ /dev/null @@ -1,27 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - normalizationConfig: - normalizationIntegrationType: postgres - normalizationRepository: airbyte/exists-2 - normalizationTag: 0.0.1 - registryOverrides: - cloud: - enabled: true - dockerRepository: airbyte/does-not-exist-4 - dockerImageTag: 0.0.1 - oss: - enabled: true - dockerRepository: airbyte/exists-3 - dockerImageTag: 0.0.1 - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_main_repo_does_not_exist.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_main_repo_does_not_exist.yaml deleted file mode 100644 index ef1221d99316..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_main_repo_does_not_exist.yaml +++ /dev/null @@ -1,23 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/does-not-exist-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - normalizationConfig: - normalizationIntegrationType: postgres - normalizationRepository: airbyte/exists-2 - normalizationTag: 0.0.1 - registryOverrides: - cloud: - enabled: true - oss: - enabled: true - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_normalization_repo_does_not_exist.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_normalization_repo_does_not_exist.yaml deleted file mode 100644 index 6c1d49293fa1..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_normalization_repo_does_not_exist.yaml +++ /dev/null @@ -1,27 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - normalizationConfig: - normalizationIntegrationType: postgres - normalizationRepository: airbyte/does-not-exist-2 - normalizationTag: 0.0.1 - registryOverrides: - cloud: - enabled: true - dockerRepository: airbyte/exists-3 - dockerImageTag: 0.0.1 - oss: - enabled: true - dockerRepository: airbyte/exists-4 - dockerImageTag: 0.0.1 - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_oss_repo_does_not_exist.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_oss_repo_does_not_exist.yaml deleted file mode 100644 index 61c907851da8..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/repo_nonexistent/metadata_oss_repo_does_not_exist.yaml +++ /dev/null @@ -1,27 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - normalizationConfig: - normalizationIntegrationType: postgres - normalizationRepository: airbyte/exists-2 - normalizationTag: 0.0.1 - registryOverrides: - cloud: - enabled: true - dockerRepository: airbyte/exists-3 - dockerImageTag: 0.0.1 - oss: - enabled: true - dockerRepository: airbyte/does-not-exist-4 - dockerImageTag: 0.0.1 - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_breaking_change_image_tag_does_not_exist.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_breaking_change_image_tag_does_not_exist.yaml deleted file mode 100644 index f646f8eb2995..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_breaking_change_image_tag_does_not_exist.yaml +++ /dev/null @@ -1,25 +0,0 @@ -data: - connectorSubtype: api - connectorType: source - definitionId: bb6afd81-87d5-47e3-97c4-e2c2901b1cf8 - dockerImageTag: 0.0.1 - dockerRepository: airbyte/image-exists1 - githubIssueLabel: source-onesignal - icon: onesignal.svg - license: MIT - name: OneSignal - registryOverrides: - cloud: - enabled: true - oss: - enabled: true - releaseStage: alpha - releases: - breakingChanges: - 0.0.0: # tag does not exist - upgradeDeadline: 2023-08-22 - message: "This version made a change." - documentationUrl: https://docs.airbyte.com/integrations/sources/onesignal - tags: - - language:python -metadataSpecVersion: "1.0" diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_cloud_image_tag_does_not_exist.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_cloud_image_tag_does_not_exist.yaml deleted file mode 100644 index a41bb35cf8ea..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_cloud_image_tag_does_not_exist.yaml +++ /dev/null @@ -1,27 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - normalizationConfig: - normalizationIntegrationType: postgres - normalizationRepository: airbyte/exists-2 - normalizationTag: 0.0.1 - registryOverrides: - cloud: - enabled: true - dockerRepository: airbyte/exists-3 - dockerImageTag: 99.99.99 # tag does not exist - oss: - enabled: true - dockerRepository: airbyte/exists-4 - dockerImageTag: 0.0.1 - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_main_image_tag_does_not_exist.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_main_image_tag_does_not_exist.yaml deleted file mode 100644 index 1007338c64fb..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_main_image_tag_does_not_exist.yaml +++ /dev/null @@ -1,23 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 99.99.99 # tag does not exist - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - normalizationConfig: - normalizationIntegrationType: postgres - normalizationRepository: airbyte/exists-2 - normalizationTag: 0.0.1 - registryOverrides: - cloud: - enabled: true - oss: - enabled: true - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_normalization_image_tag_does_not_exist.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_normalization_image_tag_does_not_exist.yaml deleted file mode 100644 index 7c578cf41a19..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_normalization_image_tag_does_not_exist.yaml +++ /dev/null @@ -1,27 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - normalizationConfig: - normalizationIntegrationType: postgres - normalizationRepository: airbyte/exists-2 - normalizationTag: 99.99.99 # tag does not exist - registryOverrides: - cloud: - enabled: true - dockerRepository: airbyte/exists-3 - dockerImageTag: 0.0.1 - oss: - enabled: true - dockerRepository: airbyte/exists-4 - dockerImageTag: 0.0.1 - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_oss_repo_does_not_exist.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_oss_repo_does_not_exist.yaml deleted file mode 100644 index 29e02dd7d39c..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/tag_nonexistent/metadata_oss_repo_does_not_exist.yaml +++ /dev/null @@ -1,27 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - normalizationConfig: - normalizationIntegrationType: postgres - normalizationRepository: airbyte/exists-2 - normalizationTag: 0.0.1 - registryOverrides: - cloud: - enabled: true - dockerRepository: airbyte/exists-3 - dockerImageTag: 0.0.1 - oss: - enabled: true - dockerRepository: airbyte/exists-4 - dockerImageTag: 99.99.99 # tag does not exist - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/valid_overrides_but_image_nonexistent/metadata_main_image_tag_does_not_exist_but_is_overrode.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/valid_overrides_but_image_nonexistent/metadata_main_image_tag_does_not_exist_but_is_overrode.yaml deleted file mode 100644 index 53c80d360c04..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/valid_overrides_but_image_nonexistent/metadata_main_image_tag_does_not_exist_but_is_overrode.yaml +++ /dev/null @@ -1,27 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 99.99.99 # tag does not exist - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - normalizationConfig: - normalizationIntegrationType: postgres - normalizationRepository: airbyte/exists-2 - normalizationTag: 0.0.1 - registryOverrides: - cloud: - enabled: true - dockerRepository: airbyte/exists-3 - dockerImageTag: 0.0.1 - oss: - enabled: true - dockerRepository: airbyte/exists-4 - dockerImageTag: 0.0.1 - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/valid_overrides_but_image_nonexistent/metadata_main_repo_does_not_exist_but_is_overrode.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/valid_overrides_but_image_nonexistent/metadata_main_repo_does_not_exist_but_is_overrode.yaml deleted file mode 100644 index 95ad1661b3b3..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/invalid/referenced_image_not_in_dockerhub/valid_overrides_but_image_nonexistent/metadata_main_repo_does_not_exist_but_is_overrode.yaml +++ /dev/null @@ -1,27 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/does-not-exist-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - normalizationConfig: - normalizationIntegrationType: postgres - normalizationRepository: airbyte/exists-2 - normalizationTag: 0.0.1 - registryOverrides: - cloud: - enabled: true - dockerRepository: airbyte/exists-3 - dockerImageTag: 0.0.1 - oss: - enabled: true - dockerRepository: airbyte/exists-4 - dockerImageTag: 0.0.1 - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_all_images_exist.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_all_images_exist.yaml deleted file mode 100644 index 7d1f5ef5da72..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_all_images_exist.yaml +++ /dev/null @@ -1,32 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - normalizationConfig: - normalizationIntegrationType: postgres - normalizationRepository: airbyte/exists-2 - normalizationTag: 0.0.1 - registryOverrides: - cloud: - enabled: true - dockerRepository: airbyte/exists-3 - dockerImageTag: 0.0.1 - oss: - enabled: true - dockerRepository: airbyte/exists-4 - dockerImageTag: 0.0.1 - releases: - breakingChanges: - 2.0.0: - upgradeDeadline: 2023-08-22 - message: "This version made a change." - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_all_images_exist_no_overrides.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_all_images_exist_no_overrides.yaml deleted file mode 100644 index d2067be338f0..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_all_images_exist_no_overrides.yaml +++ /dev/null @@ -1,14 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_all_images_exist_no_overrides_with_normalization.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_all_images_exist_no_overrides_with_normalization.yaml deleted file mode 100644 index 74be91d596ef..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_all_images_exist_no_overrides_with_normalization.yaml +++ /dev/null @@ -1,18 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - normalizationConfig: - normalizationIntegrationType: postgres - normalizationRepository: airbyte/exists-2 - normalizationTag: 0.0.1 - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_base_image_exists.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_base_image_exists.yaml deleted file mode 100644 index 0189b45a2d51..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_base_image_exists.yaml +++ /dev/null @@ -1,29 +0,0 @@ -data: - ab_internal: - ql: 400 - sl: 200 - allowedHosts: - hosts: - - zopim.com - connectorBuildOptions: - baseImage: docker.io/airbyte/base-repo-exists:1.1.0@sha256:bd98f6505c6764b1b5f99d3aedc23dfc9e9af631a62533f60eb32b1d3dbab20c - connectorSubtype: api - connectorType: source - definitionId: 40d24d0f-b8f9-4fe0-9e6c-b06c0f3f45e4 - dockerImageTag: 0.2.1 - dockerRepository: airbyte/source-exists-1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - githubIssueLabel: source-alloy-db - icon: alloy-db.svg - license: MIT - name: AlloyDB for PostgreSQL - registryOverrides: - cloud: - enabled: true - oss: - enabled: true - releaseStage: generally_available - supportLevel: certified - tags: - - language:python -metadataSpecVersion: "1.0" diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_release_candidate.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_release_candidate.yaml deleted file mode 100644 index a95f7ae31912..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_upload/valid/referenced_image_in_dockerhub/metadata_release_candidate.yaml +++ /dev/null @@ -1,24 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 2.1.0-rc.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - rolloutConfiguration: - enableProgressiveRollout: true - initialPercentage: 5 - maxPercentage: 50 - advanceDelayMinutes: 60 - breakingChanges: - 2.0.0: - upgradeDeadline: 2023-08-22 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_extra_data.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_extra_data.yaml deleted file mode 100644 index d412853bb354..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_extra_data.yaml +++ /dev/null @@ -1,15 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - someUnknownField: someUnknownValue - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_major_bump_no_breaking_changes.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_major_bump_no_breaking_changes.yaml deleted file mode 100644 index 9d26a7480bed..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_major_bump_no_breaking_changes.yaml +++ /dev/null @@ -1,14 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: Low-code - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 1.0.0 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_progressive_rollout_no_rc_suffix.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_progressive_rollout_no_rc_suffix.yaml deleted file mode 100644 index 2e68d16a48ab..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_progressive_rollout_no_rc_suffix.yaml +++ /dev/null @@ -1,22 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 2.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - rolloutConfiguration: - enableProgressiveRollout: true - breakingChanges: - 2.0.0: - upgradeDeadline: 2023-08-22 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_release_candidate_for_major_version.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_release_candidate_for_major_version.yaml deleted file mode 100644 index 7da17b70363b..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_release_candidate_for_major_version.yaml +++ /dev/null @@ -1,22 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 3.0.0-rc.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - rolloutConfiguration: - enableProgressiveRollout: true - breakingChanges: - 2.0.0: - upgradeDeadline: 2023-08-22 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_release_candidate_no_progressive_rollout.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_release_candidate_no_progressive_rollout.yaml deleted file mode 100644 index 9917b66596fc..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/metadata_release_candidate_no_progressive_rollout.yaml +++ /dev/null @@ -1,20 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 2.0.1-rc.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - breakingChanges: - 2.0.0: - upgradeDeadline: 2023-08-22 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/nonsense.json b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/nonsense.json deleted file mode 100644 index ad869b38385f..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/nonsense.json +++ /dev/null @@ -1 +0,0 @@ -asdsad diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/nonsense.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/nonsense.yaml deleted file mode 100644 index ad869b38385f..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/nonsense.yaml +++ /dev/null @@ -1 +0,0 @@ -asdsad diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_base_image_digest_does_not_exists.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_base_image_digest_does_not_exists.yaml deleted file mode 100644 index 57f5418bc40d..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_base_image_digest_does_not_exists.yaml +++ /dev/null @@ -1,29 +0,0 @@ -data: - ab_internal: - ql: 400 - sl: 200 - allowedHosts: - hosts: - - zopim.com - connectorBuildOptions: - baseImage: docker.io/airbyte/base-repo-exists:1.1.0@sha256:MISSINGSHA - connectorSubtype: api - connectorType: source - definitionId: 40d24d0f-b8f9-4fe0-9e6c-b06c0f3f45e4 - dockerImageTag: 0.2.1 - dockerRepository: airbyte/source-exists-1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - githubIssueLabel: source-alloy-db - icon: alloy-db.svg - license: MIT - name: AlloyDB for PostgreSQL - registryOverrides: - cloud: - enabled: true - oss: - enabled: true - releaseStage: generally_available - supportLevel: certified - tags: - - language:python -metadataSpecVersion: "1.0" diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_base_image_name_does_not_exists.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_base_image_name_does_not_exists.yaml deleted file mode 100644 index fdefc79a9b1b..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_base_image_name_does_not_exists.yaml +++ /dev/null @@ -1,29 +0,0 @@ -data: - ab_internal: - ql: 400 - sl: 200 - allowedHosts: - hosts: - - zopim.com - connectorBuildOptions: - baseImage: docker.io/airbyte/foobar-connector-base:1.1.0@sha256:bd98f6505c6764b1b5f99d3aedc23dfc9e9af631a62533f60eb32b1d3dbab20c - connectorSubtype: api - connectorType: source - definitionId: 40d24d0f-b8f9-4fe0-9e6c-b06c0f3f45e4 - dockerImageTag: 0.2.1 - dockerRepository: airbyte/source-exists-1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - githubIssueLabel: source-alloy-db - icon: alloy-db.svg - license: MIT - name: AlloyDB for PostgreSQL - registryOverrides: - cloud: - enabled: true - oss: - enabled: true - releaseStage: generally_available - supportLevel: certified - tags: - - language:python -metadataSpecVersion: "1.0" diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_base_image_tag_does_not_exists.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_base_image_tag_does_not_exists.yaml deleted file mode 100644 index ba84e959a984..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_base_image_tag_does_not_exists.yaml +++ /dev/null @@ -1,29 +0,0 @@ -data: - ab_internal: - ql: 400 - sl: 200 - allowedHosts: - hosts: - - zopim.com - connectorBuildOptions: - baseImage: docker.io/airbyte/base-repo-exists:99.99.99@sha256:bd98f6505c6764b1b5f99d3aedc23dfc9e9af631a62533f60eb32b1d3dbab20c - connectorSubtype: api - connectorType: source - definitionId: 40d24d0f-b8f9-4fe0-9e6c-b06c0f3f45e4 - dockerImageTag: 0.2.1 - dockerRepository: airbyte/source-exists-1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - githubIssueLabel: source-alloy-db - icon: alloy-db.svg - license: MIT - name: AlloyDB for PostgreSQL - registryOverrides: - cloud: - enabled: true - oss: - enabled: true - releaseStage: generally_available - supportLevel: certified - tags: - - language:python -metadataSpecVersion: "1.0" diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_build_base_image_wrong_type.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_build_base_image_wrong_type.yaml deleted file mode 100644 index b58cb21f304b..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_build_base_image_wrong_type.yaml +++ /dev/null @@ -1,29 +0,0 @@ -data: - allowedHosts: - hosts: - - "*.googleapis.com" - connectorBuildOptions: - unexpectedField: additionalProperties are not allowed ('unexpectedField' was unexpected) - connectorSubtype: file - connectorType: source - definitionId: 71607ba1-c0ac-4799-8049-7f4b90dd50f7 - dockerImageTag: 0.3.7 - dockerRepository: airbyte/source-google-sheets - githubIssueLabel: source-google-sheets - icon: google-sheets.svg - license: Elv2 - name: Google Sheets - registryOverrides: - cloud: - enabled: true - oss: - enabled: true - releaseStage: generally_available - documentationUrl: https://docs.airbyte.com/integrations/sources/google-sheets - tags: - - language:python - ab_internal: - sl: 300 - ql: 400 - supportLevel: certified -metadataSpecVersion: "1.0" diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_invalid_base_image_no_sha.yml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_invalid_base_image_no_sha.yml deleted file mode 100644 index 91de8734a4bf..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/connector_build_options_invalid/metadata_invalid_base_image_no_sha.yml +++ /dev/null @@ -1,29 +0,0 @@ -data: - allowedHosts: - hosts: - - "*.googleapis.com" - connectorBuildOptions: - baseImage: docker.io/airbyte/base-repo-exists:1.1.0 - connectorSubtype: file - connectorType: source - definitionId: 71607ba1-c0ac-4799-8049-7f4b90dd50f7 - dockerImageTag: 0.3.7 - dockerRepository: airbyte/source-google-sheets - githubIssueLabel: source-google-sheets - icon: google-sheets.svg - license: Elv2 - name: Google Sheets - registries: - cloud: - enabled: true - oss: - enabled: true - releaseStage: generally_available - documentationUrl: https://docs.airbyte.com/integrations/sources/google-sheets - tags: - - language:python - ab_internal: - sl: 300 - ql: 400 - supportLevel: certified -metadataSpecVersion: "1.0" diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_invalid_internal_fields.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_invalid_internal_fields.yaml deleted file mode 100644 index db4b261bd977..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_invalid_internal_fields.yaml +++ /dev/null @@ -1,17 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - ab_internal: - sl: 299 - ql: 699 - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_invalid_remote_registries.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_invalid_remote_registries.yaml deleted file mode 100644 index 1e1d095e6333..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_invalid_remote_registries.yaml +++ /dev/null @@ -1,16 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - remoteRegistries: - maven: enabled - license: MIT - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_invalid_support_refreshes.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_invalid_support_refreshes.yaml deleted file mode 100644 index 4e66c6d592ff..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_invalid_support_refreshes.yaml +++ /dev/null @@ -1,15 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - supportsRefreshes: 123 - license: MIT - tags: - - language:java \ No newline at end of file diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_unknown_support_level.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_unknown_support_level.yaml deleted file mode 100644 index 9fe7b5ededaf..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_unknown_support_level.yaml +++ /dev/null @@ -1,15 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - supportLevel: dne - license: MIT - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_wrong_language_remote_registries.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_wrong_language_remote_registries.yaml deleted file mode 100644 index c77bfde70bd4..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/metadata_wrong_language_remote_registries.yaml +++ /dev/null @@ -1,18 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - remoteRegistries: - pypi: - enabled: true - packageName: airbyte-source-alloydb-strict-encrypt - license: MIT - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/overrides_invalid/metadata_registry_no_id_override.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/overrides_invalid/metadata_registry_no_id_override.yaml deleted file mode 100644 index f6a46e1870e2..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/overrides_invalid/metadata_registry_no_id_override.yaml +++ /dev/null @@ -1,22 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - allowedHosts: - hosts: - - "${host}" - - "${tunnel_method.tunnel_host}" - registryOverrides: - oss: - enabled: true - definitionId: woohoo - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/overrides_invalid/metadata_registry_no_type_override.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/overrides_invalid/metadata_registry_no_type_override.yaml deleted file mode 100644 index 6904ca3426e5..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/overrides_invalid/metadata_registry_no_type_override.yaml +++ /dev/null @@ -1,22 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - allowedHosts: - hosts: - - "${host}" - - "${tunnel_method.tunnel_host}" - registryOverrides: - oss: - enabled: true - connectorType: destination - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/overrides_invalid/metadata_registry_unknown_override.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/overrides_invalid/metadata_registry_unknown_override.yaml deleted file mode 100644 index a6e7f18d73c5..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/overrides_invalid/metadata_registry_unknown_override.yaml +++ /dev/null @@ -1,22 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - allowedHosts: - hosts: - - "${host}" - - "${tunnel_method.tunnel_host}" - registryOverrides: - oss: - enabled: true - what: is this? - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/impact_scopes_invalid/metadata_breaking_changes_empty_impacted_stream.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/impact_scopes_invalid/metadata_breaking_changes_empty_impacted_stream.yaml deleted file mode 100644 index 3351eb5ddee5..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/impact_scopes_invalid/metadata_breaking_changes_empty_impacted_stream.yaml +++ /dev/null @@ -1,23 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - breakingChanges: - 2.0.0: - upgradeDeadline: 2023-08-22 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - scopedImpact: - - scopeType: stream - impactedScopes: [] - - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/impact_scopes_invalid/metadata_breaking_changes_impact_scopes_unknown_scope_type.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/impact_scopes_invalid/metadata_breaking_changes_impact_scopes_unknown_scope_type.yaml deleted file mode 100644 index 9b4176acfd5c..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/impact_scopes_invalid/metadata_breaking_changes_impact_scopes_unknown_scope_type.yaml +++ /dev/null @@ -1,23 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - breakingChanges: - 2.0.0: - upgradeDeadline: 2023-08-22 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - scopedImpact: - - type: foo - impactedScopes: ["bar"] - - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_breaking_change_versions_under_releases.yml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_breaking_change_versions_under_releases.yml deleted file mode 100644 index 27e2c17d1abf..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_breaking_change_versions_under_releases.yml +++ /dev/null @@ -1,18 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/alloydb - connectorSubtype: database - releaseStage: generally_available - license: MIT - releasestests/fixtures/metadata_validate/invalid/metadata_breaking_change_versions_under_releases.yml: - 2.1.3: - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - upgradeDeadline: 2023-08-22 - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_breaking_changes_not_under_releases.yml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_breaking_changes_not_under_releases.yml deleted file mode 100644 index e2b9918cccf0..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_breaking_changes_not_under_releases.yml +++ /dev/null @@ -1,18 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/alloydb - connectorSubtype: database - releaseStage: generally_available - license: MIT - breakingChanges: - 2.1.3: - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - upgradeDeadline: 2023-08-22 - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_additional_property.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_additional_property.yaml deleted file mode 100644 index 03f3579470fa..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_additional_property.yaml +++ /dev/null @@ -1,20 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - breakingChanges: - addition: "hi" - 2.1.3: - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - upgradeDeadline: 2023-08-22 - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_invalid_deadline.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_invalid_deadline.yaml deleted file mode 100644 index a4b3891435b1..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_invalid_deadline.yaml +++ /dev/null @@ -1,19 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - breakingChanges: - 1.2.3: - upgradeDeadline: 2023-08-22-11 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_no_deadline.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_no_deadline.yaml deleted file mode 100644 index 458fdccce291..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_no_deadline.yaml +++ /dev/null @@ -1,18 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - breakingChanges: - 1.2.3: - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_no_message.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_no_message.yaml deleted file mode 100644 index 73572c41a5d6..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_no_message.yaml +++ /dev/null @@ -1,18 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - breakingChanges: - 2.1.3: - upgradeDeadline: 2023-08-22 - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_version.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_version.yaml deleted file mode 100644 index 76c15e44d7c2..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_invalid_breaking_change_version.yaml +++ /dev/null @@ -1,19 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - breakingChanges: - v2.1.3: - upgradeDeadline: 2023-08-22 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_major_version_no_breaking_change_entry_for_version.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_major_version_no_breaking_change_entry_for_version.yaml deleted file mode 100644 index a7d4e65e96cd..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_major_version_no_breaking_change_entry_for_version.yaml +++ /dev/null @@ -1,25 +0,0 @@ -metadataSpecVersion: "1.0" -data: - connectorSubtype: api - connectorType: source - definitionId: bb6afd81-87d5-47e3-97c4-e2c2901b1cf8 - dockerImageTag: 2.0.0 - dockerRepository: airbyte/source-onesignal - githubIssueLabel: source-onesignal - icon: onesignal.svg - license: MIT - name: OneSignal - registryOverrides: - cloud: - enabled: true - oss: - enabled: true - releaseStage: alpha - releases: - breakingChanges: - 1.0.0: - upgradeDeadline: 2023-08-22 - message: "This version made a change." - documentationUrl: https://docs.airbyte.com/integrations/sources/onesignal - tags: - - language:python diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_major_version_no_releases.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_major_version_no_releases.yaml deleted file mode 100644 index 65ab50b555fe..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/optional_top_level_property_invalid/releases_invalid/metadata_major_version_no_releases.yaml +++ /dev/null @@ -1,20 +0,0 @@ -metadataSpecVersion: "1.0" -data: - connectorSubtype: api - connectorType: source - definitionId: bb6afd81-87d5-47e3-97c4-e2c2901b1cf8 - dockerImageTag: 2.0.0 - dockerRepository: airbyte/source-onesignal - githubIssueLabel: source-onesignal - icon: onesignal.svg - license: MIT - name: OneSignal - registryOverrides: - cloud: - enabled: true - oss: - enabled: true - releaseStage: alpha - documentationUrl: https://docs.airbyte.com/integrations/sources/onesignal - tags: - - language:python diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_invalid/tags_invalid/metadata_empty_tags.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_invalid/tags_invalid/metadata_empty_tags.yaml deleted file mode 100644 index 90f558ad64e3..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_invalid/tags_invalid/metadata_empty_tags.yaml +++ /dev/null @@ -1,13 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/source-alloydb-strict-encrypt - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 2.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - tags: [] diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_invalid/tags_invalid/metadata_invalid_tag_format.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_invalid/tags_invalid/metadata_invalid_tag_format.yaml deleted file mode 100644 index f5416208fa3e..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_invalid/tags_invalid/metadata_invalid_tag_format.yaml +++ /dev/null @@ -1,14 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/source-alloydb-strict-encrypt - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 2.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - tags: - - notkv diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_invalid/tags_invalid/metadata_no_lang_tag.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_invalid/tags_invalid/metadata_no_lang_tag.yaml deleted file mode 100644 index a065f3e742c7..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_invalid/tags_invalid/metadata_no_lang_tag.yaml +++ /dev/null @@ -1,14 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/source-alloydb-strict-encrypt - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 2.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - tags: - - keyword:test diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_connector_type.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_connector_type.yaml deleted file mode 100644 index 3222f6bdd974..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_connector_type.yaml +++ /dev/null @@ -1,13 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_definition_id.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_definition_id.yaml deleted file mode 100644 index b1eb9f113e32..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_definition_id.yaml +++ /dev/null @@ -1,17 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - connectorType: source - githubIssueLabel: source-alloydb-strict-encrypt - dockerRepository: airbyte/image-exists-1 - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - allowedHosts: - hosts: - - "${host}" - - "${tunnel_method.tunnel_host}" - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_docker_image_tag.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_docker_image_tag.yaml deleted file mode 100644 index 28b6807ee54a..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_docker_image_tag.yaml +++ /dev/null @@ -1,17 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - githubIssueLabel: source-alloydb-strict-encrypt - dockerRepository: airbyte/image-exists-1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - allowedHosts: - hosts: - - "${host}" - - "${tunnel_method.tunnel_host}" - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_docker_repo.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_docker_repo.yaml deleted file mode 100644 index 5bc5ca48cdd8..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_docker_repo.yaml +++ /dev/null @@ -1,17 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - allowedHosts: - hosts: - - "${host}" - - "${tunnel_method.tunnel_host}" - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_tags.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_tags.yaml deleted file mode 100644 index 4b704e001f8c..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_tags.yaml +++ /dev/null @@ -1,12 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/source-alloydb-strict-encrypt - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 2.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_version.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_version.yaml deleted file mode 100644 index 8142a7133c5c..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/invalid/required_top_level_property_missing/metadata_missing_version.yaml +++ /dev/null @@ -1,17 +0,0 @@ -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - allowedHosts: - hosts: - - "${host}" - - "${tunnel_method.tunnel_host}" - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/metadata_declarative_manifest_major_bump_no_breaking_change.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/metadata_declarative_manifest_major_bump_no_breaking_change.yaml deleted file mode 100644 index cde8a6cedd85..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/metadata_declarative_manifest_major_bump_no_breaking_change.yaml +++ /dev/null @@ -1,14 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: Low-code - definitionId: 64a2f99c-542f-4af8-9a6f-355f1217b436 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 1.0.0 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/metadata_simple.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/metadata_simple.yaml deleted file mode 100644 index c8bd4e079df0..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/metadata_simple.yaml +++ /dev/null @@ -1,14 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_build_base_image.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_build_base_image.yaml deleted file mode 100644 index 1eb69afb6214..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_build_base_image.yaml +++ /dev/null @@ -1,29 +0,0 @@ -data: - allowedHosts: - hosts: - - "*.googleapis.com" - connectorBuildOptions: - baseImage: docker.io/airbyte/base-repo-exists:1.1.0@sha256:bd98f6505c6764b1b5f99d3aedc23dfc9e9af631a62533f60eb32b1d3dbab20c - connectorSubtype: file - connectorType: source - definitionId: 71607ba1-c0ac-4799-8049-7f4b90dd50f7 - dockerImageTag: 0.3.7 - dockerRepository: airbyte/source-google-sheets - githubIssueLabel: source-google-sheets - icon: google-sheets.svg - license: Elv2 - name: Google Sheets - registryOverrides: - cloud: - enabled: true - oss: - enabled: true - releaseStage: generally_available - documentationUrl: https://docs.airbyte.com/integrations/sources/google-sheets - tags: - - language:python - ab_internal: - sl: 300 - ql: 400 - supportLevel: certified -metadataSpecVersion: "1.0" diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_internal_fields.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_internal_fields.yaml deleted file mode 100644 index 2d788f819f7b..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_internal_fields.yaml +++ /dev/null @@ -1,17 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - ab_internal: - sl: 200 - ql: 600 - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_registry_allowed_hosts.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_registry_allowed_hosts.yaml deleted file mode 100644 index fe9279d3c8de..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_registry_allowed_hosts.yaml +++ /dev/null @@ -1,18 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - allowedHosts: - hosts: - - "${host}" - - "${tunnel_method.tunnel_host}" - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_registry_required_resources.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_registry_required_resources.yaml deleted file mode 100644 index a49ca2841bed..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_registry_required_resources.yaml +++ /dev/null @@ -1,20 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - resourceRequirements: - jobSpecific: - - jobType: sync - resourceRequirements: - memory_request: 1Gi - memory_limit: 1Gi - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_remote_registries.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_remote_registries.yaml deleted file mode 100644 index b942106789e2..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_remote_registries.yaml +++ /dev/null @@ -1,18 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - remoteRegistries: - pypi: - enabled: true - packageName: airbyte-source-alloydb-strict-encrypt - license: MIT - tags: - - language:python diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_support_level.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_support_level.yaml deleted file mode 100644 index 0fe30754f681..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_support_level.yaml +++ /dev/null @@ -1,15 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - supportLevel: community - license: MIT - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_support_level_archived.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_support_level_archived.yaml deleted file mode 100644 index 99486312e56c..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_support_level_archived.yaml +++ /dev/null @@ -1,15 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - supportLevel: archived - license: MIT - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_support_refreshes.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_support_refreshes.yaml deleted file mode 100644 index 13174a76e3ee..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/metadata_support_refreshes.yaml +++ /dev/null @@ -1,15 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - supportsRefreshes: true - license: MIT - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_overrides/metadata_registry_complex_override.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_overrides/metadata_registry_complex_override.yaml deleted file mode 100644 index 4d0d8d7dc110..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_overrides/metadata_registry_complex_override.yaml +++ /dev/null @@ -1,31 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - allowedHosts: - hosts: - - "${host}" - - "${tunnel_method.tunnel_host}" - registryOverrides: - oss: - enabled: true - cloud: - enabled: true - name: "NEWNAME" - dockerRepository: airbyte/source-alloydb - resourceRequirements: - jobSpecific: - - jobType: sync - resourceRequirements: - memory_request: 1Gi - memory_limit: 1Gi - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_overrides/metadata_registry_enabled.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_overrides/metadata_registry_enabled.yaml deleted file mode 100644 index 81f17b894eef..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_overrides/metadata_registry_enabled.yaml +++ /dev/null @@ -1,21 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - allowedHosts: - hosts: - - "${host}" - - "${tunnel_method.tunnel_host}" - registryOverrides: - oss: - enabled: true - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_change_prerelease.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_change_prerelease.yaml deleted file mode 100644 index bc356503f1ce..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_change_prerelease.yaml +++ /dev/null @@ -1,19 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 2.0.0-preview.cf3628c - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - breakingChanges: - 2.0.0: - upgradeDeadline: 2023-08-22 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes.yaml deleted file mode 100644 index 230bbf43d09c..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes.yaml +++ /dev/null @@ -1,19 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - breakingChanges: - 2.0.0: - upgradeDeadline: 2023-08-22 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes_with_impact_scopes.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes_with_impact_scopes.yaml deleted file mode 100644 index 215d8f18c578..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes_with_impact_scopes.yaml +++ /dev/null @@ -1,22 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - breakingChanges: - 2.0.0: - upgradeDeadline: 2023-08-22 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - scopedImpact: - - scopeType: stream - impactedScopes: ["affected_stream"] - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes_with_migration_doc_url.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes_with_migration_doc_url.yaml deleted file mode 100644 index 4745efd02a9f..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes_with_migration_doc_url.yaml +++ /dev/null @@ -1,21 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - migrationDocumentationUrl: https://docs.airbyte.com/integrations/sources/existingsource-migrations - breakingChanges: - 2.0.0: - migrationDocumentationUrl: https://docs.airbyte.com/integrations/sources/existingsource-migrations#2.0.0 - upgradeDeadline: 2023-08-22 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes_with_multipel_impact_scopes.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes_with_multipel_impact_scopes.yaml deleted file mode 100644 index 0c19362d12e1..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_breaking_changes_with_multipel_impact_scopes.yaml +++ /dev/null @@ -1,24 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 0.0.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - breakingChanges: - 2.0.0: - upgradeDeadline: 2023-08-22 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - scopedImpact: - - scopeType: stream - impactedScopes: ["affected_stream", "one_more"] - - scopeType: stream - impactedScopes: ["another_affected_stream"] - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_major_version_with_breaking_change_for_version.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_major_version_with_breaking_change_for_version.yaml deleted file mode 100644 index 515df162bebb..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_major_version_with_breaking_change_for_version.yaml +++ /dev/null @@ -1,19 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 2.0.0 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - breakingChanges: - 2.0.0: - upgradeDeadline: 2023-08-22 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_release_candidate_disable_progressive_rollout.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_release_candidate_disable_progressive_rollout.yaml deleted file mode 100644 index 684d168789aa..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_release_candidate_disable_progressive_rollout.yaml +++ /dev/null @@ -1,22 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 2.0.1-rc.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - rolloutConfiguration: - enableProgressiveRollout: false - breakingChanges: - 2.0.0: - upgradeDeadline: 2023-08-22 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_release_candidate_enable_progressive_rollout.yaml b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_release_candidate_enable_progressive_rollout.yaml deleted file mode 100644 index 36debbafbe6e..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/metadata_validate/valid/with_optional_field/with_releases/metadata_release_candidate_enable_progressive_rollout.yaml +++ /dev/null @@ -1,22 +0,0 @@ -metadataSpecVersion: 1.0 -data: - name: AlloyDB for PostgreSQL - definitionId: 1fa90628-2b9e-11ed-a261-0242ac120002 - connectorType: source - dockerRepository: airbyte/image-exists-1 - githubIssueLabel: source-alloydb-strict-encrypt - dockerImageTag: 2.0.1-rc.1 - documentationUrl: https://docs.airbyte.com/integrations/sources/existingsource - connectorSubtype: database - releaseStage: generally_available - license: MIT - releases: - rolloutConfiguration: - enableProgressiveRollout: true - breakingChanges: - 2.0.0: - upgradeDeadline: 2023-08-22 - message: "This version changes the connector’s authentication method from `ApiKey` to `oAuth`, per the [API guide](https://amazon-sqs.com/api/someguide)." - - tags: - - language:java diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/stale_metadata_report_fixtures.py b/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/stale_metadata_report_fixtures.py deleted file mode 100644 index b2420fc91819..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/fixtures/stale_metadata_report_fixtures.py +++ /dev/null @@ -1,128 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -from unittest.mock import Mock - -import pytest -import yaml - - -@pytest.fixture -def mock_github_files(): - """Create mock GitHub file objects for testing.""" - mock_file_1 = Mock() - mock_file_1.type = "file" - mock_file_1.name = "metadata.yaml" - mock_file_1.path = "airbyte-integrations/connectors/source-test-1/metadata.yaml" - mock_file_1.download_url = "https://github.com/connector-1/metadata.yaml" - - mock_file_2 = Mock() - mock_file_2.type = "file" - mock_file_2.name = "metadata.yaml" - mock_file_2.path = "airbyte-integrations/connectors/source-test-2/metadata.yaml" - mock_file_2.download_url = "https://github.com/connector-2/metadata.yaml" - - mock_file_3 = Mock() - mock_file_3.type = "file" - mock_file_3.name = "metadata.yaml" - mock_file_3.path = "airbyte-integrations/connectors/source-test-3/metadata.yaml" - mock_file_3.download_url = "https://github.com/connector-3/metadata.yaml" - - return [mock_file_1, mock_file_2, mock_file_3] - - -@pytest.fixture -def mock_yaml_responses(): - """Create mock YAML responses for different test scenarios.""" - return { - "https://github.com/connector-1/metadata.yaml": """ -metadataSpecVersion: "1.0" -data: - name: "Test Source 1" - definitionId: "12345678-1234-1234-1234-123456789abc" - connectorType: "source" - dockerRepository: "airbyte/source-test-1" - dockerImageTag: "1.0.0" - license: "MIT" - documentationUrl: "https://docs.airbyte.com/integrations/sources/test-1" - githubIssueLabel: "source-test-1" - connectorSubtype: "api" - releaseStage: "alpha" - supportLevel: "certified" -""", - "https://github.com/connector-2/metadata.yaml": """ -metadataSpecVersion: "1.0" -data: - name: "Test Source 2" - definitionId: "12345678-1234-1234-1234-123456789abd" - connectorType: "source" - dockerRepository: "airbyte/source-test-2" - dockerImageTag: "1.0.0-rc" - license: "MIT" - documentationUrl: "https://docs.airbyte.com/integrations/sources/test-2" - githubIssueLabel: "source-test-2" - connectorSubtype: "api" - releaseStage: "alpha" - supportLevel: "community" -""", - "https://github.com/connector-3/metadata.yaml": """ -metadataSpecVersion: "1.0" -data: - name: "Test Source 3" - definitionId: "12345678-1234-1234-1234-123456789abe" - connectorType: "source" - dockerRepository: "airbyte/source-test-3" - dockerImageTag: "2.0.0" - license: "MIT" - documentationUrl: "https://docs.airbyte.com/integrations/sources/test-3" - githubIssueLabel: "source-test-3" - connectorSubtype: "api" - releaseStage: "alpha" - supportLevel: "archived" -""", - } - - -@pytest.fixture -def mock_gcs_blobs(): - """Create mock GCS blob objects for testing.""" - - def _create_mock_blob(repo, tag): - blob = Mock() - metadata = { - "metadataSpecVersion": "1.0", - "data": { - "name": f"Test {repo.split('/')[-1].replace('-', ' ').title()}", - "definitionId": "12345678-1234-1234-1234-123456789000", - "connectorType": "source" if "source" in repo else "destination", - "dockerRepository": repo, - "dockerImageTag": tag, - "license": "MIT", - "documentationUrl": f"https://docs.airbyte.com/integrations/{repo}", - "githubIssueLabel": repo.split("/")[-1], - "connectorSubtype": "api", - "releaseStage": "alpha", - "supportLevel": "certified", - }, - } - blob.download_as_bytes.return_value = yaml.dump(metadata).encode("utf-8") - return blob - - mock_blob_1 = _create_mock_blob("airbyte/source-gcs-1", "1.2.0") - mock_blob_2 = _create_mock_blob("airbyte/source-gcs-2", "2.1.0") - mock_blob_3 = _create_mock_blob("airbyte/destination-gcs-1", "3.0.0") - - return [mock_blob_1, mock_blob_2, mock_blob_3] - - -@pytest.fixture -def large_dataset_github_mappings(): - """Create large GitHub version mappings for performance testing.""" - return {f"airbyte/connector-{i:04d}": f"{i % 10}.{i % 5}.{i % 3}" for i in range(500)} - - -@pytest.fixture -def large_dataset_gcs_mappings(): - """Create large GCS version mappings for performance testing.""" - return {f"airbyte/connector-{i:04d}": f"{(i - 1) % 10}.{i % 5}.{i % 3}" for i in range(500)} diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/helpers/test_slack.py b/airbyte-ci/connectors/metadata_service/lib/tests/helpers/test_slack.py deleted file mode 100644 index c19f2b6d7d7e..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/helpers/test_slack.py +++ /dev/null @@ -1,86 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -from unittest.mock import Mock, patch - -import pytest - -from metadata_service.helpers.slack import send_slack_message - - -@pytest.mark.parametrize( - "slack_token,should_send,description", - [ - ("xoxb-test-token", True, "token present - should send"), - (None, False, "no token - should not send"), - ], -) -def test_send_slack_message_environment_conditions(monkeypatch, slack_token, should_send, description): - """Test send_slack_message behavior with different SLACK_TOKEN configurations.""" - if slack_token: - monkeypatch.setenv("SLACK_TOKEN", slack_token) - else: - monkeypatch.delenv("SLACK_TOKEN", raising=False) - - with patch("metadata_service.helpers.slack.WebClient") as mock_webclient_class: - mock_webclient = Mock() - mock_webclient.chat_postMessage = Mock() - mock_webclient_class.return_value = mock_webclient - - channel = "#test-channel" - message = "Test message" - - success, error_msg = send_slack_message(channel, message) - - if should_send: - mock_webclient_class.assert_called_once_with(token=slack_token) - expected_message = message + "\n" - mock_webclient.chat_postMessage.assert_called_once_with(channel=channel, text=expected_message) - assert success is True - assert error_msg is None - else: - mock_webclient_class.assert_not_called() - mock_webclient.chat_postMessage.assert_not_called() - assert success is True # No error when token not present - expected behavior - assert error_msg is None - - -@pytest.mark.parametrize( - "exception_location,exception_type,description", - [ - ("webclient_constructor", Exception, "WebClient constructor raises generic exception"), - ("webclient_constructor", ConnectionError, "WebClient constructor raises connection error"), - ("chat_post_message", Exception, "chat_postMessage raises generic exception"), - ("chat_post_message", ConnectionError, "chat_postMessage raises connection error"), - ], -) -def test_send_slack_message_error_handling(monkeypatch, exception_location, exception_type, description): - """Test send_slack_message gracefully handles various error scenarios without crashing.""" - monkeypatch.setenv("SLACK_TOKEN", "xoxb-test-token") - - channel = "#test-channel" - message = "Test message" - - if exception_location == "webclient_constructor": - with patch("metadata_service.helpers.slack.WebClient", side_effect=exception_type("Mocked error")): - success, error_msg = send_slack_message(channel, message) - - assert success is False - assert "Mocked error" in error_msg - assert isinstance(error_msg, str) - - elif exception_location == "chat_post_message": - with patch("metadata_service.helpers.slack.WebClient") as mock_webclient_class: - mock_webclient = Mock() - mock_webclient.chat_postMessage = Mock(side_effect=exception_type("Mocked error")) - mock_webclient_class.return_value = mock_webclient - - success, error_msg = send_slack_message(channel, message) - - mock_webclient_class.assert_called_once_with(token="xoxb-test-token") - mock_webclient.chat_postMessage.assert_called_once() - - assert success is False - assert "Mocked error" in error_msg - assert isinstance(error_msg, str) diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/test_commands.py b/airbyte-ci/connectors/metadata_service/lib/tests/test_commands.py deleted file mode 100644 index ce4adbf2eceb..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/test_commands.py +++ /dev/null @@ -1,267 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import pathlib - -import pytest -from click.testing import CliRunner -from pydantic import BaseModel, ValidationError, error_wrappers -from test_gcs_upload import stub_is_image_on_docker_hub - -from metadata_service import commands -from metadata_service.gcs_upload import MetadataUploadInfo, UploadedFile -from metadata_service.validators.metadata_validator import ValidatorOptions, validate_docker_image_tag_is_not_decremented - -NOT_TEST_VALIDATORS = [ - # Not testing validate_docker_image_tag_is_not_decremented as its tested independently in test_validators - validate_docker_image_tag_is_not_decremented -] - -PATCHED_VALIDATORS = [v for v in commands.PRE_UPLOAD_VALIDATORS if v not in NOT_TEST_VALIDATORS] - - -# TEST VALIDATE COMMAND -def test_valid_metadata_yaml_files(mocker, valid_metadata_yaml_files, tmp_path): - runner = CliRunner() - - # Mock dockerhub for base image checks - mocker.patch("metadata_service.validators.metadata_validator.is_image_on_docker_hub", side_effect=stub_is_image_on_docker_hub) - mocker.patch("metadata_service.commands.PRE_UPLOAD_VALIDATORS", PATCHED_VALIDATORS) - assert len(valid_metadata_yaml_files) > 0, "No files found" - - for file_path in valid_metadata_yaml_files: - result = runner.invoke(commands.validate, [file_path, str(tmp_path)]) - assert result.exit_code == 0, f"Validation failed for {file_path} with error: {result.output}" - - -def test_invalid_metadata_yaml_files(mocker, invalid_metadata_yaml_files, tmp_path): - runner = CliRunner() - - mocker.patch("metadata_service.validators.metadata_validator.is_image_on_docker_hub", side_effect=stub_is_image_on_docker_hub) - mocker.patch("metadata_service.commands.PRE_UPLOAD_VALIDATORS", PATCHED_VALIDATORS) - - assert len(invalid_metadata_yaml_files) > 0, "No files found" - - for file_path in invalid_metadata_yaml_files: - result = runner.invoke(commands.validate, [file_path, str(tmp_path)]) - assert result.exit_code != 0, f"Validation succeeded (when it should have failed) for {file_path}" - - -def test_metadata_file_not_found_fails(tmp_path): - runner = CliRunner() - result = runner.invoke(commands.validate, ["non_existent_file.yaml", str(tmp_path)]) - assert result.exit_code != 0, "Validation succeeded (when it should have failed) for non_existent_file.yaml" - - -def test_docs_path_not_found_fails(valid_metadata_yaml_files): - runner = CliRunner() - - assert len(valid_metadata_yaml_files) > 0, "No files found" - - result = runner.invoke(commands.validate, [valid_metadata_yaml_files[0], "non_existent_docs_path"]) - assert result.exit_code != 0, "Validation succeeded (when it should have failed) for non_existent_docs_path" - - -def mock_metadata_upload_info( - latest_uploaded: bool, - version_uploaded: bool, - icon_uploaded: bool, - versioned_doc_uploaded: bool, - versioned_doc_inapp_uploaded: bool, - latest_doc_uploaded: bool, - latest_doc_inapp_uploaded: bool, - metadata_file_path: str, -) -> MetadataUploadInfo: - return MetadataUploadInfo( - metadata_uploaded=(latest_uploaded or version_uploaded), - metadata_file_path=metadata_file_path, - uploaded_files=[ - UploadedFile( - id="versioned_metadata", - uploaded=version_uploaded, - blob_id="version_blob_id" if version_uploaded else None, - ), - UploadedFile( - id="latest_metadata", - uploaded=latest_uploaded, - blob_id="latest_blob_id" if latest_uploaded else None, - ), - UploadedFile( - id="latest_icon", - uploaded=icon_uploaded, - blob_id="icon_blob_id" if icon_uploaded else None, - ), - UploadedFile( - id="versioned_doc", - uploaded=versioned_doc_uploaded, - blob_id="versioned_doc_blob_id" if versioned_doc_uploaded else None, - ), - UploadedFile( - id="latest_doc", - uploaded=latest_doc_uploaded, - blob_id="latest_doc_blob_id" if latest_doc_uploaded else None, - ), - UploadedFile( - id="versioned_doc_inapp", - uploaded=versioned_doc_inapp_uploaded, - blob_id="versioned_doc_inapp_blob_id" if versioned_doc_inapp_uploaded else None, - ), - UploadedFile( - id="latest_doc_inapp", - uploaded=latest_doc_inapp_uploaded, - blob_id="latest_doc_inapp_blob_id" if latest_doc_inapp_uploaded else None, - ), - ], - ) - - -# TEST UPLOAD COMMAND -@pytest.mark.parametrize( - "latest_uploaded, version_uploaded, icon_uploaded, versioned_doc_uploaded, versioned_doc_inapp_uploaded, latest_doc_uploaded, latest_doc_inapp_uploaded", - [ - (False, False, False, False, False, False, False), - (True, False, False, False, False, False, False), - (False, True, False, False, False, False, False), - (False, False, True, False, False, False, False), - (True, True, False, False, False, False, False), - (True, False, True, False, False, False, False), - (False, True, True, False, False, False, False), - (True, True, True, False, False, False, False), - (True, True, True, True, True, True, True), - ], -) -def test_upload( - mocker, - tmp_path, - valid_metadata_yaml_files, - latest_uploaded, - version_uploaded, - icon_uploaded, - versioned_doc_uploaded, - versioned_doc_inapp_uploaded, - latest_doc_uploaded, - latest_doc_inapp_uploaded, -): - runner = CliRunner() - mocker.patch.object(commands.click, "secho") - mocker.patch.object(commands, "upload_metadata_to_gcs") - metadata_file_path = valid_metadata_yaml_files[0] - upload_info = mock_metadata_upload_info( - latest_uploaded, - version_uploaded, - icon_uploaded, - versioned_doc_uploaded, - versioned_doc_inapp_uploaded, - latest_doc_uploaded, - latest_doc_inapp_uploaded, - metadata_file_path, - ) - commands.upload_metadata_to_gcs.return_value = upload_info - result = runner.invoke( - commands.upload, [metadata_file_path, str(tmp_path), "my-bucket"] - ) # Using valid_metadata_yaml_files[0] as SA because it exists... - - if latest_uploaded: - commands.click.secho.assert_has_calls( - [mocker.call(f"File:latest_metadata for {metadata_file_path} was uploaded to latest_blob_id.", fg="green")] - ) - assert result.exit_code == 0 - else: - commands.click.secho.assert_has_calls( - [mocker.call(f"File:latest_metadata for {metadata_file_path} was not uploaded.", fg="yellow")] - ) - - if version_uploaded: - commands.click.secho.assert_has_calls( - [mocker.call(f"File:versioned_metadata for {metadata_file_path} was uploaded to version_blob_id.", fg="green")] - ) - assert result.exit_code == 0 - else: - commands.click.secho.assert_has_calls( - [mocker.call(f"File:versioned_metadata for {metadata_file_path} was not uploaded.", fg="yellow")] - ) - - if icon_uploaded: - commands.click.secho.assert_has_calls( - [mocker.call(f"File:latest_icon for {metadata_file_path} was uploaded to icon_blob_id.", fg="green")] - ) - else: - commands.click.secho.assert_has_calls([mocker.call(f"File:latest_icon for {metadata_file_path} was not uploaded.", fg="yellow")]) - - if versioned_doc_uploaded: - commands.click.secho.assert_has_calls( - [mocker.call(f"File:versioned_doc for {metadata_file_path} was uploaded to versioned_doc_blob_id.", fg="green")] - ) - else: - commands.click.secho.assert_has_calls([mocker.call(f"File:versioned_doc for {metadata_file_path} was not uploaded.", fg="yellow")]) - - if versioned_doc_inapp_uploaded: - commands.click.secho.assert_has_calls( - [mocker.call(f"File:versioned_doc_inapp for {metadata_file_path} was uploaded to versioned_doc_inapp_blob_id.", fg="green")] - ) - else: - commands.click.secho.assert_has_calls( - [mocker.call(f"File:versioned_doc_inapp for {metadata_file_path} was not uploaded.", fg="yellow")] - ) - - if latest_doc_uploaded: - commands.click.secho.assert_has_calls( - [mocker.call(f"File:latest_doc for {metadata_file_path} was uploaded to latest_doc_blob_id.", fg="green")] - ) - else: - commands.click.secho.assert_has_calls([mocker.call(f"File:latest_doc for {metadata_file_path} was not uploaded.", fg="yellow")]) - - if latest_doc_inapp_uploaded: - commands.click.secho.assert_has_calls( - [mocker.call(f"File:latest_doc_inapp for {metadata_file_path} was uploaded to latest_doc_inapp_blob_id.", fg="green")] - ) - else: - commands.click.secho.assert_has_calls( - [mocker.call(f"File:latest_doc_inapp for {metadata_file_path} was not uploaded.", fg="yellow")] - ) - - if not (latest_uploaded or version_uploaded): - # We exit with 5 status code to share with the CI pipeline that the upload was skipped. - assert result.exit_code == 5 - - -def test_upload_prerelease(mocker, valid_metadata_yaml_files, tmp_path): - runner = CliRunner() - mocker.patch.object(commands.click, "secho") - mocker.patch.object(commands, "upload_metadata_to_gcs") - - prerelease_tag = "0.3.0-preview.6d33165" - bucket = "my-bucket" - metadata_file_path = valid_metadata_yaml_files[0] - validator_opts = ValidatorOptions(docs_path=str(tmp_path), prerelease_tag=prerelease_tag) - - upload_info = mock_metadata_upload_info(False, True, False, True, False, False, False, metadata_file_path) - commands.upload_metadata_to_gcs.return_value = upload_info - result = runner.invoke( - commands.upload, [metadata_file_path, str(tmp_path), bucket, "--prerelease", prerelease_tag] - ) # Using valid_metadata_yaml_files[0] as SA because it exists... - - commands.upload_metadata_to_gcs.assert_has_calls([mocker.call(bucket, pathlib.Path(metadata_file_path), validator_opts)]) - assert result.exit_code == 0 - - -@pytest.mark.parametrize( - "error, handled", - [ - (ValidationError([error_wrappers.ErrorWrapper(Exception("Boom!"), "foo")], BaseModel), True), - (FileNotFoundError("Boom!"), True), - (ValueError("Boom!"), False), - ], -) -def test_upload_with_errors(mocker, valid_metadata_yaml_files, tmp_path, error, handled): - runner = CliRunner() - mocker.patch.object(commands.click, "secho") - mocker.patch.object(commands, "upload_metadata_to_gcs") - commands.upload_metadata_to_gcs.side_effect = error - result = runner.invoke( - commands.upload, [valid_metadata_yaml_files[0], str(tmp_path), "my-bucket"] - ) # Using valid_metadata_yaml_files[0] as SA because it exists... - assert result.exit_code == 1 - if handled: - commands.click.secho.assert_called_with(f"The metadata file could not be uploaded: {str(error)}", fg="red") diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/test_docker_hub.py b/airbyte-ci/connectors/metadata_service/lib/tests/test_docker_hub.py deleted file mode 100644 index 9f49d3ac29e9..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/test_docker_hub.py +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - - -import warnings - -import pytest - -from metadata_service import docker_hub - - -@pytest.fixture -def image_name(): - return "airbyte/source-faker" - - -@pytest.mark.slow -def test_get_docker_hub_tags_and_digests(image_name): - warnings.warn(f"This test can be flaky as its results depends on the current state of {image_name} dockerhub image.", UserWarning) - tags_and_digests = docker_hub.get_docker_hub_tags_and_digests(image_name) - assert isinstance(tags_and_digests, dict) - assert "latest" in tags_and_digests, "The latest tag is not in the returned dict" - assert "0.1.0" in tags_and_digests, f"The first {image_name} version is not in the returned dict" - assert len(tags_and_digests) > 10, f"Pagination is likely not working as we expect more than 10 version of {image_name} to be released" - - -@pytest.mark.slow -def test_get_latest_version_on_dockerhub(image_name): - warnings.warn(f"This test can be flaky as its results depends on the current state of {image_name} dockerhub image.", UserWarning) - assert ( - docker_hub.get_latest_version_on_dockerhub(image_name) is not None - ), f"No latest version found for {image_name}. We expect one to exist." diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/test_gcs_upload.py b/airbyte-ci/connectors/metadata_service/lib/tests/test_gcs_upload.py deleted file mode 100644 index b2424ad8ec66..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/test_gcs_upload.py +++ /dev/null @@ -1,868 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from datetime import datetime -from pathlib import Path -from typing import Optional - -import pytest -import yaml -from pydash.objects import get - -from metadata_service import gcs_upload -from metadata_service.constants import ( - COMPONENTS_PY_FILE_NAME, - DOC_FILE_NAME, - LATEST_GCS_FOLDER_NAME, - MANIFEST_FILE_NAME, - METADATA_FILE_NAME, - RELEASE_CANDIDATE_GCS_FOLDER_NAME, -) -from metadata_service.models.generated.ConnectorMetadataDefinitionV0 import ConnectorMetadataDefinitionV0 -from metadata_service.models.generated.GitInfo import GitInfo -from metadata_service.models.transform import to_json_sanitized_dict -from metadata_service.validators.metadata_validator import ValidatorOptions - -MOCK_VERSIONS_THAT_DO_NOT_EXIST = ["99.99.99", "0.0.0"] -MISSING_SHA = "MISSINGSHA" -DOCS_PATH = "/docs" -MOCK_DOC_URL_PATH = "integrations/sources/existingsource.md" -VALID_DOC_FILE_PATH = Path(DOCS_PATH) / MOCK_DOC_URL_PATH - -# Helpers - - -def stub_is_image_on_docker_hub(image_name: str, version: str, digest: Optional[str] = None, retries: int = 0, wait_sec: int = 30) -> bool: - image_repo_exists = "exists" in image_name - version_exists = version not in MOCK_VERSIONS_THAT_DO_NOT_EXIST - sha_is_valid = (digest != MISSING_SHA) if digest is not None else True - image_exists = all([image_repo_exists, version_exists, sha_is_valid]) - return image_exists - - -# Fixtures - - -@pytest.fixture(autouse=True) -def mock_local_doc_path_exists(monkeypatch): - original_exists = Path.exists - mocked_doc_path = VALID_DOC_FILE_PATH - - def fake_exists(self): - if self == Path(VALID_DOC_FILE_PATH) or self == mocked_doc_path: - return True - return original_exists(self) - - monkeypatch.setattr(Path, "exists", fake_exists) - - -@pytest.fixture -def temp_manifest_content(): - """Sample manifest.yaml content for testing.""" - return """ -# Temporary manifest file for testing -description: Test manifest -author: Test Author -version: 1.0.0 -""".strip() - - -@pytest.fixture -def temp_components_content(): - """Sample components.py content for testing.""" - return """ -# Temporary components.py file for testing -def test_component(): - pass -""".strip() - - -@pytest.fixture -def temp_metadata_directory( - tmp_path, valid_metadata_upload_files, manifest_exists, components_py_exists, temp_manifest_content, temp_components_content -): - """Create a temporary directory structure with optional manifest and components files based on test parameters.""" - # Copy base metadata.yaml from existing fixture to temp directory - base_metadata_file = valid_metadata_upload_files[0] - temp_metadata_path = tmp_path / "metadata.yaml" - - # Copy the content from the base metadata file - with open(base_metadata_file, "r") as f: - temp_metadata_path.write_text(f.read()) - - # Conditionally create manifest.yaml based on test parameter - if manifest_exists: - manifest_path = tmp_path / MANIFEST_FILE_NAME - manifest_path.write_text(temp_manifest_content) - - # Conditionally create components.py based on test parameter - if components_py_exists: - components_path = tmp_path / COMPONENTS_PY_FILE_NAME - components_path.write_text(temp_components_content) - - return temp_metadata_path - - -@pytest.fixture -def mock_git_operations(mocker): - """Mock Git operations to avoid repository issues with temporary files.""" - - # Create a proper GitInfo Pydantic model instance - mock_git_info = GitInfo( - commit_sha="abc123def456", - commit_timestamp=datetime(2024, 1, 1, 0, 0, 0), - commit_author="Test Author", - commit_author_email="test@example.com", - ) - mocker.patch("metadata_service.gcs_upload._get_git_info_for_file", return_value=mock_git_info) - return mock_git_info - - -# Custom Assertions - - -def assert_upload_invalid_metadata_fails_correctly(metadata_file_path: Path, expected_error_match: str, validate_success_error_match: str): - """ - When attempting to upload invalid metadata, we expect it to fail in a predictable way, depending on what is exactly invalid - about the file. This helper aims to make it easier for a developer who is adding new test cases to figure out that their test - is failing because the test data that should be invalid is passing all of the validation steps. - - Because we don't exit the uploading process if validation fails, this case often looks like a weird error message that is hard to - grok. - """ - try: - with pytest.raises(ValueError, match=expected_error_match) as exc_info: - gcs_upload.upload_metadata_to_gcs( - "my_bucket", - metadata_file_path, - validator_opts=ValidatorOptions(docs_path=VALID_DOC_FILE_PATH), - ) - print(f"Upload raised {exc_info.value}") - except AssertionError as e: - if validate_success_error_match in str(e): - raise AssertionError(f"Validation succeeded (when it should have failed) for {metadata_file_path}") from e - else: - raise e - - -def assert_blob_upload(upload_info, upload_info_file_key, blob_mock, should_upload, file_path, failure_message): - """ - Assert that the blob upload occurred (or not) as expected. - """ - file_uploaded = next((file.uploaded for file in upload_info.uploaded_files if file.id == upload_info_file_key), False) - if should_upload: - blob_mock.upload_from_filename.assert_called_with(file_path) - assert file_uploaded, failure_message - else: - blob_mock.upload_from_filename.assert_not_called() - assert not file_uploaded, failure_message - - -# Mocks - - -def setup_upload_mocks( - mocker, - version_blob_md5_hash, - latest_blob_md5_hash, - local_file_md5_hash, - doc_local_file_md5_hash, - doc_version_blob_md5_hash, - doc_latest_blob_md5_hash, - metadata_file_path, - doc_file_path, -): - # Mock dockerhub - mocker.patch("metadata_service.validators.metadata_validator.is_image_on_docker_hub", side_effect=stub_is_image_on_docker_hub) - - # Mock GCS - now using the abstracted get_gcs_storage_client - mock_storage_client = mocker.Mock() - - latest_blob_exists = latest_blob_md5_hash is not None - version_blob_exists = version_blob_md5_hash is not None - doc_version_blob_exists = doc_version_blob_md5_hash is not None - doc_latest_blob_exists = doc_latest_blob_md5_hash is not None - release_candidate_blob_exists = False - - mock_version_blob = mocker.Mock(exists=mocker.Mock(return_value=version_blob_exists), md5_hash=version_blob_md5_hash) - mock_latest_blob = mocker.Mock(exists=mocker.Mock(return_value=latest_blob_exists), md5_hash=latest_blob_md5_hash) - - mock_doc_version_blob = mocker.Mock(exists=mocker.Mock(return_value=doc_version_blob_exists), md5_hash=doc_version_blob_md5_hash) - mock_doc_latest_blob = mocker.Mock(exists=mocker.Mock(return_value=doc_latest_blob_exists), md5_hash=doc_latest_blob_md5_hash) - - mock_release_candidate_blob = mocker.Mock(exists=mocker.Mock(return_value=release_candidate_blob_exists), md5_hash="rc_hash") - - mock_zip_latest_blob = mocker.Mock(exists=mocker.Mock(return_value=True), md5_hash="zip_hash") - mock_zip_version_blob = mocker.Mock(exists=mocker.Mock(return_value=True), md5_hash="zip_hash") - - mock_sha_latest_blob = mocker.Mock(exists=mocker.Mock(return_value=True), md5_hash="sha_hash") - mock_sha_version_blob = mocker.Mock(exists=mocker.Mock(return_value=True), md5_hash="sha_hash") - - mock_components_py_latest_blob = mocker.Mock(exists=mocker.Mock(return_value=True), md5_hash="components_py_hash") - mock_components_py_version_blob = mocker.Mock(exists=mocker.Mock(return_value=True), md5_hash="components_py_hash") - - mock_manifest_latest_blob = mocker.Mock(exists=mocker.Mock(return_value=True), md5_hash="manifest_hash") - mock_manifest_version_blob = mocker.Mock(exists=mocker.Mock(return_value=True), md5_hash="manifest_hash") - - mock_other_file_blob = mocker.Mock(exists=mocker.Mock(return_value=True), md5_hash="other_hash") - mock_bucket = mock_storage_client.bucket.return_value - - # Mock the get_gcs_storage_client function directly - mocker.patch("metadata_service.gcs_upload.get_gcs_storage_client", return_value=mock_storage_client) - - # Mock bucket blob - - def side_effect_bucket_blob(file_path): - # if file path ends in latest/metadata.yaml, return mock_latest_blob - file_path_str = str(file_path) - is_latest = f"{LATEST_GCS_FOLDER_NAME}/" in file_path_str - - if file_path_str.endswith(f"{RELEASE_CANDIDATE_GCS_FOLDER_NAME}/{METADATA_FILE_NAME}"): - return mock_release_candidate_blob - - if file_path_str.endswith(METADATA_FILE_NAME): - if is_latest: - return mock_latest_blob - else: - return mock_version_blob - - if file_path_str.endswith(DOC_FILE_NAME): - if is_latest: - return mock_doc_latest_blob - else: - return mock_doc_version_blob - - if file_path_str.endswith(f"{MANIFEST_FILE_NAME}"): - if is_latest: - return mock_manifest_latest_blob - else: - return mock_manifest_version_blob - - if file_path_str.endswith(f"{COMPONENTS_PY_FILE_NAME}"): - if is_latest: - return mock_components_py_latest_blob - else: - return mock_components_py_version_blob - - if file_path_str.endswith(".sha256"): - if is_latest: - return mock_sha_latest_blob - else: - return mock_sha_version_blob - - if file_path_str.endswith(".zip"): - if is_latest: - return mock_zip_latest_blob - else: - return mock_zip_version_blob - - else: - return mock_other_file_blob - - mock_bucket.blob.side_effect = side_effect_bucket_blob - - # Mock md5 hash - def side_effect_compute_gcs_md5(file_path): - if str(file_path) == str(metadata_file_path): - return local_file_md5_hash - elif str(file_path) == str(doc_file_path): - return doc_local_file_md5_hash - else: - return f"mock_md5_hash_{file_path}" - - mocker.patch.object(gcs_upload, "compute_gcs_md5", side_effect=side_effect_compute_gcs_md5) - - return { - "mock_storage_client": mock_storage_client, - "mock_bucket": mock_bucket, - "mock_version_blob": mock_version_blob, - "mock_latest_blob": mock_latest_blob, - "mock_release_candidate_blob": mock_release_candidate_blob, - "mock_doc_version_blob": mock_doc_version_blob, - "mock_doc_latest_blob": mock_doc_latest_blob, - "mock_manifest_latest_blob": mock_manifest_latest_blob, - "mock_components_py_latest_blob": mock_components_py_latest_blob, - "mock_manifest_version_blob": mock_manifest_version_blob, - "mock_components_py_version_blob": mock_components_py_version_blob, - "mock_sha_latest_blob": mock_sha_latest_blob, - "mock_sha_version_blob": mock_sha_version_blob, - "mock_zip_latest_blob": mock_zip_latest_blob, - "mock_zip_version_blob": mock_zip_version_blob, - "mock_other_file_blob": mock_other_file_blob, - } - - -@pytest.mark.parametrize( - "version_blob_md5_hash, latest_blob_md5_hash, local_file_md5_hash, local_doc_file_md5_hash, doc_version_blob_md5_hash, doc_latest_blob_md5_hash", - [ - pytest.param( - None, - "same_md5_hash", - "same_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - id="Version blob does not exist: Version blob should be uploaded.", - ), - pytest.param( - "same_md5_hash", - None, - "same_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - id="Latest blob does not exist: Latest blob should be uploaded.", - ), - pytest.param( - None, - None, - "same_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - id="Latest blob and Version blob does not exist: both should be uploaded.", - ), - pytest.param( - "different_md5_hash", - "same_md5_hash", - "same_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - id="Version blob does not match: Version blob should be uploaded.", - ), - pytest.param( - "same_md5_hash", - "same_md5_hash", - "same_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - id="Version blob and Latest blob match, and version and latest doc blobs match: no upload should happen.", - ), - pytest.param( - "same_md5_hash", - "different_md5_hash", - "same_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - id="Latest blob does not match: Latest blob should be uploaded.", - ), - pytest.param( - "same_md5_hash", - "same_md5_hash", - "different_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - id="Latest blob and Version blob does not match: both should be uploaded.", - ), - pytest.param( - "same_md5_hash", - "same_md5_hash", - "same_md5_hash", - "same_doc_md5_hash", - None, - "same_doc_md5_hash", - id="Version doc blob does not exist: Doc version blob should be uploaded.", - ), - pytest.param( - "same_md5_hash", - "same_md5_hash", - "same_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - None, - id="Latest doc blob does not exist: Doc latest blob should be uploaded.", - ), - pytest.param( - "same_md5_hash", - "same_md5_hash", - "same_md5_hash", - "same_doc_md5_hash", - "different_doc_md5_hash", - "same_doc_md5_hash", - id="Version doc blob does not match: Doc version blob should be uploaded.", - ), - pytest.param( - "same_md5_hash", - "same_md5_hash", - "same_md5_hash", - "same_doc_md5_hash", - "same_doc_md5_hash", - "different_doc_md5_hash", - id="Latest doc blob does not match: Doc version blob should be uploaded.", - ), - ], -) -def test_upload_metadata_to_gcs_valid_metadata( - mocker, - valid_metadata_upload_files, - version_blob_md5_hash, - latest_blob_md5_hash, - local_file_md5_hash, - local_doc_file_md5_hash, - doc_version_blob_md5_hash, - doc_latest_blob_md5_hash, -): - mocker.spy(gcs_upload, "_file_upload") - mocker.spy(gcs_upload, "upload_file_if_changed") - for valid_metadata_upload_file in valid_metadata_upload_files: - metadata_file_path = Path(valid_metadata_upload_file) - metadata = ConnectorMetadataDefinitionV0.parse_obj(yaml.safe_load(metadata_file_path.read_text())) - mocks = setup_upload_mocks( - mocker, - version_blob_md5_hash, - latest_blob_md5_hash, - local_file_md5_hash, - local_doc_file_md5_hash, - doc_version_blob_md5_hash, - doc_latest_blob_md5_hash, - metadata_file_path, - VALID_DOC_FILE_PATH, - ) - mocker.patch.object(gcs_upload, "_write_metadata_to_tmp_file", mocker.Mock(return_value=metadata_file_path)) - - expected_version_key = f"metadata/{metadata.data.dockerRepository}/{metadata.data.dockerImageTag}/{METADATA_FILE_NAME}" - expected_latest_key = f"metadata/{metadata.data.dockerRepository}/{LATEST_GCS_FOLDER_NAME}/{METADATA_FILE_NAME}" - expected_release_candidate_key = ( - f"metadata/{metadata.data.dockerRepository}/{RELEASE_CANDIDATE_GCS_FOLDER_NAME}/{METADATA_FILE_NAME}" - ) - expected_version_doc_key = f"metadata/{metadata.data.dockerRepository}/{metadata.data.dockerImageTag}/{DOC_FILE_NAME}" - expected_latest_doc_key = f"metadata/{metadata.data.dockerRepository}/latest/{DOC_FILE_NAME}" - - is_release_candidate = "-rc" in metadata.data.dockerImageTag - - # Call function under tests - - upload_info = gcs_upload.upload_metadata_to_gcs( - "my_bucket", metadata_file_path, validator_opts=ValidatorOptions(docs_path=VALID_DOC_FILE_PATH) - ) - - # Assert correct file upload attempts were made - - expected_calls = [ - # Always upload the versioned metadata - mocker.call( - local_file_path=metadata_file_path, bucket=mocks["mock_bucket"], blob_path=expected_version_key, disable_cache=True - ), - # Always upload the versioned doc - mocker.call( - local_file_path=VALID_DOC_FILE_PATH, - bucket=mocks["mock_bucket"], - blob_path=expected_version_doc_key, - disable_cache=False, - ), - ] - - if is_release_candidate: - expected_calls.append( - mocker.call( - local_file_path=metadata_file_path, - bucket=mocks["mock_bucket"], - blob_path=expected_release_candidate_key, - disable_cache=True, - ) - ) - else: - expected_calls.append( - mocker.call( - local_file_path=VALID_DOC_FILE_PATH, bucket=mocks["mock_bucket"], blob_path=expected_latest_doc_key, disable_cache=False - ) - ) - expected_calls.append( - mocker.call( - local_file_path=metadata_file_path, bucket=mocks["mock_bucket"], blob_path=expected_latest_key, disable_cache=True - ) - ) - - gcs_upload.upload_file_if_changed.assert_has_calls(expected_calls, any_order=True) - - # Assert correct files were uploaded - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="latest_metadata", - blob_mock=mocks["mock_latest_blob"], - should_upload=latest_blob_md5_hash != local_file_md5_hash and not is_release_candidate, - file_path=metadata_file_path, - failure_message="Latest blob should be uploaded.", - ) - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="versioned_release_candidate", - blob_mock=mocks["mock_release_candidate_blob"], - should_upload=is_release_candidate, - file_path=metadata_file_path, - failure_message="Release candidate blob should be uploaded.", - ) - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="versioned_metadata", - blob_mock=mocks["mock_version_blob"], - should_upload=version_blob_md5_hash != local_file_md5_hash, - file_path=metadata_file_path, - failure_message="Version blob should be uploaded.", - ) - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="versioned_doc", - blob_mock=mocks["mock_doc_version_blob"], - should_upload=doc_version_blob_md5_hash != local_doc_file_md5_hash, - file_path=VALID_DOC_FILE_PATH, - failure_message="Doc version blob should be uploaded.", - ) - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="latest_doc", - blob_mock=mocks["mock_doc_latest_blob"], - should_upload=doc_latest_blob_md5_hash != local_doc_file_md5_hash and not is_release_candidate, - file_path=VALID_DOC_FILE_PATH, - failure_message="Doc latest blob should be uploaded.", - ) - - # clear the call count - gcs_upload.upload_file_if_changed.reset_mock() - - -def test_upload_metadata_to_gcs_non_existent_metadata_file(): - metadata_file_path = Path("./i_dont_exist.yaml") - with pytest.raises(ValueError, match="No such file or directory"): - gcs_upload.upload_metadata_to_gcs( - "my_bucket", - metadata_file_path, - validator_opts=ValidatorOptions(docs_path=VALID_DOC_FILE_PATH), - ) - - -def test_upload_invalid_metadata_to_gcs(mocker, invalid_metadata_yaml_files): - # Mock dockerhub - mocker.patch("metadata_service.validators.metadata_validator.is_image_on_docker_hub", side_effect=stub_is_image_on_docker_hub) - - # Test that all invalid metadata files throw a ValueError - for invalid_metadata_file in invalid_metadata_yaml_files: - metadata_file_path = Path(invalid_metadata_file) - - error_match_if_validation_fails_as_expected = "Validation error" - - # If validation succeeds, it goes on to upload any new/changed files. - # We don't mock the gcs stuff in this test, so it fails trying to - # mock compute the md5 hash. - error_match_if_validation_succeeds = "Please set the GCS_CREDENTIALS env var." - - assert_upload_invalid_metadata_fails_correctly( - metadata_file_path, error_match_if_validation_fails_as_expected, error_match_if_validation_succeeds - ) - - -def test_upload_metadata_to_gcs_invalid_docker_images(mocker, invalid_metadata_upload_files): - setup_upload_mocks(mocker, None, None, "new_md5_hash", None, None, None, None, None) - - # Test that valid metadata files that reference invalid docker images throw a ValueError - for invalid_metadata_file in invalid_metadata_upload_files: - metadata_file_path = Path(invalid_metadata_file) - - error_match_if_validation_fails_as_expected = "does not exist in DockerHub" - - # If validation succeeds, it goes on to upload any new/changed files. - # We mock gcs stuff in this test, so it fails trying to compare the md5 hashes. - error_match_if_validation_succeeds = "Unexpected path" - - assert_upload_invalid_metadata_fails_correctly( - metadata_file_path, error_match_if_validation_fails_as_expected, error_match_if_validation_succeeds - ) - - -def test_upload_metadata_to_gcs_with_prerelease(mocker, valid_metadata_upload_files, tmp_path): - mocker.spy(gcs_upload, "_file_upload") - mocker.spy(gcs_upload, "upload_file_if_changed") - prerelease_image_tag = "1.5.6-preview.f80318f" - - for valid_metadata_upload_file in valid_metadata_upload_files: - tmp_metadata_file_path = tmp_path / "metadata.yaml" - if tmp_metadata_file_path.exists(): - tmp_metadata_file_path.unlink() - - metadata_file_path = Path(valid_metadata_upload_file) - metadata = ConnectorMetadataDefinitionV0.parse_obj(yaml.safe_load(metadata_file_path.read_text())) - expected_version_key = f"metadata/{metadata.data.dockerRepository}/{prerelease_image_tag}/{METADATA_FILE_NAME}" - - mocks = setup_upload_mocks(mocker, "new_md5_hash1", "new_md5_hash2", "new_md5_hash3", None, None, None, metadata_file_path, None) - - # Mock tempfile to have a deterministic path - mocker.patch.object( - gcs_upload.tempfile, - "NamedTemporaryFile", - mocker.Mock( - return_value=mocker.Mock(__enter__=mocker.Mock(return_value=tmp_metadata_file_path.open("w")), __exit__=mocker.Mock()) - ), - ) - - upload_info = gcs_upload.upload_metadata_to_gcs( - "my_bucket", - metadata_file_path, - ValidatorOptions(docs_path=VALID_DOC_FILE_PATH, prerelease_tag=prerelease_image_tag), - ) - - # Assert that the metadata is overrode - tmp_metadata, error = gcs_upload.validate_and_load( - tmp_metadata_file_path, [], validator_opts=ValidatorOptions(docs_path=VALID_DOC_FILE_PATH) - ) - tmp_metadata_dict = to_json_sanitized_dict(tmp_metadata, exclude_none=True) - assert tmp_metadata_dict["data"]["dockerImageTag"] == prerelease_image_tag - for registry in get(tmp_metadata_dict, "data.registryOverrides", {}).values(): - if "dockerImageTag" in registry: - assert registry["dockerImageTag"] == prerelease_image_tag - - # Assert uploads attempted - - expected_calls = [ - mocker.call( - local_file_path=tmp_metadata_file_path, bucket=mocks["mock_bucket"], blob_path=expected_version_key, disable_cache=True - ), - ] - - gcs_upload.upload_file_if_changed.assert_has_calls(expected_calls, any_order=True) - - # Assert versioned uploads happened - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="versioned_metadata", - blob_mock=mocks["mock_version_blob"], - should_upload=True, - file_path=tmp_metadata_file_path, - failure_message="Latest blob should be uploaded.", - ) - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="versioned_doc", - blob_mock=mocks["mock_doc_version_blob"], - should_upload=True, - file_path=VALID_DOC_FILE_PATH, - failure_message="Latest blob should be uploaded.", - ) - - # Assert latest uploads did not happen - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="latest_metadata", - blob_mock=mocks["mock_latest_blob"], - should_upload=False, - file_path=metadata_file_path, - failure_message="Latest blob should be uploaded.", - ) - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="latest_doc", - blob_mock=mocks["mock_doc_latest_blob"], - should_upload=False, - file_path=VALID_DOC_FILE_PATH, - failure_message="Latest blob should be uploaded.", - ) - - # clear the call count - gcs_upload._file_upload.reset_mock() - gcs_upload.upload_file_if_changed.reset_mock() - - -@pytest.mark.parametrize("prerelease", [True, False]) -def test_upload_metadata_to_gcs_release_candidate(mocker, get_fixture_path, tmp_path, prerelease): - mocker.spy(gcs_upload, "_file_upload") - mocker.spy(gcs_upload, "upload_file_if_changed") - release_candidate_metadata_file = get_fixture_path( - "metadata_upload/valid/referenced_image_in_dockerhub/metadata_release_candidate.yaml" - ) - release_candidate_metadata_file_path = Path(release_candidate_metadata_file) - metadata = ConnectorMetadataDefinitionV0.parse_obj(yaml.safe_load(release_candidate_metadata_file_path.read_text())) - - tmp_metadata_file_path = tmp_path / "metadata.yaml" - if tmp_metadata_file_path.exists(): - tmp_metadata_file_path.unlink() - - mocks = setup_upload_mocks( - mocker, "new_md5_hash1", "new_md5_hash2", "new_md5_hash3", None, None, None, release_candidate_metadata_file_path, None - ) - - # Mock tempfile to have a deterministic path - mocker.patch.object( - gcs_upload.tempfile, - "NamedTemporaryFile", - mocker.Mock(return_value=mocker.Mock(__enter__=mocker.Mock(return_value=tmp_metadata_file_path.open("w")), __exit__=mocker.Mock())), - ) - assert metadata.data.releases.rolloutConfiguration.enableProgressiveRollout - - prerelease_tag = "1.5.6-preview.f80318f" if prerelease else None - - upload_info = gcs_upload.upload_metadata_to_gcs( - "my_bucket", - release_candidate_metadata_file_path, - ValidatorOptions(docs_path=VALID_DOC_FILE_PATH, prerelease_tag=prerelease_tag), - ) - - # Assert versioned uploads happened - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="versioned_release_candidate", - blob_mock=mocks["mock_release_candidate_blob"], - should_upload=not prerelease, - file_path=tmp_metadata_file_path, - failure_message="Latest blob should be uploaded.", - ) - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="versioned_doc", - blob_mock=mocks["mock_doc_version_blob"], - should_upload=True, - file_path=VALID_DOC_FILE_PATH, - failure_message="Latest blob should be uploaded.", - ) - - # Assert latest uploads did not happen - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="latest_metadata", - blob_mock=mocks["mock_latest_blob"], - should_upload=False, - file_path=tmp_metadata_file_path, - failure_message="Latest blob should be uploaded.", - ) - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="latest_doc", - blob_mock=mocks["mock_doc_latest_blob"], - should_upload=False, - file_path=VALID_DOC_FILE_PATH, - failure_message="Latest blob should be uploaded.", - ) - - -@pytest.mark.parametrize( - "manifest_exists, components_py_exists", - [ - (True, True), # Both files exist - (True, False), # Only manifest exists - (False, True), # Only components.py exists - (False, False), # Neither file exists - ], -) -def test_upload_metadata_to_gcs_with_manifest_files( - mocker, temp_metadata_directory, tmp_path, manifest_exists, components_py_exists, mock_git_operations -): - mocker.spy(gcs_upload, "_file_upload") - mocker.spy(gcs_upload, "upload_file_if_changed") - - # Use the temporary metadata file created by the fixture - metadata_file_path = temp_metadata_directory - expected_manifest_file_path = metadata_file_path.parent / MANIFEST_FILE_NAME - expected_components_py_file_path = metadata_file_path.parent / COMPONENTS_PY_FILE_NAME - - # No more Path.exists mocking needed - files either exist or don't based on fixture creation! - # Git operations are mocked by the mock_git_operations fixture! - - # Mock the _safe_load_metadata_file function to bypass YAML parsing issues in test environment - sample_metadata = { - "metadataSpecVersion": "1.0", - "data": { - "name": "Test Connector", - "definitionId": "12345678-1234-1234-1234-123456789012", - "connectorType": "source", - "dockerRepository": "airbyte/source-exists-test", - "dockerImageTag": "0.1.0", - "documentationUrl": "https://docs.airbyte.com/test", - "license": "MIT", - "githubIssueLabel": "source-test", - "connectorSubtype": "api", - "releaseStage": "alpha", - "tags": ["language:python"], - }, - } - mocker.patch("metadata_service.gcs_upload._safe_load_metadata_file", return_value=sample_metadata) - - # mock create_zip_and_get_sha256 - mocker.patch.object(gcs_upload, "create_zip_and_get_sha256", mocker.Mock(return_value="fake_zip_sha256")) - - tmp_metadata_file_path = tmp_path / "metadata.yaml" - tmp_zip_file_path = tmp_path / "components.zip" - tmp_sha256_file_path = tmp_path / "components.sha256" - - def mock_tmp_files(*args, **kwargs): - file_to_return = tmp_metadata_file_path.open("w") - if kwargs.get("suffix") == ".zip": - file_to_return = tmp_zip_file_path.open("w") - if kwargs.get("suffix") == ".sha256": - file_to_return = tmp_sha256_file_path.open("w") - - return mocker.Mock(__enter__=mocker.Mock(return_value=file_to_return), __exit__=mocker.Mock()) - - # Mock tempfile to have a deterministic path - mocker.patch.object( - gcs_upload.tempfile, - "NamedTemporaryFile", - mocker.Mock(side_effect=mock_tmp_files), - ) - - mocks = setup_upload_mocks(mocker, "new_md5_hash1", "new_md5_hash2", "new_md5_hash3", None, None, None, metadata_file_path, None) - - upload_info = gcs_upload.upload_metadata_to_gcs( - "my_bucket", - metadata_file_path, - validator_opts=ValidatorOptions(docs_path=VALID_DOC_FILE_PATH), - ) - - # Latest Uploads - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="latest_manifest", - blob_mock=mocks["mock_manifest_latest_blob"], - should_upload=manifest_exists, - file_path=expected_manifest_file_path, - failure_message="Latest manifest should be uploaded.", - ) - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="latest_components_zip", - blob_mock=mocks["mock_zip_latest_blob"], - should_upload=components_py_exists, - file_path=tmp_zip_file_path, - failure_message="Latest components.py should be uploaded.", - ) - - # Versioned Uploads - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="versioned_manifest", - blob_mock=mocks["mock_manifest_version_blob"], - should_upload=manifest_exists, - file_path=expected_manifest_file_path, - failure_message="Versioned manifest should be uploaded.", - ) - - assert_blob_upload( - upload_info=upload_info, - upload_info_file_key="versioned_components_zip", - blob_mock=mocks["mock_zip_version_blob"], - should_upload=components_py_exists, - file_path=tmp_zip_file_path, - failure_message="Versioned components.py should be uploaded.", - ) - - # clear the call count - gcs_upload._file_upload.reset_mock() - gcs_upload.upload_file_if_changed.reset_mock() diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/test_registry.py b/airbyte-ci/connectors/metadata_service/lib/tests/test_registry.py deleted file mode 100644 index 91b2e948b5bc..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/test_registry.py +++ /dev/null @@ -1,328 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -import json -import os -from unittest.mock import Mock, patch - -import pytest - -from metadata_service.constants import REGISTRIES_FOLDER -from metadata_service.models.generated import ConnectorRegistryV0 -from metadata_service.registry import ( - ConnectorTypePrimaryKey, - ConnectorTypes, - PolymorphicRegistryEntry, - _apply_metrics_to_registry_entry, - _build_connector_registry, - _convert_json_to_metrics_dict, - _get_connector_type_from_registry_entry, - _persist_registry, -) - - -class TestGetConnectorTypeFromRegistryEntry: - """Tests for _get_connector_type_from_registry_entry function.""" - - @pytest.fixture - def mock_source_entry(self): - """Create a mock source registry entry.""" - entry = Mock(spec=PolymorphicRegistryEntry) - setattr(entry, ConnectorTypePrimaryKey.SOURCE.value, "test-source-id") - return entry - - @pytest.fixture - def mock_destination_entry(self): - """Create a mock destination registry entry.""" - entry = Mock(spec=PolymorphicRegistryEntry) - setattr(entry, ConnectorTypePrimaryKey.DESTINATION.value, "test-destination-id") - return entry - - @pytest.fixture - def mock_invalid_entry(self): - """Create a mock entry that is neither source nor destination.""" - entry = Mock(spec=PolymorphicRegistryEntry) - return entry - - @pytest.mark.parametrize( - "entry_fixture,expected_type,description", - [ - ("mock_source_entry", ConnectorTypes.SOURCE, "source entry"), - ("mock_destination_entry", ConnectorTypes.DESTINATION, "destination entry"), - ], - ) - def test_get_connector_type_from_registry_entry_types(self, entry_fixture, expected_type, description, request): - """Test connector type detection from registry entries.""" - registry_entry = request.getfixturevalue(entry_fixture) - - result = _get_connector_type_from_registry_entry(registry_entry) - - assert result == expected_type - assert isinstance(result, ConnectorTypes) - - @pytest.mark.parametrize( - "entry_fixture,expected_type,has_attribute,not_has_attribute,description", - [ - ( - "mock_source_entry", - ConnectorTypes.SOURCE, - ConnectorTypePrimaryKey.SOURCE.value, - ConnectorTypePrimaryKey.DESTINATION.value, - "source entry", - ), - ( - "mock_destination_entry", - ConnectorTypes.DESTINATION, - ConnectorTypePrimaryKey.DESTINATION.value, - ConnectorTypePrimaryKey.SOURCE.value, - "destination entry", - ), - ], - ) - def test_get_connector_type_from_registry_entry_has_correct_attribute( - self, entry_fixture, expected_type, has_attribute, not_has_attribute, description, request - ): - registry_entry = request.getfixturevalue(entry_fixture) - - assert hasattr(registry_entry, has_attribute) - assert not hasattr(registry_entry, not_has_attribute) - - result = _get_connector_type_from_registry_entry(registry_entry) - - assert result == expected_type - - def test_get_connector_type_from_registry_entry_invalid_raises_error(self, mock_invalid_entry): - """Test that invalid entry raises ValueError.""" - assert not hasattr(mock_invalid_entry, ConnectorTypePrimaryKey.SOURCE.value) - assert not hasattr(mock_invalid_entry, ConnectorTypePrimaryKey.DESTINATION.value) - - with pytest.raises(ValueError) as exc_info: - _get_connector_type_from_registry_entry(mock_invalid_entry) - - assert "Registry entry is not a source or destination" in str(exc_info.value) - - -class TestConvertJsonToMetricsDict: - """Tests for _convert_json_to_metrics_dict function.""" - - @pytest.mark.parametrize( - "jsonl_input,expected_output,description", - [ - ( - '{"_airbyte_data": {"connector_definition_id": "conn-123", "airbyte_platform": "cloud", "usage": 100}}', - {"conn-123": {"cloud": {"connector_definition_id": "conn-123", "airbyte_platform": "cloud", "usage": 100}}}, - "single connector", - ), - ( - '{"_airbyte_data": {"connector_definition_id": "conn-123", "airbyte_platform": "cloud", "usage": 100}}\n{"_airbyte_data": {"connector_definition_id": "conn-456", "airbyte_platform": "oss", "usage": 50}}', - { - "conn-123": {"cloud": {"connector_definition_id": "conn-123", "airbyte_platform": "cloud", "usage": 100}}, - "conn-456": {"oss": {"connector_definition_id": "conn-456", "airbyte_platform": "oss", "usage": 50}}, - }, - "multiple connectors", - ), - ("", {}, "empty input"), - ], - ) - def test_convert_json_to_metrics_dict_valid_jsonl(self, jsonl_input, expected_output, description): - """Test JSONL string conversion to metrics dictionary.""" - result = _convert_json_to_metrics_dict(jsonl_input) - - assert result == expected_output - - -class TestApplyMetricsToRegistryEntry: - """Tests for _apply_metrics_to_registry_entry function.""" - - @pytest.mark.parametrize( - "connector_type,registry_entry,metrics_dict,expected_metrics,description", - [ - ( - ConnectorTypes.SOURCE, - {"sourceDefinitionId": "source-123", "name": "Test Source"}, - {"source-123": {"cloud": {"usage": 100}}}, - {"cloud": {"usage": 100}}, - "source with matching metrics", - ), - ( - ConnectorTypes.DESTINATION, - {"destinationDefinitionId": "dest-456", "name": "Test Destination"}, - {"dest-456": {"oss": {"usage": 50}}}, - {"oss": {"usage": 50}}, - "destination with matching metrics", - ), - ( - ConnectorTypes.SOURCE, - {"sourceDefinitionId": "source-999", "name": "No Metrics Source"}, - {}, - {}, - "entry with no matching metrics", - ), - ], - ) - def test_apply_metrics_to_registry_entry_scenarios(self, connector_type, registry_entry, metrics_dict, expected_metrics, description): - """Test metrics application to registry entries.""" - result = _apply_metrics_to_registry_entry(registry_entry, connector_type, metrics_dict) - - assert result["generated"]["metrics"] == expected_metrics - assert result["name"] == registry_entry["name"] - - def test_apply_metrics_to_registry_entry_preserves_existing_structure(self): - """Test that existing registry entry structure is preserved.""" - registry_entry = {"sourceDefinitionId": "source-123", "name": "Test Source", "existing_field": "value"} - metrics_dict = {"source-123": {"cloud": {"usage": 100}}} - - result = _apply_metrics_to_registry_entry(registry_entry, ConnectorTypes.SOURCE, metrics_dict) - - assert result["existing_field"] == "value" - assert result["name"] == "Test Source" - assert result["generated"]["metrics"] == {"cloud": {"usage": 100}} - - -class TestBuildConnectorRegistry: - """Tests for _build_connector_registry function.""" - - @pytest.mark.parametrize( - "entry_dicts,expected_sources_count,expected_destinations_count,description", - [ - ( - [ - { - "sourceDefinitionId": "550e8400-e29b-41d4-a716-446655440001", - "name": "Source 1", - "dockerRepository": "test/source", - "dockerImageTag": "1.0.0", - "documentationUrl": "https://docs.test.com", - "spec": {}, - }, - { - "destinationDefinitionId": "550e8400-e29b-41d4-a716-446655440002", - "name": "Destination 1", - "dockerRepository": "test/dest", - "dockerImageTag": "1.0.0", - "documentationUrl": "https://docs.test.com", - "spec": {}, - }, - ], - 1, - 1, - "mixed sources and destinations", - ), - ( - [ - { - "sourceDefinitionId": "550e8400-e29b-41d4-a716-446655440001", - "name": "Source 1", - "dockerRepository": "test/source1", - "dockerImageTag": "1.0.0", - "documentationUrl": "https://docs.test.com", - "spec": {}, - }, - { - "sourceDefinitionId": "550e8400-e29b-41d4-a716-446655440002", - "name": "Source 2", - "dockerRepository": "test/source2", - "dockerImageTag": "1.0.0", - "documentationUrl": "https://docs.test.com", - "spec": {}, - }, - ], - 2, - 0, - "sources only", - ), - ([], 0, 0, "empty entries"), - ], - ) - def test_build_connector_registry_scenarios(self, entry_dicts, expected_sources_count, expected_destinations_count, description): - """Test registry building with different entry combinations.""" - entries = [] - for entry_dict in entry_dicts: - entry = Mock(spec=PolymorphicRegistryEntry) - if "sourceDefinitionId" in entry_dict: - setattr(entry, ConnectorTypePrimaryKey.SOURCE.value, entry_dict["sourceDefinitionId"]) - if "destinationDefinitionId" in entry_dict: - setattr(entry, ConnectorTypePrimaryKey.DESTINATION.value, entry_dict["destinationDefinitionId"]) - entries.append(entry) - - with ( - patch("metadata_service.registry.to_json_sanitized_dict") as mock_sanitize, - patch("metadata_service.registry._apply_metrics_to_registry_entry") as mock_apply_metrics, - patch("metadata_service.registry._apply_release_candidate_entries") as mock_apply_rc, - ): - mock_sanitize.side_effect = entry_dicts - mock_apply_metrics.side_effect = lambda x, *args: x - mock_apply_rc.side_effect = lambda x, *args: x - - result = _build_connector_registry(entries, {}, {}) - - assert isinstance(result, ConnectorRegistryV0) - assert len(result.sources) == expected_sources_count - assert len(result.destinations) == expected_destinations_count - - def test_build_connector_registry_applies_metrics_and_rc(self): - """Test that metrics and release candidates are properly applied.""" - source_entry = Mock(spec=PolymorphicRegistryEntry) - setattr(source_entry, ConnectorTypePrimaryKey.SOURCE.value, "550e8400-e29b-41d4-a716-446655440001") - - entry_dict = { - "sourceDefinitionId": "550e8400-e29b-41d4-a716-446655440001", - "name": "Test Source", - "dockerRepository": "test/source", - "dockerImageTag": "1.0.0", - "documentationUrl": "https://docs.test.com", - "spec": {}, - } - - with ( - patch("metadata_service.registry.to_json_sanitized_dict") as mock_sanitize, - patch("metadata_service.registry._apply_metrics_to_registry_entry") as mock_apply_metrics, - patch("metadata_service.registry._apply_release_candidate_entries") as mock_apply_rc, - ): - mock_sanitize.return_value = entry_dict - mock_apply_metrics.return_value = entry_dict - mock_apply_rc.return_value = entry_dict - - result = _build_connector_registry([source_entry], {}, {}) - - mock_apply_metrics.assert_called_once() - mock_apply_rc.assert_called_once() - assert len(result.sources) == 1 - - -class TestPersistRegistryToJson: - """Tests for _persist_registry_to_json function.""" - - @pytest.fixture - def mock_registry(self): - """Create a mock registry object.""" - registry = Mock(spec=ConnectorRegistryV0) - registry.json.return_value = '{"sources": [], "destinations": []}' - return registry - - @pytest.mark.parametrize( - "registry_type,expected_filename,description", - [ - ("cloud", "cloud_registry.json", "cloud registry"), - ("oss", "oss_registry.json", "oss registry"), - ], - ) - def test_persist_registry_success(self, mock_registry, registry_type, expected_filename, description): - """Test successful registry persistence to GCS.""" - with ( - patch("metadata_service.registry.storage.Client") as mock_client_class, - ): - mock_client = Mock() - mock_client_class.return_value = mock_client - - mock_bucket = Mock() - mock_client.bucket.return_value = mock_bucket - - mock_blob = Mock() - mock_bucket.blob.return_value = mock_blob - - _persist_registry(mock_registry, registry_type, mock_bucket) - - mock_bucket.blob.assert_called_once_with(f"{REGISTRIES_FOLDER}/{expected_filename}") - mock_blob.upload_from_string.assert_called_once() diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/test_registry_entry.py b/airbyte-ci/connectors/metadata_service/lib/tests/test_registry_entry.py deleted file mode 100644 index 34164ab0ced7..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/test_registry_entry.py +++ /dev/null @@ -1,550 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -import datetime -import json -import os -import pathlib -import tempfile -from unittest.mock import MagicMock, Mock, patch - -import pytest -import yaml - -from metadata_service.registry_entry import generate_and_persist_registry_entry - - -@pytest.fixture -def sample_spec_dict(): - """Sample spec dictionary for testing.""" - return { - "documentationUrl": "https://docs.airbyte.com/integrations/sources/test", - "connectionSpecification": { - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Test Source Spec", - "type": "object", - "properties": {"api_key": {"type": "string", "title": "API Key", "description": "API key for authentication"}}, - "required": ["api_key"], - }, - } - - -@pytest.fixture -def sample_dependencies_dict(): - """Sample dependencies dictionary for testing.""" - return {"dependencies": [{"package_name": "airbyte-cdk", "version": "0.50.0"}, {"package_name": "requests", "version": "2.28.0"}]} - - -@pytest.fixture( - params=[ - # (registry_type, enabled, version_type) - ("oss", True, "latest"), - ("cloud", True, "latest"), - ("oss", True, "rc"), - ("cloud", True, "rc"), - ("oss", True, "dev"), - ("cloud", True, "dev"), - ("oss", False, "latest"), - ("cloud", False, "latest"), - ("oss", False, "rc"), - ("cloud", False, "rc"), - ("oss", False, "dev"), - ("cloud", False, "dev"), - ] -) -def registry_scenario(request, sample_spec_dict): - """Parameterized fixture providing different registry scenarios with temp files.""" - registry_type, enabled, version_type = request.param - - # Create metadata dict based on enabled/disabled status - docker_tag = "1.0.0" - if version_type == "rc": - docker_tag = "1.0.0-rc" - elif version_type == "dev": - docker_tag = "1.0.0-dev" - - metadata_dict = { - "metadataSpecVersion": "1.0", - "data": { - "name": f"Test Source {'Enabled' if enabled else 'Disabled'}", - "definitionId": "12345678-1234-1234-1234-123456789012", - "connectorType": "source", - "dockerRepository": f"airbyte/source-test-{'enabled' if enabled else 'disabled'}", - "dockerImageTag": docker_tag, - "documentationUrl": f"https://docs.airbyte.com/integrations/sources/test-{'enabled' if enabled else 'disabled'}", - "connectorSubtype": "api", - "releaseStage": "beta", - "license": "MIT", - "registryOverrides": {"oss": {"enabled": enabled}, "cloud": {"enabled": enabled}}, - "tags": ["language:python"], - }, - } - - # Create temporary files - with tempfile.TemporaryDirectory() as temp_dir: - # Create metadata file - metadata_path = pathlib.Path(temp_dir) / "metadata.yaml" - with open(metadata_path, "w") as f: - yaml.dump(metadata_dict, f) - - # Create spec file - spec_path = pathlib.Path(temp_dir) / "spec.json" - with open(spec_path, "w") as f: - json.dump(sample_spec_dict, f) - - yield { - "registry_type": registry_type, - "enabled": enabled, - "version_type": version_type, - "metadata_path": metadata_path, - "spec_path": spec_path, - "metadata_dict": metadata_dict, - "docker_image_tag": docker_tag, - "is_prerelease": version_type == "dev", - } - - -@patch("metadata_service.registry_entry.send_slack_message") -@patch("metadata_service.registry_entry._persist_connector_registry_entry") -@patch("metadata_service.registry_entry._get_icon_blob_from_gcs") -@patch("metadata_service.registry_entry.safe_read_gcs_file") -@patch("metadata_service.registry_entry.get_gcs_storage_client") -@patch("metadata_service.registry.storage.Client") -@patch("metadata_service.registry_entry.SpecCache") -def test_generate_and_persist_registry_entry( - mock_spec_cache_class, - mock_storage_client_class, - mock_gcs_client, - mock_safe_read_gcs_file, - mock_get_icon_blob, - mock_persist_entry, - mock_send_slack, - registry_scenario, - sample_dependencies_dict, -): - """Test registry entry generation for all scenarios: enabled/disabled, all registry types, and all version types.""" - # Arrange - scenario = registry_scenario - bucket_name = "test-bucket" - - # Mock GCS client setup - mock_storage_client = Mock() - mock_storage_client_class.return_value = mock_storage_client - mock_bucket = Mock() - mock_blob = Mock() - mock_icon_blob = Mock() - - mock_gcs_client.return_value = mock_storage_client - mock_storage_client.bucket.return_value = mock_bucket - mock_bucket.blob.return_value = mock_blob - mock_bucket.delete_blob = Mock() - - mock_spec_cache = Mock() - mock_spec_cache_class.return_value = mock_spec_cache - mock_spec_cache.download_spec.return_value = json.loads('{"fake": "spec"}') - - mock_blob.download_as_string.return_value = yaml.dump(scenario["metadata_dict"]) - mock_blob.name = "fake/blob/path.yaml" - mock_blob.updated.isoformat.return_value = "2025-01-23T12:34:56Z" - - if scenario["enabled"]: - # Mock successful operations for enabled scenarios - mock_safe_read_gcs_file.return_value = json.dumps(sample_dependencies_dict) - mock_icon_blob.bucket.name = bucket_name - mock_icon_blob.name = f"metadata/{scenario['metadata_dict']['data']['dockerRepository']}/latest/icon.svg" - mock_get_icon_blob.return_value = mock_icon_blob - else: - # Mock existing blob for deletion scenarios (latest versions only) - mock_blob.exists.return_value = True - - # Act - generate_and_persist_registry_entry( - bucket_name=bucket_name, - repo_metadata_file_path=scenario["metadata_path"], - registry_type=scenario["registry_type"], - docker_image_tag=scenario["docker_image_tag"], - is_prerelease=scenario["is_prerelease"], - ) - - # Assert based on enabled/disabled status - if scenario["enabled"]: - # ENABLED SCENARIO ASSERTIONS - - # Verify GCS operations were called - mock_gcs_client.assert_called() - # For "latest" version type (normal publishes), safe_read_gcs_file and _get_icon_blob_from_gcs - # are called twice because we generate two sets of metadata: one for versioned entry (actual - # published version), one for latest entry (with version pinning applied). - if scenario["version_type"] == "latest": - assert mock_safe_read_gcs_file.call_count == 2 - assert mock_get_icon_blob.call_count == 2 - else: - mock_safe_read_gcs_file.assert_called_once() - mock_get_icon_blob.assert_called_once_with(bucket_name, scenario["metadata_dict"]["data"]) - - # Verify registry entry was persisted - mock_persist_entry.assert_called() - persist_call_args = mock_persist_entry.call_args_list - - # Check number of persist calls based on version type - if scenario["version_type"] == "latest" or scenario["version_type"] == "rc": - # in "latest" mode, we write to versioned + `/latest` - # in "rc" mode, we write to versioned + `/release_candidate` - assert len(persist_call_args) == 2 - else: # dev - assert len(persist_call_args) == 1 # only one path - - # Verify the registry entry model was created correctly - for call_args in persist_call_args: - bucket_name_arg, registry_entry_model, registry_path = call_args[0] - assert bucket_name_arg == bucket_name - assert scenario["registry_type"] in registry_path - - # Verify the model has expected fields - registry_entry_dict = json.loads(registry_entry_model.json(exclude_none=True)) - - # Check core field transformations - assert "sourceDefinitionId" in registry_entry_dict - assert registry_entry_dict["sourceDefinitionId"] == scenario["metadata_dict"]["data"]["definitionId"] - - # Verify required fields were added - assert registry_entry_dict["tombstone"] is False - assert registry_entry_dict["custom"] is False - assert registry_entry_dict["public"] is True - assert "iconUrl" in registry_entry_dict - assert "generated" in registry_entry_dict - assert "packageInfo" in registry_entry_dict - assert registry_entry_dict["packageInfo"]["cdk_version"] == "python:0.50.0" - assert "spec" in registry_entry_dict - - # Verify fields were removed - assert "registryOverrides" not in registry_entry_dict - assert "connectorType" not in registry_entry_dict - assert "definitionId" not in registry_entry_dict - - registry_entry_paths = set() - for kall in persist_call_args: - args, _ = kall - # blob path is the last positional arg - registry_entry_paths.add(args[-1]) - if scenario["version_type"] == "rc": - assert registry_entry_paths == { - f'metadata/airbyte/source-test-enabled/{scenario["docker_image_tag"]}/{scenario["registry_type"]}.json', - f'metadata/airbyte/source-test-enabled/release_candidate/{scenario["registry_type"]}.json', - } - elif scenario["version_type"] == "latest": - assert registry_entry_paths == { - f'metadata/airbyte/source-test-enabled/{scenario["docker_image_tag"]}/{scenario["registry_type"]}.json', - f'metadata/airbyte/source-test-enabled/latest/{scenario["registry_type"]}.json', - } - elif scenario["version_type"] == "dev": - assert registry_entry_paths == { - f'metadata/airbyte/source-test-enabled/{scenario["docker_image_tag"]}/{scenario["registry_type"]}.json', - } - else: - raise Exception(f'Unexpected scenario: {scenario["version_type"]}') - - # Verify Slack notifications - slack_calls = mock_send_slack.call_args_list - assert len(slack_calls) >= 2 # start + success notifications - - start_call = slack_calls[0][0] - assert "Registry Entry Generation_ STARTED" in start_call[1] - - success_calls = [call for call in slack_calls if "SUCCESS" in call[0][1]] - assert len(success_calls) == len(persist_call_args) - - else: - # DISABLED SCENARIO ASSERTIONS - - # Verify NO generation/persistence operations were called - mock_safe_read_gcs_file.assert_not_called() - mock_get_icon_blob.assert_not_called() - mock_persist_entry.assert_not_called() - - if scenario["version_type"] == "latest": - # For latest versions, should check for deletion - mock_gcs_client.assert_called() - expected_latest_path = ( - f"metadata/{scenario['metadata_dict']['data']['dockerRepository']}/latest/{scenario['registry_type']}.json" - ) - mock_bucket.blob.assert_called_with(expected_latest_path) - mock_blob.exists.assert_called_once() - mock_bucket.delete_blob.assert_called_once_with(expected_latest_path) - else: - # For rc/dev versions, no deletion should occur - mock_bucket.delete_blob.assert_not_called() - - # Verify NOOP Slack notification - slack_calls = mock_send_slack.call_args_list - assert len(slack_calls) == 2 # STARTED + NOOP notifications - - # Check STARTED notification - start_call = slack_calls[0][0] - assert "Registry Entry Generation_ STARTED" in start_call[1] - assert scenario["registry_type"] in start_call[1] - - # Check NOOP notification - noop_call = slack_calls[1][0] - assert "Registry Entry Generation_ NOOP" in noop_call[1] - assert scenario["registry_type"] in noop_call[1] - assert "not enabled" in noop_call[1] - - -@pytest.mark.parametrize("registry_type", ["oss", "cloud"]) -@patch("metadata_service.registry_entry.send_slack_message") -def test_invalid_metadata_file_path(mock_send_slack, registry_type): - """Test exception handling when metadata file path doesn't exist or is invalid.""" - - # Arrange - invalid_metadata_path = pathlib.Path("/nonexistent/metadata.yaml") - spec_path = pathlib.Path("/some/spec.json") # This won't be reached - bucket_name = "test-bucket" - - # Act & Assert - with pytest.raises(FileNotFoundError): - generate_and_persist_registry_entry( - bucket_name=bucket_name, - repo_metadata_file_path=invalid_metadata_path, - registry_type=registry_type, - docker_image_tag="irrelevant", - is_prerelease=False, - ) - - -@pytest.mark.parametrize( - "failure_stage,registry_type", - [ - ("gcs_client", "oss"), - ("gcs_client", "cloud"), - ("dependencies_read", "oss"), - ("dependencies_read", "cloud"), - ("icon_blob", "oss"), - ("icon_blob", "cloud"), - ("persist", "oss"), - ("persist", "cloud"), - ], -) -@patch("metadata_service.registry_entry.send_slack_message") -@patch("metadata_service.registry_entry._persist_connector_registry_entry") -@patch("metadata_service.registry_entry._get_icon_blob_from_gcs") -@patch("metadata_service.registry_entry.safe_read_gcs_file") -@patch("metadata_service.registry_entry.get_gcs_storage_client") -def test_gcs_operations_failure( - mock_gcs_client, - mock_safe_read_gcs_file, - mock_get_icon_blob, - mock_persist_entry, - mock_send_slack, - temp_files, - sample_dependencies_dict, - failure_stage, - registry_type, -): - """Test exception handling when various GCS operations fail.""" - # Arrange - metadata_path, spec_path = temp_files - bucket_name = "test-bucket" - - # Mock the failure based on stage - if failure_stage == "gcs_client": - mock_gcs_client.side_effect = Exception("GCS client connection failed") - elif failure_stage == "dependencies_read": - mock_gcs_client.return_value = Mock() - mock_safe_read_gcs_file.side_effect = Exception("Failed to read dependencies") - elif failure_stage == "icon_blob": - mock_gcs_client.return_value = Mock() - mock_safe_read_gcs_file.return_value = json.dumps(sample_dependencies_dict) - mock_get_icon_blob.side_effect = Exception("Failed to get icon blob") - elif failure_stage == "persist": - # Mock successful setup until persistence - mock_storage_client = Mock() - mock_bucket = Mock() - mock_icon_blob = Mock() - - mock_gcs_client.return_value = mock_storage_client - mock_storage_client.bucket.return_value = mock_bucket - mock_bucket.blob.return_value = Mock() - - mock_safe_read_gcs_file.return_value = json.dumps(sample_dependencies_dict) - mock_icon_blob.bucket.name = bucket_name - mock_icon_blob.name = "metadata/airbyte/source-test/latest/icon.svg" - mock_get_icon_blob.return_value = mock_icon_blob - - # Fail at persistence - mock_persist_entry.side_effect = Exception("Failed to persist registry entry") - - # Act & Assert - with pytest.raises(Exception): - generate_and_persist_registry_entry( - bucket_name=bucket_name, - repo_metadata_file_path=metadata_path, - registry_type=registry_type, - docker_image_tag="irrelevant", - is_prerelease=False, - ) - - # Verify error Slack notification was sent for non-client failures - if failure_stage != "gcs_client": - slack_calls = mock_send_slack.call_args_list - error_calls = [call for call in slack_calls if "FAILED" in call[0][1]] - assert len(error_calls) >= 1 - - -@pytest.mark.parametrize("registry_type", ["oss", "cloud"]) -@patch("metadata_service.registry_entry.send_slack_message") -@patch("metadata_service.registry_entry._apply_metadata_overrides") -def test_metadata_override_application_failure(mock_apply_overrides, mock_send_slack, temp_files, registry_type): - """Test exception handling when _apply_metadata_overrides fails.""" - - # Arrange - metadata_path, spec_path = temp_files - bucket_name = "test-bucket" - - # Mock failure during metadata override application - mock_apply_overrides.side_effect = Exception("Failed to apply metadata overrides") - - # Act & Assert - with pytest.raises(Exception): - generate_and_persist_registry_entry( - bucket_name=bucket_name, - repo_metadata_file_path=metadata_path, - registry_type=registry_type, - docker_image_tag="irrelevant", - is_prerelease=False, - ) - - # Verify error Slack notification was sent - slack_calls = mock_send_slack.call_args_list - error_calls = [call for call in slack_calls if "FAILED" in call[0][1]] - assert len(error_calls) >= 1 - - -@pytest.mark.parametrize("registry_type", ["oss", "cloud"]) -@patch("metadata_service.registry_entry.send_slack_message") -@patch("metadata_service.registry_entry._persist_connector_registry_entry") -@patch("metadata_service.registry_entry._get_icon_blob_from_gcs") -@patch("metadata_service.registry_entry.safe_read_gcs_file") -@patch("metadata_service.registry_entry.get_gcs_storage_client") -@patch("metadata_service.registry_entry._get_connector_type_from_registry_entry") -def test_registry_entry_model_parsing_failure( - mock_get_connector_type, - mock_gcs_client, - mock_safe_read_gcs_file, - mock_get_icon_blob, - mock_persist_entry, - mock_send_slack, - temp_files, - sample_dependencies_dict, - registry_type, -): - """Test exception handling when pydantic model parsing fails due to invalid data.""" - - # Arrange - metadata_path, spec_path = temp_files - bucket_name = "test-bucket" - - # Mock successful operations until model parsing - mock_storage_client = Mock() - mock_bucket = Mock() - mock_icon_blob = Mock() - - mock_gcs_client.return_value = mock_storage_client - mock_storage_client.bucket.return_value = mock_bucket - mock_bucket.blob.return_value = Mock() - - mock_safe_read_gcs_file.return_value = json.dumps(sample_dependencies_dict) - mock_icon_blob.bucket.name = bucket_name - mock_icon_blob.name = "metadata/airbyte/source-test/latest/icon.svg" - mock_get_icon_blob.return_value = mock_icon_blob - - # Mock model parsing failure - from metadata_service.models.generated import ConnectorRegistrySourceDefinition - - mock_get_connector_type.return_value = (Mock(), ConnectorRegistrySourceDefinition) - - # Create a mock that fails when parse_obj is called - mock_model_class = Mock() - mock_model_class.parse_obj.side_effect = Exception("Invalid model data") - mock_get_connector_type.return_value = (Mock(), mock_model_class) - - # Act & Assert - with pytest.raises(Exception): - generate_and_persist_registry_entry( - bucket_name=bucket_name, - repo_metadata_file_path=metadata_path, - registry_type=registry_type, - docker_image_tag="irrelevant", - is_prerelease=False, - ) - - -# Re-create the temp_files_disabled fixture since it was removed in refactoring -@pytest.fixture -def temp_files_disabled(sample_spec_dict): - """Create temporary metadata and spec files for disabled registry testing.""" - metadata_dict_disabled = { - "metadataSpecVersion": "1.0", - "data": { - "name": "Test Source Disabled", - "definitionId": "12345678-1234-1234-1234-123456789012", - "connectorType": "source", - "dockerRepository": "airbyte/source-test-disabled", - "dockerImageTag": "1.0.0", - "documentationUrl": "https://docs.airbyte.com/integrations/sources/test-disabled", - "connectorSubtype": "api", - "releaseStage": "beta", - "license": "MIT", - "registryOverrides": {"oss": {"enabled": False}, "cloud": {"enabled": False}}, - "tags": ["language:python"], - }, - } - - with tempfile.TemporaryDirectory() as temp_dir: - # Create metadata file - metadata_path = pathlib.Path(temp_dir) / "metadata.yaml" - with open(metadata_path, "w") as f: - yaml.dump(metadata_dict_disabled, f) - - # Create spec file - spec_path = pathlib.Path(temp_dir) / "spec.json" - with open(spec_path, "w") as f: - json.dump(sample_spec_dict, f) - - yield metadata_path, spec_path - - -# Re-create the temp_files fixture since it was removed in refactoring -@pytest.fixture -def temp_files(sample_spec_dict): - """Create temporary metadata and spec files for testing.""" - metadata_dict = { - "metadataSpecVersion": "1.0", - "data": { - "name": "Test Source", - "definitionId": "12345678-1234-1234-1234-123456789012", - "connectorType": "source", - "dockerRepository": "airbyte/source-test", - "dockerImageTag": "1.0.0", - "documentationUrl": "https://docs.airbyte.com/integrations/sources/test", - "connectorSubtype": "api", - "releaseStage": "beta", - "license": "MIT", - "registryOverrides": {"oss": {"enabled": True}, "cloud": {"enabled": True}}, - "tags": ["language:python"], - }, - } - - with tempfile.TemporaryDirectory() as temp_dir: - # Create metadata file - metadata_path = pathlib.Path(temp_dir) / "metadata.yaml" - with open(metadata_path, "w") as f: - yaml.dump(metadata_dict, f) - - # Create spec file - spec_path = pathlib.Path(temp_dir) / "spec.json" - with open(spec_path, "w") as f: - json.dump(sample_spec_dict, f) - - yield metadata_path, spec_path diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/test_spec_cache.py b/airbyte-ci/connectors/metadata_service/lib/tests/test_spec_cache.py deleted file mode 100644 index eac4bfd2cde2..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/test_spec_cache.py +++ /dev/null @@ -1,102 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from unittest.mock import patch - -import pytest - -from metadata_service.spec_cache import CachedSpec, Registries, SpecCache, get_docker_info_from_spec_cache_path - - -@pytest.fixture -def mock_spec_cache(): - with ( - patch("google.cloud.storage.Client.create_anonymous_client") as MockClient, - patch("google.cloud.storage.Client.bucket") as MockBucket, - ): - # Create stub mock client and bucket - MockClient.return_value - MockBucket.return_value - - # Create a list of 4 test CachedSpecs - test_specs = [ - CachedSpec("image1", "tag-has-override", "path1", Registries.OSS), - CachedSpec("image1", "tag-has-override", "path2", Registries.CLOUD), - CachedSpec("image2", "tag-no-override", "path3", Registries.OSS), - CachedSpec("image3", "tag-no-override", "path4", Registries.CLOUD), - ] - - # Mock get_all_cached_specs to return test_specs - with patch.object(SpecCache, "get_all_cached_specs", return_value=test_specs): - yield SpecCache() - - -@pytest.mark.parametrize( - "image,tag,given_registry,expected_registry", - [ - ("image1", "tag-has-override", "OSS", Registries.OSS), - ("image1", "tag-has-override", "CLOUD", Registries.CLOUD), - ("image2", "tag-no-override", "OSS", Registries.OSS), - ("image2", "tag-no-override", "CLOUD", Registries.OSS), - ("image3", "tag-no-override", "OSS", None), - ("image3", "tag-no-override", "CLOUD", Registries.CLOUD), - ("nonexistent", "tag", "OSS", None), - ("nonexistent", "tag", "CLOUD", None), - ], -) -def test_find_spec_cache_with_fallback(mock_spec_cache, image, tag, given_registry, expected_registry): - spec = mock_spec_cache.find_spec_cache_with_fallback(image, tag, given_registry) - if expected_registry == None: - assert spec == None - else: - assert spec.docker_repository == image - assert spec.docker_image_tag == tag - assert spec.registry == expected_registry - - -@pytest.mark.parametrize( - "spec_cache_path,expected_spec", - [ - ( - "specs/airbyte/destination-azure-blob-storage/0.1.1/spec.json", - CachedSpec( - "airbyte/destination-azure-blob-storage", - "0.1.1", - "specs/airbyte/destination-azure-blob-storage/0.1.1/spec.json", - Registries.OSS, - ), - ), - ( - "specs/airbyte/destination-azure-blob-storage/0.1.1/spec.cloud.json", - CachedSpec( - "airbyte/destination-azure-blob-storage", - "0.1.1", - "specs/airbyte/destination-azure-blob-storage/0.1.1/spec.cloud.json", - Registries.CLOUD, - ), - ), - ( - "specs/airbyte/source-azure-blob-storage/1.1.1/spec.json", - CachedSpec( - "airbyte/source-azure-blob-storage", "1.1.1", "specs/airbyte/source-azure-blob-storage/1.1.1/spec.json", Registries.OSS - ), - ), - ( - "specs/faros/some-name/1.1.1/spec.json", - CachedSpec("faros/some-name", "1.1.1", "specs/faros/some-name/1.1.1/spec.json", Registries.OSS), - ), - ], -) -def test_get_docker_info_from_spec_cache_path(spec_cache_path, expected_spec): - actual_spec = get_docker_info_from_spec_cache_path(spec_cache_path) - - assert actual_spec.docker_repository == expected_spec.docker_repository - assert actual_spec.docker_image_tag == expected_spec.docker_image_tag - assert actual_spec.spec_cache_path == expected_spec.spec_cache_path - assert actual_spec.registry == expected_spec.registry - - -def test_get_docker_info_from_spec_cache_path_invalid(): - with pytest.raises(Exception): - get_docker_info_from_spec_cache_path("specs/airbyte/destination-azure-blob-storage/0.1.1/spec") diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/test_specs_secrets_mask.py b/airbyte-ci/connectors/metadata_service/lib/tests/test_specs_secrets_mask.py deleted file mode 100644 index 9451117ca68e..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/test_specs_secrets_mask.py +++ /dev/null @@ -1,311 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -import json -import os -from unittest.mock import Mock, patch - -import pytest -import yaml -from google.cloud import storage - -from metadata_service.constants import REGISTRIES_FOLDER, SPECS_SECRETS_MASK_FILE_NAME, VALID_REGISTRIES -from metadata_service.models.generated import ConnectorRegistryV0 -from metadata_service.registry import PolymorphicRegistryEntry -from metadata_service.specs_secrets_mask import _get_registries_from_gcs, _get_specs_secrets_from_registry_entries, _persist_secrets_to_gcs - - -class TestGetRegistriesFromGcs: - """Tests for _get_registries_from_gcs function.""" - - @pytest.fixture - def mock_bucket(self): - """Create a mock GCS bucket.""" - return Mock(spec=storage.Bucket) - - @pytest.fixture - def valid_registry_data(self): - """Sample valid registry data.""" - return { - "sources": [], - "destinations": [], - } - - @pytest.fixture - def mock_blob(self): - """Create a mock GCS blob.""" - return Mock(spec=storage.Blob) - - def test_get_registries_from_gcs_success(self, mock_bucket, mock_blob, valid_registry_data): - """Test successful retrieval of all valid registries from GCS.""" - mock_bucket.blob.return_value = mock_blob - - with ( - patch("metadata_service.specs_secrets_mask.safe_read_gcs_file") as mock_safe_read, - patch("metadata_service.specs_secrets_mask.ConnectorRegistryV0.parse_obj") as mock_parse, - ): - mock_safe_read.return_value = json.dumps(valid_registry_data) - mock_registry = Mock(spec=ConnectorRegistryV0) - mock_parse.return_value = mock_registry - - result = _get_registries_from_gcs(mock_bucket) - - assert len(result) == len(VALID_REGISTRIES) - assert all(registry == mock_registry for registry in result) - - expected_calls = [f"{REGISTRIES_FOLDER}/{registry}_registry.json" for registry in VALID_REGISTRIES] - actual_calls = [call[0][0] for call in mock_bucket.blob.call_args_list] - assert actual_calls == expected_calls - - assert mock_safe_read.call_count == len(VALID_REGISTRIES) - - def test_get_registries_from_gcs_multiple_registries(self, mock_bucket, mock_blob, valid_registry_data): - """Test that the function correctly processes all registries in VALID_REGISTRIES.""" - mock_bucket.blob.return_value = mock_blob - - with ( - patch("metadata_service.specs_secrets_mask.safe_read_gcs_file") as mock_safe_read, - patch("metadata_service.specs_secrets_mask.ConnectorRegistryV0.parse_obj") as mock_parse, - ): - mock_safe_read.return_value = json.dumps(valid_registry_data) - mock_registry = Mock(spec=ConnectorRegistryV0) - mock_parse.return_value = mock_registry - - result = _get_registries_from_gcs(mock_bucket) - - assert len(result) == 2 - assert mock_parse.call_count == 2 - assert mock_safe_read.call_count == 2 - - -class TestGetSpecsSecretsFromRegistryEntries: - """Tests for _get_specs_secrets_from_registry_entries function.""" - - @pytest.fixture - def mock_registry_entry(self): - """Create a mock registry entry.""" - return Mock(spec=PolymorphicRegistryEntry) - - @pytest.fixture - def single_secret_entry_data(self): - """Sample entry data with a single secret property.""" - return { - "spec": { - "connectionSpecification": { - "properties": { - "password": {"type": "string", "airbyte_secret": True}, - "username": {"type": "string", "airbyte_secret": False}, - } - } - } - } - - @pytest.fixture - def multiple_secrets_entry_data(self): - """Sample entry data with multiple secret properties.""" - return { - "spec": { - "connectionSpecification": { - "properties": { - "password": {"type": "string", "airbyte_secret": True}, - "api_key": {"type": "string", "airbyte_secret": True}, - "username": {"type": "string", "airbyte_secret": False}, - } - } - } - } - - @pytest.fixture - def nested_secrets_entry_data(self): - """Sample entry data with nested secret properties.""" - return { - "spec": { - "connectionSpecification": { - "properties": { - "oauth": { - "type": "object", - "properties": { - "client_secret": {"type": "string", "airbyte_secret": True}, - "client_id": {"type": "string", "airbyte_secret": False}, - }, - }, - "username": {"type": "string", "airbyte_secret": False}, - } - } - } - } - - @pytest.fixture - def deeply_nested_secrets_entry_data(self): - """Sample entry data with deeply nested secret properties.""" - return { - "spec": { - "connectionSpecification": { - "properties": { - "connection": { - "type": "object", - "properties": { - "auth": { - "type": "object", - "properties": { - "credentials": { - "type": "object", - "properties": {"secret_token": {"type": "string", "airbyte_secret": True}}, - } - }, - } - }, - } - } - } - } - } - - @pytest.fixture - def no_secrets_entry_data(self): - """Sample entry data with no secret properties.""" - return { - "spec": { - "connectionSpecification": { - "properties": {"username": {"type": "string", "airbyte_secret": False}, "host": {"type": "string"}} - } - } - } - - @pytest.mark.parametrize( - "entry_data_fixture,expected_secrets,description", - [ - ("single_secret_entry_data", {"password"}, "single secret property"), - ("multiple_secrets_entry_data", {"password", "api_key"}, "multiple secret properties"), - ("nested_secrets_entry_data", {"client_secret"}, "nested secret property"), - ("deeply_nested_secrets_entry_data", {"secret_token"}, "deeply nested secret property"), - ("no_secrets_entry_data", set(), "no secret properties"), - ], - ) - def test_get_specs_secrets_valid_structures(self, mock_registry_entry, entry_data_fixture, expected_secrets, description, request): - """Test extraction from various valid entry structures.""" - entry_data = request.getfixturevalue(entry_data_fixture) - - with patch("metadata_service.specs_secrets_mask.to_json_sanitized_dict") as mock_sanitize: - mock_sanitize.return_value = entry_data - - result = _get_specs_secrets_from_registry_entries([mock_registry_entry]) - - assert result == expected_secrets, f"Failed for {description}" - mock_sanitize.assert_called_once_with(mock_registry_entry) - - def test_get_specs_secrets_multiple_entries_aggregation(self, mock_registry_entry, single_secret_entry_data, nested_secrets_entry_data): - """Test that secrets from multiple entries are properly aggregated.""" - entry1 = Mock(spec=PolymorphicRegistryEntry) - entry2 = Mock(spec=PolymorphicRegistryEntry) - - with patch("metadata_service.specs_secrets_mask.to_json_sanitized_dict") as mock_sanitize: - mock_sanitize.side_effect = [single_secret_entry_data, nested_secrets_entry_data] - - result = _get_specs_secrets_from_registry_entries([entry1, entry2]) - - assert result == {"password", "client_secret"} - assert mock_sanitize.call_count == 2 - - def test_get_specs_secrets_duplicate_secrets_handling(self, single_secret_entry_data): - """Test that duplicate secret names from different entries are handled correctly.""" - entry1 = Mock(spec=PolymorphicRegistryEntry) - entry2 = Mock(spec=PolymorphicRegistryEntry) - - with patch("metadata_service.specs_secrets_mask.to_json_sanitized_dict") as mock_sanitize: - mock_sanitize.return_value = single_secret_entry_data - - result = _get_specs_secrets_from_registry_entries([entry1, entry2]) - - assert result == {"password"} - assert mock_sanitize.call_count == 2 - - def test_get_specs_secrets_empty_entries_list(self): - """Test behavior with empty entries list.""" - result = _get_specs_secrets_from_registry_entries([]) - - assert result == set() - - def test_get_specs_secrets_complex_real_world_structure(self, mock_registry_entry): - """Test with realistic connector specification structure.""" - complex_entry_data = { - "spec": { - "connectionSpecification": { - "properties": { - "host": {"type": "string"}, - "port": {"type": "integer"}, - "database": {"type": "string"}, - "credentials": { - "type": "object", - "oneOf": [ - { - "properties": { - "auth_type": {"type": "string", "const": "username_password"}, - "username": {"type": "string"}, - "password": {"type": "string", "airbyte_secret": True}, - } - }, - { - "properties": { - "auth_type": {"type": "string", "const": "oauth2"}, - "client_id": {"type": "string"}, - "client_secret": {"type": "string", "airbyte_secret": True}, - "refresh_token": {"type": "string", "airbyte_secret": True}, - } - }, - ], - }, - "ssl_config": { - "type": "object", - "properties": {"ssl_mode": {"type": "string"}, "client_key": {"type": "string", "airbyte_secret": True}}, - }, - } - } - } - } - - with patch("metadata_service.specs_secrets_mask.to_json_sanitized_dict") as mock_sanitize: - mock_sanitize.return_value = complex_entry_data - - result = _get_specs_secrets_from_registry_entries([mock_registry_entry]) - - expected_secrets = {"password", "client_secret", "refresh_token", "client_key"} - assert result == expected_secrets - - -class TestPersistSecretsToGcs: - """Tests for _persist_secrets_to_gcs function.""" - - @pytest.fixture - def mock_bucket(self): - """Create a mock GCS bucket.""" - return Mock(spec=storage.Bucket) - - @pytest.fixture - def mock_blob(self): - """Create a mock GCS blob.""" - mock_blob = Mock() - mock_blob.name = f"{REGISTRIES_FOLDER}/{SPECS_SECRETS_MASK_FILE_NAME}" - return mock_blob - - @pytest.mark.parametrize( - "secrets_set,expected_yaml_content,description", - [ - (set(), {"properties": []}, "empty secrets set"), - ({"password"}, {"properties": ["password"]}, "single secret"), - ({"password", "api_key", "token"}, {"properties": ["api_key", "password", "token"]}, "multiple secrets sorted"), - ({"z_secret", "a_secret", "m_secret"}, {"properties": ["a_secret", "m_secret", "z_secret"]}, "secrets sorted alphabetically"), - ], - ) - def test_persist_secrets_to_gcs_various_secret_sets(self, mock_bucket, mock_blob, secrets_set, expected_yaml_content, description): - """Test persistence with different secret set sizes and contents.""" - mock_bucket.blob.return_value = mock_blob - - _persist_secrets_to_gcs(secrets_set, mock_bucket) - - mock_bucket.blob.assert_called_once_with(f"{REGISTRIES_FOLDER}/{SPECS_SECRETS_MASK_FILE_NAME}") - mock_blob.upload_from_string.assert_called_once() - uploaded_content = mock_blob.upload_from_string.call_args[0][0] - parsed_yaml = yaml.safe_load(uploaded_content) - assert parsed_yaml == expected_yaml_content, f"Failed for {description}" diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/test_stale_metadata_report.py b/airbyte-ci/connectors/metadata_service/lib/tests/test_stale_metadata_report.py deleted file mode 100644 index c5e294dafd53..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/test_stale_metadata_report.py +++ /dev/null @@ -1,238 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -import datetime -from unittest.mock import Mock, patch - -import pytest -import yaml as real_yaml - -from metadata_service.constants import PUBLISH_GRACE_PERIOD -from metadata_service.stale_metadata_report import ( - _generate_stale_metadata_report, - _get_latest_metadata_entries_on_gcs, - _get_latest_metadata_versions_on_github, - _is_younger_than_grace_period, - generate_and_publish_stale_metadata_report, -) - -pytest_plugins = ["tests.fixtures.stale_metadata_report_fixtures"] - - -def _mock_commits(old_datetime): - commit = Mock() - commit.commit = Mock() - commit.commit.author = Mock() - commit.commit.author.date = old_datetime - return [commit] - - -def mock_get(url, yaml_responses): - mock_response = Mock() - mock_response.text = yaml_responses[url] - mock_response.raise_for_status = Mock() - return mock_response - - -def mock_safe_load(yaml_text: str): - return real_yaml.safe_load(yaml_text) - - -@pytest.mark.parametrize( - "hours_offset,expected_result", - [ - (-1, False), - (0, False), - (1, True), - ], -) -def test_is_younger_than_grace_period_parameterized(hours_offset, expected_result): - """Test _is_younger_than_grace_period with different time offsets relative to grace period.""" - grace_period_marker = datetime.datetime.now(datetime.timezone.utc) - PUBLISH_GRACE_PERIOD - test_datetime = grace_period_marker + datetime.timedelta(hours=hours_offset) - - mock_last_modified_at_date_time = test_datetime - - result = _is_younger_than_grace_period(mock_last_modified_at_date_time) - assert result == expected_result - - -@pytest.mark.parametrize( - "github_versions,gcs_versions,expected_stale_count,description", - [ - ({}, {}, 0, "empty mappings"), - ({"connector-a": "1.0.0"}, {"connector-a": "1.0.0"}, 0, "identical versions"), - ({"connector-a": "1.1.0"}, {"connector-a": "1.0.0"}, 1, "github newer than gcs"), - ({"connector-a": "1.0.0"}, {}, 1, "missing from gcs"), - ({}, {"connector-a": "1.0.0"}, 0, "missing from github - not reported"), - ({"connector-a": "1.1.0", "connector-b": "2.0.0"}, {"connector-a": "1.0.0", "connector-b": "2.0.0"}, 1, "mixed scenarios"), - ], -) -def test_generate_stale_metadata_report_parameterized(github_versions, gcs_versions, expected_stale_count, description): - """Test _generate_stale_metadata_report with different version mapping scenarios.""" - result_df = _generate_stale_metadata_report(github_versions, gcs_versions) - - assert len(result_df) == expected_stale_count, f"Failed for {description}" - - if expected_stale_count > 0: - expected_columns = ["connector", "master_version", "gcs_version"] - assert list(result_df.columns) == expected_columns, f"Incorrect columns for {description}" - - for _, row in result_df.iterrows(): - connector = row["connector"] - github_version = row["master_version"] - gcs_version = row["gcs_version"] - - assert connector in github_versions, f"Connector {connector} not in GitHub versions" - assert github_versions[connector] == github_version, f"GitHub version mismatch for {connector}" - assert github_version != gcs_version, f"Versions should be different for stale connector {connector}" - - -def test_get_latest_metadata_versions_on_github_success(mock_github_files, mock_yaml_responses): - """Test _get_latest_metadata_versions_on_github successfully retrieves and filters metadata.""" - with ( - patch("os.getenv") as mock_getenv, - patch("metadata_service.stale_metadata_report.Auth") as mock_auth, - patch("metadata_service.stale_metadata_report.Github") as mock_github, - patch("metadata_service.stale_metadata_report.requests") as mock_requests, - patch("metadata_service.stale_metadata_report.yaml") as mock_yaml, - ): - mock_getenv.return_value = "test-github-token" - mock_auth.Token.return_value = Mock() - - mock_github_client = Mock() - mock_repo = Mock() - mock_github.return_value = mock_github_client - mock_github_client.get_repo.return_value = mock_repo - - # Configure search_code to return our mock file list - mock_github_client.search_code.return_value = mock_github_files - - # Each call to repo.get_commits(path=...) should return a commit list with an old datetime - old_datetime = datetime.datetime.now(datetime.timezone.utc) - PUBLISH_GRACE_PERIOD - datetime.timedelta(hours=1) - - mock_repo.full_name = "airbyte/airbyte" - mock_repo.get_commits.side_effect = lambda path: _mock_commits(old_datetime) - - mock_requests.get.side_effect = lambda url: mock_get(url, mock_yaml_responses) - - mock_yaml.safe_load = mock_safe_load - - result = _get_latest_metadata_versions_on_github() - - expected_result = {"airbyte/source-test-1": "1.0.0"} - - assert result == expected_result - mock_getenv.assert_called_once_with("GITHUB_TOKEN") - mock_github_client.get_repo.assert_called_once() - mock_github_client.search_code.assert_called_once() - assert mock_requests.get.call_count == 3 - - -def test_get_latest_metadata_entries_on_gcs_success(mock_gcs_blobs): - """Test _get_latest_metadata_entries_on_gcs successfully retrieves metadata from GCS.""" - with ( - patch("metadata_service.stale_metadata_report.get_gcs_storage_client") as mock_get_client, - patch("metadata_service.stale_metadata_report.yaml") as mock_yaml, - ): - mock_storage_client = Mock() - mock_bucket = Mock() - mock_get_client.return_value = mock_storage_client - mock_storage_client.bucket.return_value = mock_bucket - mock_bucket.list_blobs.return_value = mock_gcs_blobs - - mock_yaml.safe_load = mock_safe_load - - result = _get_latest_metadata_entries_on_gcs("test-bucket") - - expected_result = {"airbyte/source-gcs-1": "1.2.0", "airbyte/source-gcs-2": "2.1.0", "airbyte/destination-gcs-1": "3.0.0"} - - assert result == expected_result - mock_get_client.assert_called_once() - mock_storage_client.bucket.assert_called_once_with("test-bucket") - mock_bucket.list_blobs.assert_called_once() - assert all(blob.download_as_bytes.called for blob in mock_gcs_blobs) - - -def test_generate_and_publish_stale_metadata_report_with_stale_data(): - """Test main workflow when stale metadata is detected.""" - with ( - patch("metadata_service.stale_metadata_report.STALE_REPORT_CHANNEL", "123456789"), - patch("metadata_service.stale_metadata_report.PUBLISH_UPDATE_CHANNEL", "987654321"), - patch("metadata_service.stale_metadata_report._get_latest_metadata_versions_on_github") as mock_github, - patch("metadata_service.stale_metadata_report._get_latest_metadata_entries_on_gcs") as mock_gcs, - patch("metadata_service.stale_metadata_report.send_slack_message", return_value=(True, None)) as mock_slack, - patch("pandas.DataFrame.to_markdown") as mock_to_markdown, - ): - mock_github.return_value = {"connector-a": "2.0.0", "connector-b": "1.5.0"} - mock_gcs.return_value = {"connector-a": "1.0.0", "connector-b": "1.5.0"} - mock_to_markdown.return_value = ( - "| connector | master_version | gcs_version |\n|-----------|----------------|-------------|\n| connector-a | 2.0.0 | 1.0.0 |" - ) - - result = generate_and_publish_stale_metadata_report("test-bucket") - - assert result == (True, None) - assert mock_slack.call_count == 2 - - alert_call = mock_slack.call_args_list[0] - assert "123456789" in str(alert_call) - assert "Stale metadata detected" in alert_call[0][1] - - report_call = mock_slack.call_args_list[1] - assert "123456789" in str(report_call) - assert report_call[1]["enable_code_block_wrapping"] is True - - -def test_generate_and_publish_stale_metadata_report_no_stale_data(): - """Test main workflow when no stale metadata is detected.""" - with ( - patch("metadata_service.stale_metadata_report.STALE_REPORT_CHANNEL", "123456789"), - patch("metadata_service.stale_metadata_report.PUBLISH_UPDATE_CHANNEL", "987654321"), - patch("metadata_service.stale_metadata_report._get_latest_metadata_versions_on_github") as mock_github, - patch("metadata_service.stale_metadata_report._get_latest_metadata_entries_on_gcs") as mock_gcs, - patch("metadata_service.stale_metadata_report.send_slack_message", return_value=(True, None)) as mock_slack, - ): - mock_github.return_value = {"connector-a": "1.0.0", "connector-b": "1.5.0"} - mock_gcs.return_value = {"connector-a": "1.0.0", "connector-b": "1.5.0"} - - result = generate_and_publish_stale_metadata_report("test-bucket") - - assert result == (True, None) - mock_slack.assert_called_once() - - success_call = mock_slack.call_args_list[0] - assert "987654321" in str(success_call) - assert "No stale metadata" in success_call[0][1] - - -def test_generate_and_publish_stale_metadata_report_large_stale_report(): - """Test main workflow with a large number of stale connectors.""" - large_github_data = {f"airbyte/connector-{i:04d}": f"2.{i % 10}.0" for i in range(100)} - large_gcs_data = {f"airbyte/connector-{i:04d}": f"1.{i % 10}.0" for i in range(100)} - - with ( - patch("metadata_service.stale_metadata_report._get_latest_metadata_versions_on_github") as mock_github, - patch("metadata_service.stale_metadata_report._get_latest_metadata_entries_on_gcs") as mock_gcs, - patch("metadata_service.stale_metadata_report.send_slack_message", return_value=(True, None)) as mock_slack, - patch("pandas.DataFrame.to_markdown") as mock_to_markdown, - patch("metadata_service.stale_metadata_report.STALE_REPORT_CHANNEL", "123456789"), - patch("metadata_service.stale_metadata_report.PUBLISH_UPDATE_CHANNEL", "987654321"), - ): - mock_github.return_value = large_github_data - mock_gcs.return_value = large_gcs_data - mock_to_markdown.return_value = "Large markdown table with 100 stale connectors..." - - result = generate_and_publish_stale_metadata_report("test-bucket") - - assert result == (True, None) - assert mock_slack.call_count == 2 - - alert_call = mock_slack.call_args_list[0] - assert "123456789" in str(alert_call) - assert "Stale metadata detected" in alert_call[0][1] - - report_call = mock_slack.call_args_list[1] - assert "123456789" in str(report_call) - assert report_call[1]["enable_code_block_wrapping"] is True diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/test_transform.py b/airbyte-ci/connectors/metadata_service/lib/tests/test_transform.py deleted file mode 100644 index 47d056808104..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/test_transform.py +++ /dev/null @@ -1,89 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import pathlib - -import yaml - -from metadata_service.models import transform -from metadata_service.models.generated.ConnectorMetadataDefinitionV0 import ConnectorMetadataDefinitionV0 - - -def get_all_dict_key_paths(dict_to_traverse, key_path=""): - """Get all paths to keys in a dict. - - Args: - dict_to_traverse (dict): A dict. - - Returns: - list: List of paths to keys in the dict. e.g ["data.name", "data.version", "data.meta.url""] - """ - if not isinstance(dict_to_traverse, dict): - return [key_path] - - key_paths = [] - for key, value in dict_to_traverse.items(): - new_key_path = f"{key_path}.{key}" if key_path else key - key_paths += get_all_dict_key_paths(value, new_key_path) - - return key_paths - - -def have_same_keys(dict1, dict2, omitted_keys=None): - """Check if two dicts have the same keys, ignoring specified keys in the second dict. - - Args: - dict1 (dict): A dict. - dict2 (dict): A dict. - omitted_keys (list, optional): List of keys to ignore in dict2. - - Returns: - tuple: (bool, list) - True if the dicts have the same keys (considering omissions), - and a list of keys that are different or omitted. - """ - if omitted_keys is None: - omitted_keys = [] - - keys1 = set(get_all_dict_key_paths(dict1)) - keys2 = set(get_all_dict_key_paths(dict2)) - - # Determine the difference in keys - different_keys = list(keys1.symmetric_difference(keys2)) - - # Remove omitted keys - different_keys = [key for key in different_keys if key not in omitted_keys] - - return len(different_keys) == 0, different_keys - - -def test_transform_to_json_does_not_mutate_keys(valid_metadata_upload_files, valid_metadata_yaml_files): - all_valid_metadata_files = valid_metadata_upload_files + valid_metadata_yaml_files - - fields_with_defaults = [ - "data.supportsRefreshes", - "data.supportsFileTransfer", - "data.supportsDataActivation", - "data.releases.rolloutConfiguration.enableProgressiveRollout", - "data.releases.rolloutConfiguration.initialPercentage", - "data.releases.rolloutConfiguration.maxPercentage", - "data.releases.rolloutConfiguration.advanceDelayMinutes", - "data.releases.breakingChanges.2.0.0.deadlineAction", - "data.ab_internal.isEnterprise", - "data.ab_internal.requireVersionIncrementsInPullRequests", - ] - - for file_path in all_valid_metadata_files: - metadata_file_path = pathlib.Path(file_path) - original_yaml_text = metadata_file_path.read_text() - - metadata_yaml_dict = yaml.safe_load(original_yaml_text) - metadata = ConnectorMetadataDefinitionV0.parse_obj(metadata_yaml_dict) - metadata_json_dict = transform.to_json_sanitized_dict(metadata) - - new_yaml_text = yaml.safe_dump(metadata_json_dict, sort_keys=False) - new_yaml_dict = yaml.safe_load(new_yaml_text) - - # assert same keys in both dicts, deep compare, and that the values are the same - is_same, different_keys = have_same_keys(metadata_yaml_dict, new_yaml_dict, fields_with_defaults) - assert is_same, f"Different keys found: {different_keys}" diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/test_validators/__init__.py b/airbyte-ci/connectors/metadata_service/lib/tests/test_validators/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/airbyte-ci/connectors/metadata_service/lib/tests/test_validators/test_metadata_validators.py b/airbyte-ci/connectors/metadata_service/lib/tests/test_validators/test_metadata_validators.py deleted file mode 100644 index 29c686def430..000000000000 --- a/airbyte-ci/connectors/metadata_service/lib/tests/test_validators/test_metadata_validators.py +++ /dev/null @@ -1,158 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -import pytest -import requests -import semver -import yaml - -from metadata_service.docker_hub import get_latest_version_on_dockerhub -from metadata_service.models.generated.ConnectorMetadataDefinitionV0 import ConnectorMetadataDefinitionV0 -from metadata_service.validators import metadata_validator - - -@pytest.fixture -def metadata_definition(): - return ConnectorMetadataDefinitionV0.parse_obj( - { - "data": { - "ab_internal": {"ql": 300, "sl": 100}, - "allowedHosts": {"hosts": []}, - "connectorBuildOptions": { - "baseImage": "docker.io/airbyte/python-connector-base:2.0.0@sha256:c44839ba84406116e8ba68722a0f30e8f6e7056c726f447681bb9e9ece8bd916" - }, - "connectorSubtype": "api", - "connectorType": "source", - "definitionId": "dfd88b22-b603-4c3d-aad7-3701784586b1", - "dockerImageTag": "6.2.18-rc.1", - "dockerRepository": "airbyte/source-faker", - "documentationUrl": "https://docs.airbyte.com/integrations/sources/faker", - "githubIssueLabel": "source-faker", - "icon": "faker.svg", - "license": "MIT", - "name": "Sample Data (Faker)", - "registryOverrides": {"cloud": {"enabled": True}, "oss": {"enabled": True}}, - "releaseStage": "beta", - "releases": { - "rolloutConfiguration": {"enableProgressiveRollout": True}, - "breakingChanges": { - "4.0.0": {"message": "This is a breaking change message", "upgradeDeadline": "2023-07-19"}, - "5.0.0": { - "message": "ID and products.year fields are changing to be integers instead of floats.", - "upgradeDeadline": "2023-08-31", - }, - "6.0.0": {"message": "Declare 'id' columns as primary keys.", "upgradeDeadline": "2024-04-01"}, - }, - }, - "remoteRegistries": {"pypi": {"enabled": True, "packageName": "airbyte-source-faker"}}, - "resourceRequirements": { - "jobSpecific": [{"jobType": "sync", "resourceRequirements": {"cpu_limit": "4.0", "cpu_request": "1.0"}}] - }, - "suggestedStreams": {"streams": ["users", "products", "purchases"]}, - "supportLevel": "community", - "tags": ["language:python", "cdk:python"], - "connectorTestSuitesOptions": [ - { - "suite": "liveTests", - "testConnections": [{"name": "faker_config_dev_null", "id": "73abc3a9-3fea-4e7c-b58d-2c8236464a95"}], - }, - {"suite": "unitTests"}, - { - "suite": "acceptanceTests", - "testSecrets": [ - { - "name": "SECRET_SOURCE-FAKER_CREDS", - "fileName": "config.json", - "secretStore": {"type": "GSM", "alias": "airbyte-connector-testing-secret-store"}, - } - ], - }, - ], - }, - "metadataSpecVersion": "1.0", - } - ) - - -@pytest.mark.slow -@pytest.mark.parametrize( - "latest_version, current_version,should_pass_validation", - [("1.0.0", "0.1.0", False), ("1.0.0", "1.0.0", True), ("1.0.0", "1.1.0", True)], -) -def test_validate_docker_image_tag_is_not_decremented(mocker, metadata_definition, latest_version, current_version, should_pass_validation): - mocker.patch.object(metadata_validator, "get_latest_version_on_dockerhub", return_value=latest_version) - metadata_definition.data.dockerImageTag = current_version - passed_validation, _ = metadata_validator.validate_docker_image_tag_is_not_decremented(metadata_definition, None) - assert passed_validation == should_pass_validation - - -@pytest.fixture -def current_version(metadata_definition): - return metadata_definition.data.dockerImageTag - - -@pytest.fixture -def decremented_version(current_version): - version_info = semver.VersionInfo.parse(current_version) - if version_info.major > 0: - patched_version_info = version_info.replace(major=version_info.major - 1) - elif version_info.minor > 0: - patched_version_info = version_info.replace(major=version_info.minor - 1) - elif version_info.patch > 0: - patched_version_info = version_info.replace(patch=version_info.patch - 1) - else: - raise ValueError(f"Version {version_info} can't be decremented to prepare our test") - return str(patched_version_info) - - -@pytest.fixture -def incremented_version(current_version): - version_info = semver.VersionInfo.parse(current_version) - if version_info.major > 0: - patched_version_info = version_info.replace(major=version_info.major + 1) - elif version_info.minor > 0: - patched_version_info = version_info.replace(major=version_info.minor + 1) - elif version_info.patch > 0: - patched_version_info = version_info.replace(patch=version_info.patch + 1) - else: - raise ValueError(f"Version {version_info} can't be incremented to prepare our test") - return str(patched_version_info) - - -@pytest.mark.slow -def test_validation_fail_on_docker_image_tag_decrement(metadata_definition, decremented_version): - current_version = metadata_definition.data.dockerImageTag - - metadata_definition.data.dockerImageTag = decremented_version - success, error_message = metadata_validator.validate_docker_image_tag_is_not_decremented(metadata_definition, None) - assert not success - expected_prefix = f"The dockerImageTag value ({decremented_version}) can't be decremented: it should be equal to or above" - assert error_message.startswith(expected_prefix), error_message - - -@pytest.mark.slow -def test_validation_pass_on_docker_image_tag_increment(metadata_definition, incremented_version): - metadata_definition.data.dockerImageTag = incremented_version - success, error_message = metadata_validator.validate_docker_image_tag_is_not_decremented(metadata_definition, None) - assert success - assert error_message is None - - -@pytest.mark.slow -def test_validation_pass_on_same_docker_image_tag(mocker, metadata_definition): - mocker.patch.object(metadata_validator, "get_latest_version_on_dockerhub", return_value=metadata_definition.data.dockerImageTag) - success, error_message = metadata_validator.validate_docker_image_tag_is_not_decremented(metadata_definition, None) - assert success - assert error_message is None - - -@pytest.mark.slow -def test_validation_pass_on_docker_image_no_latest(capsys, metadata_definition): - metadata_definition.data.dockerRepository = "airbyte/unreleased" - success, error_message = metadata_validator.validate_docker_image_tag_is_not_decremented(metadata_definition, None) - captured = capsys.readouterr() - assert ( - "https://registry.hub.docker.com/v2/repositories/airbyte/unreleased/tags returned a 404. The connector might not be released yet." - in captured.out - ) - assert success - assert error_message is None diff --git a/airbyte-ci/connectors/pipelines/.gitignore b/airbyte-ci/connectors/pipelines/.gitignore deleted file mode 100644 index d17bbbefa193..000000000000 --- a/airbyte-ci/connectors/pipelines/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -pipeline_reports -.venv diff --git a/airbyte-ci/connectors/pipelines/CONTRIBUTING.md b/airbyte-ci/connectors/pipelines/CONTRIBUTING.md deleted file mode 100644 index 5b0549ca0d85..000000000000 --- a/airbyte-ci/connectors/pipelines/CONTRIBUTING.md +++ /dev/null @@ -1,366 +0,0 @@ -## What is `airbyte-ci`? - -`airbyte-ci` is a CLI written as a python package which is made to execute CI operations on the `airbyte` repo. It is heavily using the [Dagger](https://dagger.cloud/) library to build and orchestrate Docker containers programatically. It enables a centralized and programmatic approach at executing CI logics which can seamlessly run both locally and in remote CI environments. - -You can read more why we are using Dagger and the benefit it has provided in this [blog post](https://dagger.io/blog/airbyte-use-case) - -## When is a contribution to `airbyte-ci` a good fit for your use case? - -- When you want to make global changes to connectors artifacts and build logic. -- When you want to execute something made to run both in CI or for local development. As airbyte-ci logic relies on container orchestration you can have reproducible environment and execution both locally and in a remote CI environment. -- When you want to orchestrate the tests and release of an internal package in CI. - -## Who can I ask help from? - -The tool has been maintained by multiple Airbyters. -Our top contributors who can help you figuring the best approach to implement your use case are: - -- [@alafanechere](https://github.com/alafanechere). -- [@postamar](https://github.com/postamar) -- [@erohmensing](https://github.com/erohmensing) -- [@bnchrch](https://github.com/bnchrch) -- [@stephane-airbyte](https://github.com/stephane-airbyte) - -## Where is the code? - -The code is currently available in the `airbytehq/airbyte` repo under [ `airbyte-ci/connectors/pipelines` ](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines) - -## What use cases it currently supports - -According to your need you might want to introduce a new logic to an existing flow or create a new one. -Here are the currently supported use cases. Feel free to grab them as example if you want to craft a new flow, or modify an existing one. If you are not sure about which direction to take feel free to ask advices (see [*Who Can I ask help?*](## Who can I ask help from?) from section). - -| Command group | Feature | Command | Entrypoint path | -| ------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [`connectors`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/commands.py#L237) | Running test suites connectors | `airbyte-ci connectors test` | [`airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/commands.py`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/commands.py) | -| [`connectors`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/commands.py#L237) | Building connectors | `airbyte-ci connectors build` | [`airbyte-ci/connectors/pipelines/airbyte_ci/connectors/build_image/commands.py`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/commands.py) | -| [`connectors`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/commands.py#L237) | Publishing connectors | `airbyte-ci connectors publish` | [`airbyte-ci/connectors/pipelines/airbyte_ci/connectors/publish/commands.py`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/commands.py) | -| [`connectors`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/commands.py#L237) | Bumping connectors versions | `airbyte-ci connectors bump_version` | [`airbyte-ci/connectors/pipelines/airbyte_ci/connectors/bump_version/commands.py`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/commands.py) | -| [`connectors`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/commands.py#L237) | Listing connectors | `airbyte-ci connectors list` | [`airbyte-ci/connectors/pipelines/airbyte_ci/connectors/list/commands.py`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/list/commands.py) | -| [`connectors`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/commands.py#L237) | Migrate a connector to use our base image | `airbyte-ci connectors migrate_to_base_image` | [`airbyte-ci/connectors/pipelines/airbyte_ci/connectors/migrate_to_base_image/commands.py`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_base_image/commands.py) | -| [`connectors`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/commands.py#L237) | Migrate a connector to use `poetry` as a package manager | `airbyte-ci connectors migrate_to_poetry` | [`airbyte-ci/connectors/pipelines/airbyte_ci/connectors/migrate_to_poetry/commands.py`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_poetry/commands.py) | -| [`connectors`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/commands.py#L237) | Upgrade the base image used by a connector | `airbyte-ci connectors upgrade_base_image` | [`airbyte-ci/connectors/pipelines/airbyte_ci/connectors/upgrade_base_image/commands.py`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_base_image/commands.py) | -| [`connectors`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/commands.py#L237) | Upgrade the CDK version used by a connector | `airbyte-ci connectors upgrade_cdk` | [`airbyte-ci/connectors/pipelines/airbyte_ci/connectors/upgrade_cdk/commands.py`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/commands.py) | -| [`format`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/format/commands.py#L32) | Check that the full repo is correctly formatted | `airbyte-ci format check all` | [`airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/format/commands.py`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/format/commands.py#L78) | -| [`format`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/format/commands.py#L32) | Format the whole repo | `airbyte-ci format fix all` | [`airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/format/commands.py`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/format/commands.py#L101) | -| [`test`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/commands.py#L107) | Run tests on internal poetry packages | `airbyte-ci test` | [`airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/commands.py`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/commands.py#L107) | -| [`poetry`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/commands.py#L33) | Publish a poetry package to PyPi | `airbyte-ci poetry publish` | [`airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/publish/commands.py`](https:github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/publish/commands.py#L69) | - -## How to install the package for development - -There are multiple way to have dev install of the tool. Feel free to grab the one you prefer / which works for you. -**Please note that all the install mode lead to an editable install. There's no need to re-install the tool following a code change**. - -### System requirements - -- `Python` > 3.10 -- [`Poetry`](https://python-poetry.org/) or [`pipx`](https://github.com/pypa/pipx) - -### Installation options - -There are many ways to install Python tools / packages. - -For most users we recommend you use `make` but `pipx` and `poetry` are also viable options - -#### With `make` - -```bash - # From airbyte repo root: - make tools.airbyte-ci-dev.install -``` - -#### With `pipx` - -```bash -# From airbyte-ci/connectors/pipelines: -pipx install --editable --force . -``` - -#### With `poetry` - -⚠️ This places you in a python environment specific to airbyte-ci. This can be a problem if you are developing airbyte-ci and testing/using your changes in another python project. - -```bash -# From airbyte-ci/connectors/pipelines -poetry install -poetry shell -``` - -## Main libraries used in the tool - -### [Click](https://click.palletsprojects.com/en/8.1.x/) - -This is a python light CLI framework we use to declare entrypoint. You'll interact with it if you have to deal with commands, command groups, option, arguments etc. - -### [Dagger](https://dagger-io.readthedocs.io/en/sdk-python-v0.9.6/) - -This is an SDK to build, execute and interact with Docker containers in Python. It's basically a nice API on top of [BuildKit](https://docs.docker.com/build/buildkit/). We use containers to wrap the majority of `airbyte-ci` operations as it allows us to: - -- Execute language agnostic operations: you can execute bash commands, gradle tasks, etc. in containers with Python. Pure magic! -- Benefit from caching by default. You can consider a Dagger operation a "line in a Dockerfile". Each operation is cached by BuildKit if the inputs of the operation did not change. -- As Dagger exposes async APIs we can easily implement concurrent logic. This is great for performance. - -**Please note that we are currently using v0.9.6 of Dagger. The library is under active development so please refer to [this specific version documentation](https://dagger-io.readthedocs.io/en/sdk-python-v0.9.6/) if you want an accurate view of the available APIs.** - -### [anyio](https://anyio.readthedocs.io/en/stable/basics.html) / [asyncer](https://asyncer.tiangolo.com/) - -As Dagger exposes async APIs we use `anyio` (and the `asyncer` wrapper sometimes) to benefit from [structured concurrency](https://en.wikipedia.org/wiki/Structured_concurrency). -**Reading the docs of these libraries is a must if you want to declare concurrent logics.** - -## Design principles - -_The principles set out below are ideals, but the first iterations on the project did not always respect them. Don't be surprised if you see code that contradicts what we're about to say (tech debt...)._ - -### `airbyte-ci` is _just_ an orchestrator - -Ideally the steps declared in airbyte-ci pipeline do not contain any business logic themselves. They call external projects, within containers, which contains the business logic. - -Following this principles will help in decoupling airbyte-ci from other project and make it agnostic from business logics that can quickly evolve. Not introducing business logic to the tool encourages abstraction efforts that can lead to future leverage. - -Maintaining business logic in smaller projects also increases velocity, as introducing a new logic would not require changing airbyte-ci and, which is already a big project in terms of code lines. - -#### Good examples of this principle - -- `connectors-qa`: We want to run specific static checks on all our connectors: we introduced a specific python package ([`connectors-qa`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/connectors_qa/README.md#L1))which declares and run the checks on connectors. We orchestrate the run of this package inside the [QaChecks](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/common.py#L122) step. This class is just aware of the tool location, its entry point, and what has to be mounted to the container for the command to run. -- Internal package testing: We expose an `airbyte-ci test` command which can run a CI pipeline on an internal poetry package. The pipeline logic is declared at the package level with `poe` tasks in the package `pyproject.toml`. `airbyte-ci` is made aware about what is has to run by parsing the content of the `[tool.airbyte_ci]` section of the `pyproject.toml`file. [Example](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/ci_credentials/pyproject.toml#L35) - -### No command or pipeline should be language specific - -We oftentimes have to introduce new flows for connectors / CDK. Even if the need for this flow is currently only existing for a specific connector language (Python / Java), we should build language agnostic command and pipelines. The language specific implementation should come at the most downstream level of the pipeline and we should leverage factory like patterns to get language agnostic pipelines. - -#### Good example of this principle: our build command - -The `airbyte-ci connectors build` command can build multiple connectors of different languages in a single execution. -The higher level [`run_connector_build_pipeline` function](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/__init__.py#L36) is connector language agnostic and calls connector language specific sub pipelines according to the connector language. -We have per-language submodules in which language specific `BuildConnectorImages` classes are implemented: - -- [`python_connectors.py`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/python_connectors.py) -- [`java_connectors.py`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/java_connectors.py#L14) - -### Pipelines are functions, steps are classes - -A pipeline is a function: - -- instantiating and running steps -- collecting step results and acting according to step results -- returning a report - -A step is a class which inheriting from the `Step` base class: - -- Can be instantiated with parameters -- Has a `_run` method which: - - Performs one or multiple operations according to input parameter and context values - - Returns a `StepResult` which can have a `succeeded`, `failed` or `skipped` `StepStatus` - -**Steps should ideally not call other steps and the DAG of steps can be understand by reading the pipeline function.** - -#### Step examples: - -- [`PytestStep`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/python_connectors.py#L29) -- [`GradleTask`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/gradle.py#L21) - -#### Pipelines examples: - -- [`run_connector_publish_pipeline`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/pipeline.py#L296) -- [`run_connector_test_pipeline`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/pipeline.py#L48) - -## Main classes - -### [`PipelineContext`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/models/contexts/pipeline_context.py#L33) (and [`ConnectorContext`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/context.py#L33), [`PublishConnectorContext`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/context.py#L19)) - -Pipeline contexts are instantiated on each command execution and produced according to the CLI inputs. We populate this class with global configuration, helpers and attributes that are accessed during pipeline and step execution. - -It has, for instance, the following attributes: - -- The dagger client -- The list of modified files on the branch -- A `connector` attribute -- A `get_connector_dir` method to interact with the connector -- Global secrets to connect to protected resources -- A `is_ci` attribute to know if the current execution is a local or CI one. - -We use `PipelineContext` with context managers so that we can easily handle setup and teardown logic of context (like producing a `Report`) - -### [`Step`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/models/steps.py#L189) - -`Step` is an abstract class. It is meant to be inherited for implementation of pipeline steps which are use case specific. `Step` exposes a public `run` method which calls a private `_run` method wrapped with progress logger and a retry mechanism. - -When declaring a `Step` child class you are expected to: - -- declare a `title` attribute or `property` -- implement the `_run` method which should return a `StepResult` object. You are free to override the `Step` methods if needed. - -### [`Result` / `StepResult`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/models/steps.py#L86) - -The `Result` class (and its subclasses) are meant to characterize the result of a `Step` execution. -`Result` objects are build with: - -- `StepStatus` (success/failure/skipped) -- `stderr`: The standard error of the operation execution -- `stdout` : The standard output of the operation execution -- `excinfo`: An Exception instance if you want to handle an operation error -- `output`: Any object you'd like to attach to the result for reuse in other Steps -- `artifacts`: Any object produced by the Step that you'd like to attach to the `Report` - -### [`Report`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/models/reports.py#L34) - -A `Report` object is instantiated on `PipelineContext` teardown with a collection of step results. It is meant to persists execution results as json / html locally and in remote storage to share them with users or other automated processes. - -## Github Action orchestration - -A benefit of declaring CI logic in a centralized python package is that our CI logic can be agnostic from the CI platform it runs on. We are currently using GitHub actions. This section will explain how we run `airbyte-ci` in GitHub actions. - -### Multiple workflows re-using the same actions - -Each CI use case has its own Github Action worfklow: - -- [Connector testing](https://github.com/airbytehq/airbyte/blob/master/.github/workflows/connectors_tests.yml#L1) -- [Connector publish](https://github.com/airbytehq/airbyte/blob/master/.github/workflows/publish_connectors.yml#L1) -- [Internal package testing](https://github.com/airbytehq/airbyte/blob/master/.github/workflows/airbyte-ci-tests.yml#L1) -- etc. - -They all use the [`run-airbyte-ci` re-usable action](https://github.com/airbytehq/airbyte/blob/master/.github/actions/run-airbyte-ci/action.yml#L1)to which they provide the `airbyte-ci` command the workflow should run and other environment specific options. - -The `run-airbyte-ci` action does the following: - -- [Pull Dagger image and install airbyte-ci from binary (or sources if the tool was changed on the branch)](https://github.com/airbytehq/airbyte/blob/master/.github/actions/run-airbyte-ci/action.yml#L105) -- [Run the airbyte-ci command passed as an input with other options also passed as inputs](https://github.com/airbytehq/airbyte/blob/main/.github/actions/run-airbyte-ci/action.yml#L111) - -## A full example: breaking down the execution flow of a connector test pipeline - -Let's describe and follow what happens when we run: -`airbyte-ci connectors --modified test` - -**This command is meant to run tests on connectors that were modified on the branch.** -Let's assume I modified the `source-faker` connector. - -### 1. The `airbyte-ci` command group - -On command execution the [`airbyte-ci` command group](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/cli/airbyte_ci.py#L186) acts as the main entrypoint. It is: - -- Provisioning the click context object with options values, that can be accessed in downstream commands. -- Checking if the local docker configuration is correct -- Wrapping the command execution with `dagger run` to get their nice terminal UI (unless `--disable-dagger-run` is passed) - -### 2. The `connectors` command subgroup - -After passing through the top level command group, click dispatches the command execution to the [`connectors`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/commands.py#L237) command subgroup. -It continues to populate the click context with other connectors specific options values which will be consumed by the final `test` command. -**It also computes the list of modified files on the branch and attach this list to the click context.** The `get_modified_files` function basically performs a `git diff` between the current branch and the `--diffed-branch` . - -### 3. Reaching the `test` command - -After going through the command groups we finally reach the actual command the user wants to execute: the [`test` command](https://github.com/airbytehq/airbyte/blob/main/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/commands.py#L72). - -This function: - -- Sends a pending commit status check to Github when we are running in CI -- Determines which steps should be skipped or kept according to user inputs (by building a `RunStepOptions` object) -- Instantiate one `ConnectorContext` per connector under test: we only modified `source-faker` so we'll have a single `ConnectorContext` to work with. -- Call `run_connectors_pipelines` with the `ConnectorContext`s and - -#### 4. Globally dispatching pipeline logic in `run_connectors_pipeline` - -[`run_connectors_pipeline`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pipeline.py#L83) gets called with all the `ConnectorContext` produced according to the user inputs and a callable which captures the pipeline logic: `run_connector_test_pipeline`. -`run_connectors_pipeline`, as its taking a pipeline callable, it has no specific pipeline logic. - -This function: - -- Instantiates the dagger client -- Create a task group to concurrently run the pipeline callable: we'd concurrently run test pipeline on multiple connectors if multiple connectors were modified. -- The concurrency of the pipeline is control via a semaphore object. - -#### 5. Actually running the pipeline in [`run_connector_test_pipeline`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/pipeline.py#L48) - -_Reminder: this function is called for each connector selected for testing. It takes a `ConnectorContext` and a `Semaphore` as inputs._ - -The specific steps to run in the pipeline for a connector is determined by the output of the [`get_test_steps`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/pipeline.py#L32) function which is building a step tree according to the connector language. - -**You can for instance check the declared step tree for python connectors [here](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/python_connectors.py#L249).**: - -```python -def get_test_steps(context: ConnectorContext) -> STEP_TREE: - """ - Get all the tests steps for a Python connector. - """ - return [ - [StepToRun(id=CONNECTOR_TEST_STEP_ID.BUILD, step=BuildConnectorImages(context))], - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.UNIT, - step=UnitTests(context), - args=lambda results: {"connector_under_test": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ) - ], - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.INTEGRATION, - step=IntegrationTests(context), - args=lambda results: {"connector_under_test": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ), - StepToRun( - id=CONNECTOR_TEST_STEP_ID.PYTHON_CLI_VALIDATION, - step=PyAirbyteValidation(context), - args=lambda results: {"connector_under_test": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ), - StepToRun( - id=CONNECTOR_TEST_STEP_ID.ACCEPTANCE, - step=AcceptanceTests(context, context.concurrent_cat), - args=lambda results: {"connector_under_test_container": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ), - ], - ] -``` - -After creating the step tree (a.k.a a _DAG_) it enters the `Semaphore` and `PipelineContext` context manager to execute the steps to run with `run_steps`. `run_steps` executes steps concurrently according to their dependencies. - -Once the steps are executed we get step results. We can build a `ConnectorReport` from these results. The report is finally attached to the `context` so that it gets persisted on `context` teardown. - -```python -async def run_connector_test_pipeline(context: ConnectorContext, semaphore: anyio.Semaphore) -> ConnectorReport: - """ - Compute the steps to run for a connector test pipeline. - """ - all_steps_to_run: STEP_TREE = [] - - all_steps_to_run += get_test_steps(context) - - if not context.code_tests_only: - static_analysis_steps_to_run = [ - [ - StepToRun(id=CONNECTOR_TEST_STEP_ID.VERSION_INC_CHECK, step=VersionIncrementCheck(context)), - StepToRun(id=CONNECTOR_TEST_STEP_ID.QA_CHECKS, step=QaChecks(context)), - ] - ] - all_steps_to_run += static_analysis_steps_to_run - - async with semaphore: - async with context: - result_dict = await run_steps( - runnables=all_steps_to_run, - options=context.run_step_options, - ) - - results = list(result_dict.values()) - report = ConnectorReport(context, steps_results=results, name="TEST RESULTS") - context.report = report - - return report -``` - -#### 6. `ConnectorContext` teardown - -Once the context manager is exited (when we exit the `async with context` block) the [`ConnectorContext.__aexit__` function is executed](https://github.com/airbytehq/airbyte/blob/main/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/context.py#L237) - -This function: - -- Determines the global success or failure state of the pipeline according to the StepResults -- Uploads connector secrets back to GSM if they got updated -- Persists the report to disk -- Prints the report to the console -- Uploads the report to remote storage if we're in CI -- Updates the per connector commit status check diff --git a/airbyte-ci/connectors/pipelines/README.md b/airbyte-ci/connectors/pipelines/README.md deleted file mode 100644 index 9df54aa7443b..000000000000 --- a/airbyte-ci/connectors/pipelines/README.md +++ /dev/null @@ -1,1249 +0,0 @@ -# Airbyte CI CLI - -## What is it? - -`airbyte-ci` is a command line interface to run CI/CD pipelines. The goal of this CLI is to offer -developers a tool to run these pipelines locally and in a CI context with the same guarantee. It can -prevent unnecessary commit -> push cycles developers typically go through when they when to test -their changes against a remote CI. This is made possible thanks to the use of -[Dagger](https://dagger.io), a CI/CD engine relying on Docker Buildkit to provide reproducible -builds. Our pipeline are declared with Python code, the main entrypoint is -[here](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connector_ops/connector_ops/pipelines/commands/airbyte_ci.py). -This documentation should be helpful for both local and CI use of the CLI. We indeed -[power connector testing in the CI with this CLI](https://github.com/airbytehq/airbyte/blob/master/.github/workflows/connector_integration_test_single_dagger.yml#L78). - -## How to install - -### Requirements - -- A running Docker engine with version >= 20.10.23 - -## Install or Update - -The recommended way to install `airbyte-ci` is using the [Makefile](../../../Makefile). - -```sh -# from the root of the airbyte repository -make tools.airbyte-ci.install -``` - -### Setting up connector secrets access - -If you plan to use Airbyte CI to run CAT (Connector Acceptance Tests), we recommend setting up GSM -access so that Airbyte CI can pull remote secrets from GSM. For setup instructions, see the CI -Credentials package (which Airbyte CI uses under the hood) README's -[Get GSM Access](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/ci_credentials/README.md#get-gsm-access) -instructions. - -### Updating the airbyte-ci tool - -To reinstall airbyte-ci, run the following command: - -```sh -airbyte-ci update -``` - -or if that fails, you can reinstall it with the following command: - -```sh -# from the root of the airbyte repository -make tools.airbyte-ci.install -``` - -## Checking the airbyte-ci install - -To check that airbyte-ci is installed correctly, run the following command: - -```sh -make tools.airbyte-ci.check -``` - -## Cleaning the airbyte-ci install - -To clean the airbyte-ci install, run the following command: - -```sh -make tools.airbyte-ci.clean -``` - -## Disabling telemetry - -We collect anonymous usage data to help improve the tool. If you would like to disable this, you can -set the `AIRBYTE_CI_DISABLE_TELEMETRY` environment variable to `true`. - -## Installation for development - -#### Pre-requisites - -- Poetry >= 1.1.8 -- Python >= 3.10 - -#### Installation - -If you are developing on pipelines, we recommend installing airbyte-ci with poetry: - -```bash -cd airbyte-ci/connectors/pipelines/ -poetry install -poetry env activate -cd ../../ -``` - -**Alternatively**, you can install airbyte-ci with pipx so that the entrypoint is available in your -PATH: - -```bash -make tools.airbyte-ci.install -``` - -However, this will not automatically install the dependencies for the local dependencies of -airbyte-ci, or respect the lockfile. - -Its often best to use the `poetry` steps instead. - -#### Running Tests - -From `airbyte-ci/connectors/pipelines`: - -```bash -poetry run pytest tests -``` - -You can also run a subset of tests: - -```bash -poetry run pytest pipelines/models/steps.py -``` - -More options, such as running test by keyword matching, are available - see the -[pytest CLI documentation](https://docs.pytest.org/en/6.2.x/usage.html) for all the available -options.``` - -#### Checking Code Format (Pipelines) - -```bash -poetry run ruff check pipelines -``` - -## Commands reference - -At this point you can run `airbyte-ci` commands. - -- [Airbyte CI CLI](#airbyte-ci-cli) - - [What is it?](#what-is-it) - - [How to install](#how-to-install) - - [Requirements](#requirements) - - [Install or Update](#install-or-update) - - [Setting up connector secrets access](#setting-up-connector-secrets-access) - - [Updating the airbyte-ci tool](#updating-the-airbyte-ci-tool) - - [Checking the airbyte-ci install](#checking-the-airbyte-ci-install) - - [Cleaning the airbyte-ci install](#cleaning-the-airbyte-ci-install) - - [Disabling telemetry](#disabling-telemetry) - - [Installation for development](#installation-for-development) - - [Pre-requisites](#pre-requisites) - - [Installation](#installation) - - [Running Tests](#running-tests) - - [Checking Code Format (Pipelines)](#checking-code-format-pipelines) - - [Commands reference](#commands-reference) - - [`airbyte-ci` command group](#airbyte-ci-command-group) - - [Options](#options) - - [`connectors` command subgroup](#connectors-command-subgroup) - - [Options](#options-1) - - [`connectors list` command](#connectors-list-command) - - [Examples](#examples) - - [`connectors test` command](#connectors-test-command) - - [Examples](#examples-1) - - [What it runs](#what-it-runs) - - [Options](#options-2) - - [Extra parameters](#extra-parameters) - - [`connectors build` command](#connectors-build-command) - - [What it runs](#what-it-runs-1) - - [Options](#options-3) - - [`connectors publish` command](#connectors-publish-command) - - [Examples](#examples-2) - - [Options](#options-4) - - [What it runs](#what-it-runs-2) - - [Python registry publishing](#python-registry-publishing) - - [`connectors up-to-date` command](#connectors-up-to-date-command) - - [Examples](#examples-3) - - [Other things it could do](#other-things-it-could-do) - - [`connectors bump-version` command](#connectors-bump-version-command) - - [Examples](#examples-4) - - [Arguments](#arguments) - - [`connectors upgrade_cdk` command](#connectors-upgrade_cdk-command) - - [Examples](#examples-5) - - [Arguments](#arguments-1) - - [`connectors migrate-to-base-image` command](#connectors-migrate-to-base-image-command) - - [Examples](#examples-6) - - [`connectors migrate-to-poetry` command](#connectors-migrate-to-poetry-command) - - [Examples](#examples-7) - - [`connectors migrate-to-inline-schemas` command](#connectors-migrate-to-inline-schemas-command) - - [Examples](#examples-8) - - [`connectors pull-request` command](#connectors-pull-request-command) - - [Examples](#examples-9) - - [`format` command subgroup](#format-command-subgroup) - - [Options](#options-6) - - [Examples](#examples-10) - - [`format check all` command](#format-check-all-command) - - [`format fix all` command](#format-fix-all-command) - - [`poetry` command subgroup](#poetry-command-subgroup) - - [Options](#options-7) - - [Examples](#examples-11) - - [`publish` command](#publish-command) - - [Options](#options-8) - - [`metadata` command subgroup](#metadata-command-subgroup) - - [`metadata deploy orchestrator` command](#metadata-deploy-orchestrator-command) - - [Example](#example) - - [What it runs](#what-it-runs-3) - - [`tests` command](#tests-command) - - [Options](#options-9) - - [Examples](#examples-12) - - [`migrate-to-manifest-only` command](#migrate-to-manifest-only-command) - - [Examples](#examples-13) - - [Changelog](#changelog) - - [More info](#more-info) -- [Troubleshooting](#troubleshooting) - - [Commands](#commands) - - [`make tools.airbyte-ci.check`](#make-toolsairbyte-cicheck) - - [`make tools.airbyte-ci.clean`](#make-toolsairbyte-ciclean) - - [Common issues](#common-issues) - - [`airbyte-ci` is not found](#airbyte-ci-is-not-found) - - [Development](#development) - - [`airbyte-ci` is not found](#airbyte-ci-is-not-found-1) - - [python3.10 not found](#python310-not-found) - - [Any type of pipeline failure](#any-type-of-pipeline-failure) - -### `airbyte-ci` command group - -**The main command group option has sensible defaults. In local use cases you're not likely to pass -options to the `airbyte-ci` command group.** - -#### Options - -| Option | Default value | Mapped environment variable | Description | -| ---------------------------------------------- | ------------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------- | -| `--yes/--y` | False | | Agrees to all prompts. | -| `--yes-auto-update/--no-auto-update` | True | | Agrees to the auto update prompts. | -| `--enable-update-check/--disable-update-check` | True | | Turns on the update check feature | -| `--enable-dagger-run/--disable-dagger-run` | `--enable-dagger-run` | | Disables the Dagger terminal UI. | -| `--is-local/--is-ci` | `--is-local` | | Determines the environment in which the CLI runs: local environment or CI environment. | -| `--git-branch` | The checked out git branch name | `CI_GIT_BRANCH` | The git branch on which the pipelines will run. | -| `--git-revision` | The current branch head | `CI_GIT_REVISION` | The commit hash on which the pipelines will run. | -| `--diffed-branch` | `master` | | Branch to which the git diff will happen to detect new or modified files. | -| `--gha-workflow-run-id` | | | GHA CI only - The run id of the GitHub action workflow | -| `--ci-context` | `manual` | | The current CI context: `manual` for manual run, `pull-request`, `nightly_builds`, `master` | -| `--pipeline-start-timestamp` | Current epoch time | `CI_PIPELINE_START_TIMESTAMP` | Start time of the pipeline as epoch time. Used for pipeline run duration computation. | -| `--show-dagger-logs/--hide-dagger-logs` | `--hide-dagger-logs` | | Flag to show or hide the dagger logs. | - -### `connectors` command subgroup - -Available commands: - -- `airbyte-ci connectors test`: Run tests for one or multiple connectors. -- `airbyte-ci connectors build`: Build docker images for one or multiple connectors. -- `airbyte-ci connectors publish`: Publish a connector to Airbyte's DockerHub. - -#### Options - -| Option | Multiple | Default value | Mapped Environment Variable | Description | -| -------------------------------------------------------------- | -------- | -------------------------------- | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `--use-remote-secrets/--use-local-secrets` | False | | | If --use-remote-secrets, connectors configuration will be pulled from Google Secret Manager. Requires the `GCP_GSM_CREDENTIALS` environment variable to be set with a service account with permission to read GSM secrets. If --use-local-secrets the connector configuration will be read from the local connector `secrets` folder. If this flag is not used and a `GCP_GSM_CREDENTIALS` environment variable is set remote secrets will be used, local secrets will be used otherwise. | -| `--name` | True | | | Select a specific connector for which the pipeline will run. Can be used multiple times to select multiple connectors. The expected name is the connector technical name. e.g. `source-pokeapi` | -| `--support-level` | True | | | Select connectors with a specific support level: `community`, `certified`. Can be used multiple times to select multiple support levels. | -| `--metadata-query` | False | | | Filter connectors by the `data` field in the metadata file using a [simpleeval](https://github.com/danthedeckie/simpleeval) query. e.g. 'data.ab_internal.ql == 200' | -| `--use-local-cdk` | False | False | | Build with the airbyte-cdk from the local repository. " "This is useful for testing changes to the CDK. | -| `--language` | True | | | Select connectors with a specific language: `python`, `low-code`, `java`. Can be used multiple times to select multiple languages. | -| `--modified` | False | False | | Run the pipeline on only the modified connectors on the branch or previous commit (depends on the pipeline implementation). Archived connectors are ignored. | -| `--concurrency` | False | 5 | | Control the number of connector pipelines that can run in parallel. Useful to speed up pipelines or control their resource usage. | -| `--metadata-change-only/--not-metadata-change-only` | False | `--not-metadata-change-only` | | Only run the pipeline on connectors with changes on their metadata.yaml file. | -| `--enable-dependency-scanning / --disable-dependency-scanning` | False | ` --disable-dependency-scanning` | | When enabled the dependency scanning will be performed to detect the connectors to select according to a dependency change. | -| `--docker-hub-username` | | | DOCKER_HUB_USERNAME | Your username to connect to DockerHub. Required for the publish subcommand. | -| `--docker-hub-password` | | | DOCKER_HUB_PASSWORD | Your password to connect to DockerHub. Required for the publish subcommand. | - -### `connectors list` command - -Retrieve the list of connectors satisfying the provided filters. - -#### Examples - -List all connectors: - -`airbyte-ci connectors list` - -List all connectors and write the output to a file: -`airbyte-ci connectors list --output=connectors.json` - -List certified connectors: - -`airbyte-ci connectors --support-level=certified list` - -List connectors changed on the current branch: - -`airbyte-ci connectors --modified list` - -List connectors with a specific language: - -`airbyte-ci connectors --language=python list` - -List connectors with multiple filters: - -`airbyte-ci connectors --language=low-code --support-level=certified list` - -### `connectors test` command - -Run a test pipeline for one or multiple connectors. - -#### Examples - -Test a single connector: `airbyte-ci connectors --name=source-pokeapi test` - -Test multiple connectors: `airbyte-ci connectors --name=source-pokeapi --name=source-bigquery test` - -Test certified connectors: `airbyte-ci connectors --support-level=certified test` - -Test connectors changed on the current branch: `airbyte-ci connectors --modified test` - -Run acceptance test only on the modified connectors, just run its full refresh tests: -`airbyte-ci connectors --modified test --only-step="acceptance" --acceptance.-k=test_full_refresh` - -#### What it runs - -```mermaid -flowchart TD - entrypoint[[For each selected connector]] - subgraph static ["Static code analysis"] - qa[Run QA checks] - sem["Check version follows semantic versioning"] - incr["Check version is incremented"] - metadata_validation["Run metadata validation on metadata.yaml"] - sem --> incr - end - subgraph tests ["Tests"] - build[Build connector docker image] - unit[Run unit tests] - integration[Run integration tests] - pyairbyte_validation[Python CLI smoke tests via PyAirbyte] - cat[Run connector acceptance tests] - secret[Load connector configuration] - - unit-->secret - unit-->build - secret-->integration - secret-->cat - secret-->pyairbyte_validation - build-->integration - build-->cat - end - entrypoint-->static - entrypoint-->tests - report["Build test report"] - tests-->report - static-->report -``` - -#### Options - -| Option | Multiple | Default value | Description | -| ------------------------------------------------------- | -------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `--skip-step/-x` | True | | Skip steps by id e.g. `-x unit -x acceptance` | -| `--only-step/-k` | True | | Only run specific steps by id e.g. `-k unit -k acceptance` | -| `--fail-fast` | False | False | Abort after any tests fail, rather than continuing to run additional tests. Use this setting to confirm a known bug is fixed (or not), or when you only require a pass/fail result. | -| `--code-tests-only` | True | False | Skip any tests not directly related to code updates. For instance, metadata checks, version bump checks, changelog verification, etc. Use this setting to help focus on code quality during development. | -| `--concurrent-cat` | False | False | Make CAT tests run concurrently using pytest-xdist. Be careful about source or destination API rate limits. | -| `--.=` | True | | You can pass extra parameters for specific test steps. More details in the extra parameters section below | -| `--ci-requirements` | False | | | Output the CI requirements as a JSON payload. It is used to determine the CI runner to use. - -Note: - -- The above options are implemented for Java connectors but may not be available for Python - connectors. If an option is not supported, the pipeline will not fail but instead the 'default' - behavior will be executed. - -#### Extra parameters - -You can pass extra parameters to the following steps: - -- `unit` -- `integration` -- `acceptance` - -This allows you to override the default parameters of these steps. For example, you can only run the -`test_read` test of the acceptance test suite with: -`airbyte-ci connectors --name=source-pokeapi test --acceptance.-k=test_read` Here the `-k` parameter -is passed to the pytest command running acceptance tests. Please keep in mind that the extra -parameters are not validated by the CLI: if you pass an invalid parameter, you'll face a late -failure during the pipeline execution. - -### `connectors build` command - -Run a build pipeline for one or multiple connectors and export the built docker image to the local -docker host. It's mainly purposed for local use. - -Build a single connector: `airbyte-ci connectors --name=source-pokeapi build` - -Build a single connector with a custom image tag: -`airbyte-ci connectors --name=source-pokeapi build --tag=my-custom-tag` - -Build a single connector for multiple architectures: -`airbyte-ci connectors --name=source-pokeapi build --architecture=linux/amd64 --architecture=linux/arm64` - -You will get: - -- `airbyte/source-pokeapi:dev-linux-amd64` -- `airbyte/source-pokeapi:dev-linux-arm64` - -Build multiple connectors: -`airbyte-ci connectors --name=source-pokeapi --name=source-bigquery build` - -Build certified connectors: `airbyte-ci connectors --support-level=certified build` - -Build connectors changed on the current branch: `airbyte-ci connectors --modified build` - -#### What it runs - -For Python and Low Code connectors: - -```mermaid -flowchart TD - arch(For each platform amd64/arm64) - connector[Build connector image] - load[Load to docker host with :dev tag, current platform] - spec[Get spec] - arch-->connector-->spec--"if success"-->load -``` - -For Java connectors: - -```mermaid -flowchart TD - arch(For each platform amd64/arm64) - distTar[Gradle distTar task run] - base[Build integration base] - java_base[Build integration base Java] - normalization[Build Normalization] - connector[Build connector image] - - arch-->base-->java_base-->connector - distTar-->connector - normalization--"if supports normalization"-->connector - - load[Load to docker host with :dev tag] - spec[Get spec] - connector-->spec--"if success"-->load -``` - -### Options - -| Option | Multiple | Default value | Description | -| --------------------- | -------- | -------------- | -------------------------------------------------------------------- | -| `--architecture`/`-a` | True | Local platform | Defines for which architecture(s) the connector image will be built. | -| `--tag` | False | `dev` | Image tag for the built image. | - -### `connectors publish` command - -Run a publish pipeline for one or multiple connectors. It's mainly purposed for CI use to release a -connector update. - -### Examples - -Publish all connectors modified in the head commit: `airbyte-ci connectors --modified publish` - -### Options - -| Option | Required | Default | Mapped environment variable | Description | -| ------------------------------------ | -------- | ------------------------------- | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `--pre-release/--main-release` | False | `--pre-release` | | Whether to publish the pre-release or the main release version of a connector. Defaults to pre-release. For main release you have to set the credentials to interact with the GCS bucket. | -| `--spec-cache-gcs-credentials` | False | | `SPEC_CACHE_GCS_CREDENTIALS` | The service account key to upload files to the GCS bucket hosting spec cache. | -| `--spec-cache-bucket-name` | False | | `SPEC_CACHE_BUCKET_NAME` | The name of the GCS bucket where specs will be cached. | -| `--metadata-service-gcs-credentials` | False | | `METADATA_SERVICE_GCS_CREDENTIALS` | The service account key to upload files to the GCS bucket hosting the metadata files. | -| `--metadata-service-bucket-name` | False | | `METADATA_SERVICE_BUCKET_NAME` | The name of the GCS bucket where metadata files will be uploaded. | -| `--slack-webhook` | False | | `SLACK_WEBHOOK` | The Slack webhook URL to send notifications to. | -| `--slack-channel` | False | | `SLACK_CHANNEL` | The Slack channel name to send notifications to. | -| `--ci-requirements` | False | | | Output the CI requirements as a JSON payload. It is used to determine the CI runner to use. | -| `--python-registry-token` | False | | `PYTHON_REGISTRY_TOKEN` | The API token to authenticate with the registry. For pypi, the `pypi-` prefix needs to be specified | -| `--python-registry-url` | False | https://upload.pypi.org/legacy/ | `PYTHON_REGISTRY_URL` | The python registry to publish to. Defaults to main pypi | -| `--python-registry-check-url` | False | https://pypi.org/pypi | `PYTHON_REGISTRY_CHECK_URL` | The python registry url to check whether a package is published already | -| `--promote-release-candidate` | False | False | | Promote the release candidate version of selected connectors as main version. | -| `--rollback-release-candidate` | False | False | | Rollback the release candidate version of the selector connectors. | - -I've added an empty "Default" column, and you can fill in the default values as needed. - -#### What it runs - -```mermaid -flowchart TD - validate[Validate the metadata file] - check[Check if the connector image already exists] - build[Build the connector image for all platform variants] - publish_to_python_registry[Push the connector image to the python registry if enabled] - upload_spec[Upload connector spec to the spec cache bucket] - push[Push the connector image from DockerHub, with platform variants] - pull[Pull the connector image from DockerHub to check SPEC can be run and the image layers are healthy] - upload_metadata[Upload its metadata file to the metadata service bucket] - - validate-->check-->build-->upload_spec-->publish_to_python_registry-->push-->pull-->upload_metadata -``` - -#### Python registry publishing - -If `remoteRegistries.pypi.enabled` in the connector metadata is set to `true`, the connector will be -published to the python registry. To do so, the `--python-registry-token` and -`--python-registry-url` options are used to authenticate with the registry and publish the -connector. If the current version of the connector is already published to the registry, the publish -will be skipped (the `--python-registry-check-url` is used for the check). - -On a pre-release, the connector will be published as a `.dev` version. - -The `remoteRegistries.pypi.packageName` field holds the name of the used package name. It should be -set to `airbyte-source-`. Certified Python connectors are required to have PyPI -publishing enabled. - -An example `remoteRegistries` entry in a connector `metadata.yaml` looks like this: - -```yaml -remoteRegistries: - pypi: - enabled: true - packageName: airbyte-source-pokeapi -``` - -### `connectors up-to-date` command - -Meant to be run on a cron script. - -Actions: - -- Set the latest base image version on selected connectors -- Run `poetry update` on selected connectors -- Bump the connector version and update the changelog -- Open a PR with the changes, set `auto-merge` label on it. - -``` -Usage: airbyte-ci connectors up-to-date [OPTIONS] - -Options: - --no-bump Don't bump the version or changelog. - --dep TEXT Give a specific set of `poetry add` dependencies to update. For - example: --dep airbyte-cdk==0.80.0 --dep pytest@^6.2 - --open-reports Auto open reports in the browser. - --create-prs Create pull requests for each updated connector. - --auto-merge Set the auto-merge label on created PRs. - --help Show this message and exit. -``` - -### Examples - -Get source-openweather up to date. If there are changes, bump the version and add to changelog: - -- `airbyte-ci connectors --name=source-openweather up-to-date`: upgrades main dependecies -- `airbyte-ci connectors --name=source-openweather up-to-date` -- `airbyte-ci connectors --name=source-openweather up-to-date --create-prs`: make a pull request for it -- `airbyte-ci connectors --name=source-openweather up-to-date --no-bump`: don't change the version or changelog - -### `connectors bump-version` command - -Bump the version of the selected connectors. -A placeholder will be added to the changelog file for the new entry PR number. -Use the `connectors pull-request` command to create a PR, it will update the changelog entry with the PR number. - -### Examples - -Bump source-openweather: -`airbyte-ci connectors --name=source-openweather bump-version patch ""` - -#### Arguments - -| Argument | Description | -| ----------------- | ---------------------------------------------------------------------- | -| `BUMP_TYPE` | major, minor, patch, rc, or version: | -| `CHANGELOG_ENTRY` | The changelog entry that will get added to the connector documentation | - -#### Options - -| Option | Description | -| ----------- | ----------------------------------------------------------------------------------------- | -| --pr-number | Explicitly set the PR number in the changelog entry, a placeholder will be set otherwise. | -| --rc | Bump the version by the specified bump type and append the release candidate suffix. | - -### `connectors upgrade-cdk` command - -Updates the CDK version of the selected connectors. -For Python connectors, sets the `airbyte-cdk` dependency in `pyproject.toml` and refreshes the lockfile, updating only essential dependencies. - -### Examples - -`airbyte-ci connectors --language=python upgrade-cdk` -> Updates all python connectors to the caret range of the latest version. -`airbyte-ci connectors --name=source-openweather upgrade-cdk "3.0.0"` -> Pins source-openweather to version 3.0.0 -`airbyte-ci connectors --modified upgrade-cdk "<4"` -> Updates all modified connectors to the highest available version of major version 3.x.x - -#### Arguments - -| Argument | Description | -| ------------- | ------------------------------------------------------------------------- | -| `CDK_VERSION` | CDK version constraint to set (default to `^{most_recent_patch_version}`) | - -#### Notes - -When using < (less than) or > (greater than) for the `CDK_VERSION` argument, it must be wrapped in quotation marks ("<3"). Otherwise the shell (zsh or bash) will interprete these characters as redirection operators. - -### `connectors migrate-to-base-image` command - -Make a connector using a Dockerfile migrate to the base image by: - -- Removing its Dockerfile -- Updating its metadata to use the latest base image version -- Updating its documentation to explain the build process -- Bumping by a patch version - -#### Examples - -Migrate source-openweather to use the base image: -`airbyte-ci connectors --name=source-openweather migrate-to-base-image` - -### `connectors migrate-to-poetry` command - -Migrate connectors the poetry package manager. - -#### Examples - -Migrate source-openweather to use the base image: -`airbyte-ci connectors --name=source-openweather migrate-to-poetry` -`airbyte-ci connectors --name=source-openweather migrate-to-poetry --changelog --bump patch` - -### `connectors migrate-to-inline-schemas` command - -Migrate `.json` schemas into `manifest.yaml` files, when present. - -``` -Usage: airbyte-ci connectors migrate-to-inline-schemas [OPTIONS] - -Options: - --report Auto open report browser. - --help Show this message and exit. -``` - -#### Examples - -Migrate source-quickbooks to use inline schemas: -`airbyte-ci connectors --name=source-quickbooks migrate-to-inline-schemas` - -### `connectors pull-request` command - -Makes a pull request for all changed connectors. If the branch already exists, it will update the existing one. - -``` -Usage: airbyte-ci connectors pull-request [OPTIONS] - -Options: - -m, --message TEXT Commit message and pull request title and - changelog (if enabled). [required] - -b, --branch_id TEXT update a branch named / instead generating one from the message. - [required] - --report Auto open report browser. - --title TEXT Title of the PR to be created or edited - (optional - defaults to message or no change). - --body TEXT Body of the PR to be created or edited (optional - - defaults to empty or not change). - --help Show this message and exit. -``` - -#### Examples - -Make a PR for all changes, bump the version and make a changelog in those PRs. They will be on the branch ci_update/round2/: -`airbyte-ci connectors --modified pull-request -m "upgrading connectors" -b ci_update/round2` - -Do it just for a few connectors: -`airbyte-ci connectors --name source-aha --name source-quickbooks pull-request -m "upgrading connectors" -b ci_update/round2` - -You can also set or set/change the title or body of the PR: -`airbyte-ci connectors --name source-aha --name source-quickbooks pull-request -m "upgrading connectors" -b ci_update/round2 --title "New title" --body "full body\n\ngoes here"` - -### `connectors generate-erd` command - -Generates a couple of files and publish a new ERD to dbdocs. The generated files are: - -- `/erd/discovered_catalog.json`: the catalog used to generate the estimated relations and the dbml file -- `/erd/estimated_relationships.json`: the output of the LLM trying to figure out the relationships between the different streams -- `/erd/source.dbml`: the file used the upload the ERDs to dbdocs - -Pre-requisites: - -- The config file use to discover the catalog should be available in `/secrets/config.json` - -#### Create initial diagram workflow or on connector's schema change - -Steps - -- Ensure the pre-requisites mentioned above are met -- Run `DBDOCS_TOKEN= GENAI_API_KEY= airbyte-ci connectors --name= generate-erd` -- Create a PR with files `/erd/estimated_relationships.json` and `/erd/source.dbml` for documentation purposes - -Expected Outcome - -- The diagram is available in dbdocs -- `/erd/estimated_relationships.json` and `/erd/source.dbml` are updated on master - -#### On manual validation - -Steps - -- If not exists, create file `/erd/confirmed_relationships.json` with the following format and add: - - `relations` describes the relationships that we know exist - - `false_positives` describes the relationships the LLM found that we know do not exist - -``` -{ - "streams": [ - { - "name": , - "relations": { - : "." - } - "false_positives": { - : "." - } - }, - <...> - ] -} -``` - -- Ensure the pre-requisites mentioned above are met -- Run `DBDOCS_TOKEN= airbyte-ci connectors --name= generate-erd -x llm_relationships` -- Create a PR with files `/erd/confirmed_relationships.json` and `/erd/source.dbml` for documentation purposes - -#### Options - -| Option | Required | Default | Mapped environment variable | Description | -| ---------------- | -------- | ------- | --------------------------- | ----------------------------------------------------------- | -| `--skip-step/-x` | False | | | Skip steps by id e.g. `-x llm_relationships -x publish_erd` | - -### `format` command subgroup - -`airbyte-ci format` is no longer available. To format code in this repository, we're using `pre-commit`. Assuming `pre-commit` is installed, `pre-commit run` will run the formatters for you. - -### `poetry` command subgroup - -Available commands: - -- `airbyte-ci poetry publish` - -### Options - -| Option | Required | Default | Mapped environment variable | Description | -| ---------------- | -------- | ------- | --------------------------- | -------------------------------------------------------------- | -| `--package-path` | True | | | The path to the python package to execute a poetry command on. | - -### Examples - -- Publish a python package: - `airbyte-ci poetry --package-path=path/to/package publish --publish-name=my-package --publish-version="1.2.3" --python-registry-token="..." --registry-url="http://host.docker.internal:8012/"` - -### `publish` command - -This command publishes poetry packages (using `pyproject.toml`) or python packages (using -`setup.py`) to a python registry. - -For poetry packages, the package name and version can be taken from the `pyproject.toml` file or be -specified as options. - -#### Options - -| Option | Required | Default | Mapped environment variable | Description | -| ------------------------- | -------- | ------------------------------- | --------------------------- | -------------------------------------------------------------------------------------------------------- | -| `--publish-name` | False | | | The name of the package. Not required for poetry packages that define it in the `pyproject.toml` file | -| `--publish-version` | False | | | The version of the package. Not required for poetry packages that define it in the `pyproject.toml` file | -| `--python-registry-token` | True | | PYTHON_REGISTRY_TOKEN | The API token to authenticate with the registry. For pypi, the `pypi-` prefix needs to be specified | -| `--python-registry-url` | False | https://upload.pypi.org/legacy/ | PYTHON_REGISTRY_URL | The python registry to publish to. Defaults to main pypi | - -### `metadata` command subgroup - -Available commands: - -- `airbyte-ci metadata deploy orchestrator` - -### `metadata deploy orchestrator` command - -This command deploys the metadata service orchestrator to production. The -`DAGSTER_CLOUD_METADATA_API_TOKEN` environment variable must be set. - -#### Example - -`airbyte-ci metadata deploy orchestrator` - -#### What it runs - -```mermaid -flowchart TD - test[Run orchestrator tests] --> deploy[Deploy orchestrator to Dagster Cloud] -``` - -### `tests` command - -This command runs the poe tasks declared in the `[tool.airbyte-ci]` section of our internal poetry -packages. Feel free to checkout this -[Pydantic model](https://github.com/airbytehq/airbyte/blob/main/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/models.py#L9) -to see the list of available options in `[tool.airbyte-ci]` section. - -You can find the list of internal packages -[here](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/__init__.py#L1) - -#### Options - -| Option | Required | Multiple | Description | -| -------------------------- | -------- | -------- | ------------------------------------------------------------------------------------------- | -| `--poetry-package-path/-p` | False | True | Poetry packages path to run the poe tasks for. | -| `--modified` | False | False | Run poe tasks of modified internal poetry packages. | -| `--ci-requirements` | False | False | Output the CI requirements as a JSON payload. It is used to determine the CI runner to use. | - -#### Examples - -You can pass multiple `--poetry-package-path` options to run poe tasks. - -E.G.: running Poe tasks on the modified internal packages of the current branch: -`airbyte-ci test --modified` - -### `migrate-to-manifest-only` command - -This command migrates valid connectors to the `manifest-only` format. It contains two steps: - -1. Check: Validates whether a connector is a candidate for the migration. If not, the operation will be skipped. -2. Migrate: Strips out all unneccessary files/folders, leaving only the root-level manifest, metadata, icon, and acceptance/integration test files. Unwraps the manifest (references and `$parameters`) so it's compatible with Connector Builder. - -#### Examples - -```bash -airbyte-ci connectors --name=source-pokeapi migrate-to-manifest-only -airbyte-ci connectors --language=low-code migrate-to-manifest-only -``` - -## Changelog - -| Version | PR | Description | -| ------- | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -| 5.5.0 | [#64164](https://github.com/airbytehq/airbyte/pull/64164) | Remove the `MetadataValidation` step from the airbyte-ci pipeline. This is now done via a shell script. | -| 5.4.0 | [#64135](https://github.com/airbytehq/airbyte/pull/64135) | Delete the base_images sub-package. Connector base images are now built using Dockerfiles | -| 5.3.0 | [#61598](https://github.com/airbytehq/airbyte/pull/61598) | Add trackable commit text and github-native auto-merge in up-to-date, auto-merge, rc-promote, and rc-rollback | -| 5.2.5 | [#60325](https://github.com/airbytehq/airbyte/pull/60325) | Update slack team to oc-extensibility-critical-systems | -| 5.2.4 | [#59724](https://github.com/airbytehq/airbyte/pull/59724) | Fix components mounting and test dependencies for manifest-only unit tests | -| 5.1.0 | [#53238](https://github.com/airbytehq/airbyte/pull/53238) | Add ability to opt out of version increment checks via metadata flag | -| 5.0.1 | [#52664](https://github.com/airbytehq/airbyte/pull/52664) | Update Python version requirement from 3.10 to 3.11. | -| 4.49.4 | [#52104](https://github.com/airbytehq/airbyte/pull/52104) | Stream Gradle task output to the step logger | -| 5.0.0 | [#52647](https://github.com/airbytehq/airbyte/pull/52647) | Removed migration and formatting commands. | -| 4.49.3 | [#52102](https://github.com/airbytehq/airbyte/pull/52102) | Load docker image to local docker host for java connectors | -| 4.49.2 | [#52090](https://github.com/airbytehq/airbyte/pull/52090) | Re-add custom task parameters in GradleTask | -| 4.49.1 | [#52087](https://github.com/airbytehq/airbyte/pull/52087) | Wire the `--enable-report-auto-open` correctly for connector tests | -| 4.49.0 | [#52033](https://github.com/airbytehq/airbyte/pull/52033) | Run gradle as a subprocess and not via Dagger | -| 4.48.9 | [#51609](https://github.com/airbytehq/airbyte/pull/51609) | Fix ownership of shared cache volume for non root connectors | -| 4.48.8 | [#51582](https://github.com/airbytehq/airbyte/pull/51582) | Fix typo in `migrate-to-inline-schemas` command | -| 4.48.7 | [#51579](https://github.com/airbytehq/airbyte/pull/51579) | Give back the ownership of /tmp to the original user on finalize build | -| 4.48.6 | [#51577](https://github.com/airbytehq/airbyte/pull/51577) | Run finalize build scripts as root | -| 4.48.5 | [#49827](https://github.com/airbytehq/airbyte/pull/49827) | Bypasses CI checks for promoted release candidate PRs. | -| 4.48.4 | [#51003](https://github.com/airbytehq/airbyte/pull/51003) | Install git in the build / test connector container when `--use-cdk-ref` is passed. | -| 4.48.3 | [#50988](https://github.com/airbytehq/airbyte/pull/50988) | Remove deprecated `--no-update` flag from poetry commands | -| 4.48.2 | [#50871](https://github.com/airbytehq/airbyte/pull/50871) | Speed up connector modification detection. | -| 4.48.1 | [#50410](https://github.com/airbytehq/airbyte/pull/50410) | Java connector build: give ownership of built artifacts to the current image user. | -| 4.48.0 | [#49960](https://github.com/airbytehq/airbyte/pull/49960) | Deprecate airbyte-ci format command | -| 4.47.0 | [#49832](https://github.com/airbytehq/airbyte/pull/49462) | Build java connectors from the base image declared in `metadata.yaml`. | -| 4.46.5 | [#49835](https://github.com/airbytehq/airbyte/pull/49835) | Fix connector language discovery for projects with Kotlin Gradle build scripts. | -| 4.46.4 | [#49462](https://github.com/airbytehq/airbyte/pull/49462) | Support Kotlin Gradle build scripts in connectors. | -| 4.46.3 | [#49465](https://github.com/airbytehq/airbyte/pull/49465) | Fix `--use-local-cdk` on rootless connectors. | -| 4.46.2 | [#49136](https://github.com/airbytehq/airbyte/pull/49136) | Fix failed install of python components due to non-root permissions. | -| 4.46.1 | [#49146](https://github.com/airbytehq/airbyte/pull/49146) | Update `crane` image address as the one we were using has been deleted by the maintainer. | -| 4.46.0 | [#48790](https://github.com/airbytehq/airbyte/pull/48790) | Add unit tests step for manifest-only connectors | -| 4.45.3 | [#48927](https://github.com/airbytehq/airbyte/pull/48927) | Fix bug in determine_changelog_entry_comment | -| 4.45.2 | [#48868](https://github.com/airbytehq/airbyte/pull/48868) | Fix ownership issues while using `--use-local-cdk` | -| 4.45.1 | [#48872](https://github.com/airbytehq/airbyte/pull/48872) | Make the `connectors list` command write its output to a JSON file. | -| 4.45.0 | [#48866](https://github.com/airbytehq/airbyte/pull/48866) | Adds `--rc` option to `bump-version` command | -| 4.44.2 | [#48725](https://github.com/airbytehq/airbyte/pull/48725) | up-to-date: specific changelog comment for base image upgrade to rootless. | -| 4.44.1 | [#48836](https://github.com/airbytehq/airbyte/pull/48836) | Manifest-only connector build: give ownership of copied file to the current user. | -| 4.44.0 | [#48818](https://github.com/airbytehq/airbyte/pull/48818) | Use local CDK or CDK ref for manifest only connector build. | -| 4.43.1 | [#48824](https://github.com/airbytehq/airbyte/pull/48824) | Allow uploading CI reports to GCS with fewer permissions set. | -| 4.43.0 | [#36545](https://github.com/airbytehq/airbyte/pull/36545) | Switch to `airbyte` user when available in Python base image. | -| 4.42.2 | [#48404](https://github.com/airbytehq/airbyte/pull/48404) | Include `advanced_auth` in spec migration for manifest-only pipeline | -| 4.42.1 | [#47316](https://github.com/airbytehq/airbyte/pull/47316) | Connector testing: skip incremental acceptance test when the connector is not released. | -| 4.42.0 | [#47386](https://github.com/airbytehq/airbyte/pull/47386) | Version increment check: make sure consecutive RC remain on the same version. | -| 4.41.9 | [#47483](https://github.com/airbytehq/airbyte/pull/47483) | Fix build logic used in `up-to-date` to support any connector language. | -| 4.41.8 | [#47447](https://github.com/airbytehq/airbyte/pull/47447) | Use `cache_ttl` for base image registry listing in `up-to-date`. | -| 4.41.7 | [#47444](https://github.com/airbytehq/airbyte/pull/47444) | Remove redundant `--ignore-connector` error from up-to-date. `--metadata-query` can be used instead. | -| 4.41.6 | [#47308](https://github.com/airbytehq/airbyte/pull/47308) | Connector testing: skip incremental acceptance test when the connector is not released. | -| 4.41.5 | [#47255](https://github.com/airbytehq/airbyte/pull/47255) | Fix `DisableProgressiveRollout` following Dagger API change. | -| 4.41.4 | [#47203](https://github.com/airbytehq/airbyte/pull/47203) | Fix some `with_exec` and entrypoint usage following Dagger upgrade | -| 4.41.3 | [#47189](https://github.com/airbytehq/airbyte/pull/47189) | Fix up-to-date which did not export doc to the right path | -| 4.41.2 | [#47185](https://github.com/airbytehq/airbyte/pull/47185) | Fix the bump version command which did not update the changelog. | -| 4.41.1 | [#46914](https://github.com/airbytehq/airbyte/pull/46914) | Upgrade to Dagger 0.13.3 | -| 4.41.0 | [#46914](https://github.com/airbytehq/airbyte/pull/46914) | Rework the connector rollback pipeline for progressive rollout | -| 4.40.0 | [#46380](https://github.com/airbytehq/airbyte/pull/46380) | The `bump-version` command now allows the `rc` bump type. | -| 4.39.0 | [#46696](https://github.com/airbytehq/airbyte/pull/46696) | Bump PyAirbyte dependency and replace `airbyte-lib-validate-source` CLI command with new `validate` command | -| 4.38.0 | [#46380](https://github.com/airbytehq/airbyte/pull/46380) | `connectors up-to-date` now supports manifest-only connectors! | -| 4.37.0 | [#46380](https://github.com/airbytehq/airbyte/pull/46380) | Include custom components file handling in manifest-only migrations | -| 4.36.2 | [#46278](https://github.com/airbytehq/airbyte/pull/46278) | Fixed a bug in RC rollout and promote not taking `semaphore` | -| 4.36.1 | [#46274](https://github.com/airbytehq/airbyte/pull/46274) | `airbyte-ci format js` respects `.prettierc` and `.prettierignore` | -| 4.36.0 | [#44877](https://github.com/airbytehq/airbyte/pull/44877) | Implement `--promote/rollback-release-candidate` in `connectors publish`. | -| 4.35.6 | [#45632](https://github.com/airbytehq/airbyte/pull/45632) | Add entry to format file ignore list (`destination-*/expected-spec.json`) | -| 4.35.5 | [#45672](https://github.com/airbytehq/airbyte/pull/45672) | Fix docs mount during publish | -| 4.35.4 | [#42584](https://github.com/airbytehq/airbyte/pull/42584) | Mount connector directory to metadata validation | -| 4.35.3 | [#45393](https://github.com/airbytehq/airbyte/pull/45393) | Resolve symlinks in `SimpleDockerStep`. | -| 4.35.2 | [#45360](https://github.com/airbytehq/airbyte/pull/45360) | Updated dependencies. | -| 4.35.1 | [#45160](https://github.com/airbytehq/airbyte/pull/45160) | Remove deps.toml dependency for java connectors. | -| 4.35.0 | [#44879](https://github.com/airbytehq/airbyte/pull/44879) | Mount `components.py` when building manifest-only connector image | -| 4.34.2 | [#44786](https://github.com/airbytehq/airbyte/pull/44786) | Pre-emptively skip archived connectors when searching for modified files | -| 4.34.1 | [#44557](https://github.com/airbytehq/airbyte/pull/44557) | Conditionally propagate parameters in manifest-only migration | -| 4.34.0 | [#44551](https://github.com/airbytehq/airbyte/pull/44551) | `connectors publish` do not push the `latest` tag when the current version is a release candidate. | -| 4.33.1 | [#44465](https://github.com/airbytehq/airbyte/pull/44465) | Ignore version check if only erd folder is changed | -| 4.33.0 | [#44377](https://github.com/airbytehq/airbyte/pull/44377) | Upload connector SBOM to metadata service bucket on publish. | -| 4.32.5 | [#44173](https://github.com/airbytehq/airbyte/pull/44173) | Bug fix for live tests' --should-read-with-state handling. | -| 4.32.4 | [#44025](https://github.com/airbytehq/airbyte/pull/44025) | Ignore third party connectors on `publish`. | -| 4.32.3 | [#44118](https://github.com/airbytehq/airbyte/pull/44118) | Improve error handling in live tests. | -| 4.32.2 | [#43970](https://github.com/airbytehq/airbyte/pull/43970) | Make `connectors publish` early exit if no connectors are selected. | -| 4.32.1 | [#41642](https://github.com/airbytehq/airbyte/pull/41642) | Avoid transient publish failures by increasing `POETRY_REQUESTS_TIMEOUT` and setting retries on `PublishToPythonRegistry`. | -| 4.32.0 | [#43969](https://github.com/airbytehq/airbyte/pull/43969) | Add an `--ignore-connector` option to `up-to-date` | -| 4.31.5 | [#43934](https://github.com/airbytehq/airbyte/pull/43934) | Track deleted files when generating pull-request | -| 4.31.4 | [#43724](https://github.com/airbytehq/airbyte/pull/43724) | Do not send slack message on connector pre-release. | -| 4.31.3 | [#43426](https://github.com/airbytehq/airbyte/pull/43426) | Ignore archived connectors on connector selection from modified files. | -| 4.31.2 | [#43433](https://github.com/airbytehq/airbyte/pull/43433) | Fix 'changed_file' indentation in 'pull-request' command | -| 4.31.1 | [#43442](https://github.com/airbytehq/airbyte/pull/43442) | Resolve type check failure in bump version | -| 4.31.0 | [#42970](https://github.com/airbytehq/airbyte/pull/42970) | Add explicit version set to bump version | -| 4.30.1 | [#43386](https://github.com/airbytehq/airbyte/pull/43386) | Fix 'format' command usage bug in airbyte-enterprise. | -| 4.30.0 | [#42583](https://github.com/airbytehq/airbyte/pull/42583) | Updated dependencies | -| 4.29.0 | [#42576](https://github.com/airbytehq/airbyte/pull/42576) | New command: `migrate-to-manifest-only` | -| 4.28.3 | [#42046](https://github.com/airbytehq/airbyte/pull/42046) | Trigger connector tests on doc change. | -| 4.28.2 | [#43297](https://github.com/airbytehq/airbyte/pull/43297) | `migrate-to-inline_schemas` removes unused schema files and empty schema dirs. | -| 4.28.1 | [#42972](https://github.com/airbytehq/airbyte/pull/42972) | Add airbyte-enterprise support for format commandi | -| 4.28.0 | [#42849](https://github.com/airbytehq/airbyte/pull/42849) | Couple selection of strict-encrypt variants (e vice versa) | -| 4.27.0 | [#42574](https://github.com/airbytehq/airbyte/pull/42574) | Live tests: run from connectors test pipeline for connectors with sandbox connections | -| 4.26.1 | [#42905](https://github.com/airbytehq/airbyte/pull/42905) | Rename the docker cache volume to avoid using the corrupted previous volume. | -| 4.26.0 | [#42849](https://github.com/airbytehq/airbyte/pull/42849) | Send publish failures messages to `#connector-publish-failures` | -| 4.25.4 | [#42463](https://github.com/airbytehq/airbyte/pull/42463) | Add validation before live test runs | -| 4.25.3 | [#42437](https://github.com/airbytehq/airbyte/pull/42437) | Ugrade-cdk: Update to work with Python connectors using poetry | -| 4.25.2 | [#42077](https://github.com/airbytehq/airbyte/pull/42077) | Live/regression tests: add status check for regression test runs | -| 4.25.1 | [#42410](https://github.com/airbytehq/airbyte/pull/42410) | Live/regression tests: disable approval requirement on forks | -| 4.25.0 | [#42044](https://github.com/airbytehq/airbyte/pull/42044) | Live/regression tests: add support for selecting from a subset of connections | -| 4.24.3 | [#42040](https://github.com/airbytehq/airbyte/pull/42040) | Always send regression test approval status check; skip on auto-merge PRs. | -| 4.24.2 | [#41676](https://github.com/airbytehq/airbyte/pull/41676) | Send regression test approval status check when skipped. | -| 4.24.1 | [#41642](https://github.com/airbytehq/airbyte/pull/41642) | Use the AIRBYTE_GITHUB_REPO environment variable to run airbyte-ci in other repos. | -| 4.24.0 | [#41627](https://github.com/airbytehq/airbyte/pull/41627) | Require manual regression test approval for certified connectors | -| 4.23.1 | [#41541](https://github.com/airbytehq/airbyte/pull/41541) | Add support for submodule use-case. | -| 4.23.0 | [#39906](https://github.com/airbytehq/airbyte/pull/39906) | Add manifest only build pipeline | -| 4.22.0 | [#41623](https://github.com/airbytehq/airbyte/pull/41623) | Make `airbyte-ci` run on private forks. | -| 4.21.1 | [#41029](https://github.com/airbytehq/airbyte/pull/41029) | `up-to-date`: mount local docker config to `Syft` to pull private images and benefit from increased DockerHub rate limits. | -| 4.21.0 | [#40547](https://github.com/airbytehq/airbyte/pull/40547) | Make bump-version accept a `--pr-number` option. | -| 4.20.3 | [#40754](https://github.com/airbytehq/airbyte/pull/40754) | Accept and ignore additional args in `migrate-to-poetry` pipeline | -| 4.20.2 | [#40709](https://github.com/airbytehq/airbyte/pull/40709) | Fix use of GH token. | -| 4.20.1 | [#40698](https://github.com/airbytehq/airbyte/pull/40698) | Add live tests evaluation mode options. | -| 4.20.0 | [#38816](https://github.com/airbytehq/airbyte/pull/38816) | Add command for running all live tests (validation + regression). | -| 4.19.0 | [#39600](https://github.com/airbytehq/airbyte/pull/39600) | Productionize the `up-to-date` command | -| 4.18.3 | [#39341](https://github.com/airbytehq/airbyte/pull/39341) | Fix `--use-local-cdk` option: change `no-deps` to `force-reinstall` | -| 4.18.2 | [#39483](https://github.com/airbytehq/airbyte/pull/39483) | Skip IncrementalAcceptanceTests when AcceptanceTests succeed. | -| 4.18.1 | [#39457](https://github.com/airbytehq/airbyte/pull/39457) | Make slugify consistent with live-test | -| 4.18.0 | [#39366](https://github.com/airbytehq/airbyte/pull/39366) | Implement IncrementalAcceptance tests to only fail CI on community connectors when there's an Acceptance tests regression. | -| 4.17.0 | [#39321](https://github.com/airbytehq/airbyte/pull/39321) | Bust the java connector build cache flow to get fresh yum packages on a daily basis. | -| 4.16.0 | [#38772](https://github.com/airbytehq/airbyte/pull/38232) | Add pipeline to replace usage of AirbyteLogger. | -| 4.15.7 | [#38772](https://github.com/airbytehq/airbyte/pull/38772) | Fix regression test connector image retrieval. | -| 4.15.6 | [#38783](https://github.com/airbytehq/airbyte/pull/38783) | Fix a variable access error with `repo_dir` in the `bump-version` command. | -| 4.15.5 | [#38732](https://github.com/airbytehq/airbyte/pull/38732) | Update metadata deploy pipeline to 3.10 | -| 4.15.4 | [#38646](https://github.com/airbytehq/airbyte/pull/38646) | Make airbyte-ci able to test external repos. | -| 4.15.3 | [#38645](https://github.com/airbytehq/airbyte/pull/38645) | Fix typo preventing correct secret mounting on Python connectors integration tests. | -| 4.15.2 | [#38628](https://github.com/airbytehq/airbyte/pull/38628) | Introduce ConnectorTestContext to avoid trying fetching connector secret in the PublishContext. | -| 4.15.1 | [#38615](https://github.com/airbytehq/airbyte/pull/38615) | Do not eagerly fetch connector secrets. | -| 4.15.0 | [#38322](https://github.com/airbytehq/airbyte/pull/38322) | Introduce a SecretStore abstraction to fetch connector secrets from metadata files. | -| 4.14.1 | [#38582](https://github.com/airbytehq/airbyte/pull/38582) | Fixed bugs in `up-to-date` flags, `pull-request` version change logic. | -| 4.14.0 | [#38281](https://github.com/airbytehq/airbyte/pull/38281) | Conditionally run test suites according to `connectorTestSuitesOptions` in metadata files. | -| 4.13.3 | [#38221](https://github.com/airbytehq/airbyte/pull/38221) | Add dagster cloud dev deployment pipeline opitions | -| 4.13.2 | [#38246](https://github.com/airbytehq/airbyte/pull/38246) | Remove invalid connector test step options. | -| 4.13.1 | [#38020](https://github.com/airbytehq/airbyte/pull/38020) | Add `auto_merge` as an internal package to test. | -| 4.13.0 | [#32715](https://github.com/airbytehq/airbyte/pull/32715) | Tag connector metadata with git info | -| 4.12.7 | [#37787](https://github.com/airbytehq/airbyte/pull/37787) | Remove requirements on dockerhub credentials to run QA checks. | -| 4.12.6 | [#36497](https://github.com/airbytehq/airbyte/pull/36497) | Add airbyte-cdk to list of poetry packages for testing | -| 4.12.5 | [#37785](https://github.com/airbytehq/airbyte/pull/37785) | Set the `--yes-auto-update` flag to `True` by default. | -| 4.12.4 | [#37786](https://github.com/airbytehq/airbyte/pull/37786) | (fixed 4.12.2): Do not upload dagger log to GCP when no credentials are available. | -| 4.12.3 | [#37783](https://github.com/airbytehq/airbyte/pull/37783) | Revert 4.12.2 | -| 4.12.2 | [#37778](https://github.com/airbytehq/airbyte/pull/37778) | Do not upload dagger log to GCP when no credentials are available. | -| 4.12.1 | [#37765](https://github.com/airbytehq/airbyte/pull/37765) | Relax the required env var to run in CI and handle their absence gracefully. | -| 4.12.0 | [#37690](https://github.com/airbytehq/airbyte/pull/37690) | Pass custom CI status name in `connectors test` | -| 4.11.0 | [#37641](https://github.com/airbytehq/airbyte/pull/37641) | Updates to run regression tests in GitHub Actions. | -| 4.10.5 | [#37641](https://github.com/airbytehq/airbyte/pull/37641) | Reintroduce changes from 4.10.0 with a fix. | -| 4.10.4 | [#37641](https://github.com/airbytehq/airbyte/pull/37641) | Temporarily revert changes from version 4.10.0 | -| 4.10.3 | [#37615](https://github.com/airbytehq/airbyte/pull/37615) | Fix `KeyError` when running `migrate-to-poetry` | -| 4.10.2 | [#37614](https://github.com/airbytehq/airbyte/pull/37614) | Fix `UnboundLocalError: local variable 'add_changelog_entry_result' referenced before assignment` in `migrate-to-base-image` | -| 4.10.1 | [#37622](https://github.com/airbytehq/airbyte/pull/37622) | Temporarily disable regression tests in CI | -| 4.10.0 | [#37616](https://github.com/airbytehq/airbyte/pull/37616) | Improve modified files comparison when the target branch is from a fork. | -| 4.9.0 | [#37440](https://github.com/airbytehq/airbyte/pull/37440) | Run regression tests with `airbyte-ci connectors test` | -| 4.8.0 | [#37404](https://github.com/airbytehq/airbyte/pull/37404) | Accept a `git-repo-url` option on the `airbyte-ci` root command to checkout forked repo. | -| 4.7.4 | [#37485](https://github.com/airbytehq/airbyte/pull/37485) | Allow java connectors to be written in kotlin. | -| 4.7.3 | [#37101](https://github.com/airbytehq/airbyte/pull/37101) | Pin PyAirbyte version. | -| 4.7.2 | [#36962](https://github.com/airbytehq/airbyte/pull/36962) | Re-enable connector dependencies upload on publish. | -| 4.7.1 | [#36961](https://github.com/airbytehq/airbyte/pull/36961) | Temporarily disable python connectors dependencies upload until we find a schema the data team can work with. | -| 4.7.0 | [#36892](https://github.com/airbytehq/airbyte/pull/36892) | Upload Python connectors dependencies list to GCS on publish. | -| 4.6.5 | [#36722](https://github.com/airbytehq/airbyte/pull/36527) | Fix incorrect pipeline names | -| 4.6.4 | [#36480](https://github.com/airbytehq/airbyte/pull/36480) | Burst the Gradle Task cache if a new CDK version was released | -| 4.6.3 | [#36527](https://github.com/airbytehq/airbyte/pull/36527) | Handle extras as well as groups in `airbyte ci test` [poetry packages] | -| 4.6.2 | [#36220](https://github.com/airbytehq/airbyte/pull/36220) | Allow using `migrate-to-base-image` without PULL_REQUEST_NUMBER | -| 4.6.1 | [#36319](https://github.com/airbytehq/airbyte/pull/36319) | Fix `ValueError` related to PR number in migrate-to-poetry | -| 4.6.0 | [#35583](https://github.com/airbytehq/airbyte/pull/35583) | Implement the `airbyte-ci connectors migrate-to-poetry` command. | -| 4.5.4 | [#36206](https://github.com/airbytehq/airbyte/pull/36206) | Revert poetry cache removal during nightly builds | -| 4.5.3 | [#34586](https://github.com/airbytehq/airbyte/pull/34586) | Extract connector changelog modification logic into its own class | -| 4.5.2 | [#35802](https://github.com/airbytehq/airbyte/pull/35802) | Fix bug with connectors bump-version command | -| 4.5.1 | [#35786](https://github.com/airbytehq/airbyte/pull/35786) | Declare `live_tests` as an internal poetry package. | -| 4.5.0 | [#35784](https://github.com/airbytehq/airbyte/pull/35784) | Format command supports kotlin | -| 4.4.0 | [#35317](https://github.com/airbytehq/airbyte/pull/35317) | Augment java connector reports to include full logs and junit test results | -| 4.3.2 | [#35536](https://github.com/airbytehq/airbyte/pull/35536) | Make QA checks run correctly on `*-strict-encrypt` connectors. | -| 4.3.1 | [#35437](https://github.com/airbytehq/airbyte/pull/35437) | Do not run QA checks on publish, just MetadataValidation. | -| 4.3.0 | [#35438](https://github.com/airbytehq/airbyte/pull/35438) | Optionally disable telemetry with environment variable. | -| 4.2.4 | [#35325](https://github.com/airbytehq/airbyte/pull/35325) | Use `connectors_qa` for QA checks and remove redundant checks. | -| 4.2.3 | [#35322](https://github.com/airbytehq/airbyte/pull/35322) | Declare `connectors_qa` as an internal package for testing. | -| 4.2.2 | [#35364](https://github.com/airbytehq/airbyte/pull/35364) | Fix connector tests following gradle changes in #35307. | -| 4.2.1 | [#35204](https://github.com/airbytehq/airbyte/pull/35204) | Run `poetry check` before `poetry install` on poetry package install. | -| 4.2.0 | [#35103](https://github.com/airbytehq/airbyte/pull/35103) | Java 21 support. | -| 4.1.4 | [#35039](https://github.com/airbytehq/airbyte/pull/35039) | Fix bug which prevented gradle test reports from being added. | -| 4.1.3 | [#35010](https://github.com/airbytehq/airbyte/pull/35010) | Use `poetry install --no-root` in the builder container. | -| 4.1.2 | [#34945](https://github.com/airbytehq/airbyte/pull/34945) | Only install main dependencies when running poetry install. | -| 4.1.1 | [#34430](https://github.com/airbytehq/airbyte/pull/34430) | Speed up airbyte-ci startup (and airbyte-ci format). | -| 4.1.0 | [#34923](https://github.com/airbytehq/airbyte/pull/34923) | Include gradle test reports in HTML connector test report. | -| 4.0.0 | [#34736](https://github.com/airbytehq/airbyte/pull/34736) | Run poe tasks declared in internal poetry packages. | -| 3.10.4 | [#34867](https://github.com/airbytehq/airbyte/pull/34867) | Remove connector ops team | -| 3.10.3 | [#34836](https://github.com/airbytehq/airbyte/pull/34836) | Add check for python registry publishing enabled for certified python sources. | -| 3.10.2 | [#34044](https://github.com/airbytehq/airbyte/pull/34044) | Add pypi validation testing. | -| 3.10.1 | [#34756](https://github.com/airbytehq/airbyte/pull/34756) | Enable connectors tests in draft PRs. | -| 3.10.0 | [#34606](https://github.com/airbytehq/airbyte/pull/34606) | Allow configuration of separate check URL to check whether package exists already. | -| 3.9.0 | [#34606](https://github.com/airbytehq/airbyte/pull/34606) | Allow configuration of python registry URL via environment variable. | -| 3.8.1 | [#34607](https://github.com/airbytehq/airbyte/pull/34607) | Improve gradle dependency cache volume protection. | -| 3.8.0 | [#34316](https://github.com/airbytehq/airbyte/pull/34316) | Expose Dagger engine image name in `--ci-requirements` and add `--ci-requirements` to the `airbyte-ci` root command group. | -| 3.7.3 | [#34560](https://github.com/airbytehq/airbyte/pull/34560) | Simplify Gradle task execution framework by removing local maven repo support. | -| 3.7.2 | [#34555](https://github.com/airbytehq/airbyte/pull/34555) | Override secret masking in some very specific special cases. | -| 3.7.1 | [#34441](https://github.com/airbytehq/airbyte/pull/34441) | Support masked secret scrubbing for java CDK v0.15+ | -| 3.7.0 | [#34343](https://github.com/airbytehq/airbyte/pull/34343) | allow running connector upgrade_cdk for java connectors | -| 3.6.1 | [#34490](https://github.com/airbytehq/airbyte/pull/34490) | Fix inconsistent dagger log path typing | -| 3.6.0 | [#34111](https://github.com/airbytehq/airbyte/pull/34111) | Add python registry publishing | -| 3.5.3 | [#34339](https://github.com/airbytehq/airbyte/pull/34339) | only do minimal changes on a connector version_bump | -| 3.5.2 | [#34381](https://github.com/airbytehq/airbyte/pull/34381) | Bind a sidecar docker host for `airbyte-ci test` | -| 3.5.1 | [#34321](https://github.com/airbytehq/airbyte/pull/34321) | Upgrade to Dagger 0.9.6 . | -| 3.5.0 | [#33313](https://github.com/airbytehq/airbyte/pull/33313) | Pass extra params after Gradle tasks. | -| 3.4.2 | [#34301](https://github.com/airbytehq/airbyte/pull/34301) | Pass extra params after Gradle tasks. | -| 3.4.1 | [#34067](https://github.com/airbytehq/airbyte/pull/34067) | Use dagster-cloud 1.5.7 for deploy | -| 3.4.0 | [#34276](https://github.com/airbytehq/airbyte/pull/34276) | Introduce `--only-step` option for connector tests. | -| 3.3.0 | [#34218](https://github.com/airbytehq/airbyte/pull/34218) | Introduce `--ci-requirements` option for client defined CI runners. | -| 3.2.0 | [#34050](https://github.com/airbytehq/airbyte/pull/34050) | Connector test steps can take extra parameters | -| 3.1.3 | [#34136](https://github.com/airbytehq/airbyte/pull/34136) | Fix issue where dagger excludes were not being properly applied | -| 3.1.2 | [#33972](https://github.com/airbytehq/airbyte/pull/33972) | Remove secrets scrubbing hack for --is-local and other small tweaks. | -| 3.1.1 | [#33979](https://github.com/airbytehq/airbyte/pull/33979) | Fix AssertionError on report existence again | -| 3.1.0 | [#33994](https://github.com/airbytehq/airbyte/pull/33994) | Log more context information in CI. | -| 3.0.2 | [#33987](https://github.com/airbytehq/airbyte/pull/33987) | Fix type checking issue when running --help | -| 3.0.1 | [#33981](https://github.com/airbytehq/airbyte/pull/33981) | Fix issues with deploying dagster, pin pendulum version in dagster-cli install | -| 3.0.0 | [#33582](https://github.com/airbytehq/airbyte/pull/33582) | Upgrade to Dagger 0.9.5 | -| 2.14.3 | [#33964](https://github.com/airbytehq/airbyte/pull/33964) | Reintroduce mypy with fixes for AssertionError on publish and missing report URL on connector test commit status. | -| 2.14.2 | [#33954](https://github.com/airbytehq/airbyte/pull/33954) | Revert mypy changes | -| 2.14.1 | [#33956](https://github.com/airbytehq/airbyte/pull/33956) | Exclude pnpm lock files from auto-formatting | -| 2.14.0 | [#33941](https://github.com/airbytehq/airbyte/pull/33941) | Enable in-connector normalization in destination-postgres | -| 2.13.1 | [#33920](https://github.com/airbytehq/airbyte/pull/33920) | Report different sentry environments | -| 2.13.0 | [#33784](https://github.com/airbytehq/airbyte/pull/33784) | Make `airbyte-ci test` able to run any poetry command | -| 2.12.0 | [#33313](https://github.com/airbytehq/airbyte/pull/33313) | Add upgrade CDK command | -| 2.11.0 | [#32188](https://github.com/airbytehq/airbyte/pull/32188) | Add -x option to connector test to allow for skipping steps | -| 2.10.12 | [#33419](https://github.com/airbytehq/airbyte/pull/33419) | Make ClickPipelineContext handle dagger logging. | -| 2.10.11 | [#33497](https://github.com/airbytehq/airbyte/pull/33497) | Consider nested .gitignore rules in format. | -| 2.10.10 | [#33449](https://github.com/airbytehq/airbyte/pull/33449) | Add generated metadata models to the default format ignore list. | -| 2.10.9 | [#33370](https://github.com/airbytehq/airbyte/pull/33370) | Fix bug that broke airbyte-ci test | -| 2.10.8 | [#33249](https://github.com/airbytehq/airbyte/pull/33249) | Exclude git ignored files from formatting. | -| 2.10.7 | [#33248](https://github.com/airbytehq/airbyte/pull/33248) | Fix bug which broke airbyte-ci connectors tests when optional DockerHub credentials env vars are not set. | -| 2.10.6 | [#33170](https://github.com/airbytehq/airbyte/pull/33170) | Remove Dagger logs from console output of `format`. | -| 2.10.5 | [#33097](https://github.com/airbytehq/airbyte/pull/33097) | Improve `format` performances, exit with 1 status code when `fix` changes files. | -| 2.10.4 | [#33206](https://github.com/airbytehq/airbyte/pull/33206) | Add "-y/--yes" Flag to allow preconfirmation of prompts | -| 2.10.3 | [#33080](https://github.com/airbytehq/airbyte/pull/33080) | Fix update failing due to SSL error on install. | -| 2.10.2 | [#33008](https://github.com/airbytehq/airbyte/pull/33008) | Fix local `connector build`. | -| 2.10.1 | [#32928](https://github.com/airbytehq/airbyte/pull/32928) | Fix BuildConnectorImages constructor. | -| 2.10.0 | [#32819](https://github.com/airbytehq/airbyte/pull/32819) | Add `--tag` option to connector build. | -| 2.9.0 | [#32816](https://github.com/airbytehq/airbyte/pull/32816) | Add `--architecture` option to connector build. | -| 2.8.1 | [#32999](https://github.com/airbytehq/airbyte/pull/32999) | Improve Java code formatting speed | -| 2.8.0 | [#31930](https://github.com/airbytehq/airbyte/pull/31930) | Move pipx install to `airbyte-ci-dev`, and add auto-update feature targeting binary | -| 2.7.3 | [#32847](https://github.com/airbytehq/airbyte/pull/32847) | Improve --modified behaviour for pull requests. | -| 2.7.2 | [#32839](https://github.com/airbytehq/airbyte/pull/32839) | Revert changes in v2.7.1. | -| 2.7.1 | [#32806](https://github.com/airbytehq/airbyte/pull/32806) | Improve --modified behaviour for pull requests. | -| 2.7.0 | [#31930](https://github.com/airbytehq/airbyte/pull/31930) | Merge airbyte-ci-internal into airbyte-ci | -| 2.6.0 | [#31831](https://github.com/airbytehq/airbyte/pull/31831) | Add `airbyte-ci format` commands, remove connector-specific formatting check | -| 2.5.9 | [#32427](https://github.com/airbytehq/airbyte/pull/32427) | Re-enable caching for source-postgres | -| 2.5.8 | [#32402](https://github.com/airbytehq/airbyte/pull/32402) | Set Dagger Cloud token for airbyters only | -| 2.5.7 | [#31628](https://github.com/airbytehq/airbyte/pull/31628) | Add ClickPipelineContext class | -| 2.5.6 | [#32139](https://github.com/airbytehq/airbyte/pull/32139) | Test coverage report on Python connector UnitTest. | -| 2.5.5 | [#32114](https://github.com/airbytehq/airbyte/pull/32114) | Create cache mount for `/var/lib/docker` to store images in `dind` context. | -| 2.5.4 | [#32090](https://github.com/airbytehq/airbyte/pull/32090) | Do not cache `docker login`. | -| 2.5.3 | [#31974](https://github.com/airbytehq/airbyte/pull/31974) | Fix latest CDK install and pip cache mount on connector install. | -| 2.5.2 | [#31871](https://github.com/airbytehq/airbyte/pull/31871) | Deactivate PR comments, add HTML report links to the PR status when its ready. | -| 2.5.1 | [#31774](https://github.com/airbytehq/airbyte/pull/31774) | Add a docker configuration check on `airbyte-ci` startup. | -| 2.5.0 | [#31766](https://github.com/airbytehq/airbyte/pull/31766) | Support local connectors secrets. | -| 2.4.0 | [#31716](https://github.com/airbytehq/airbyte/pull/31716) | Enable pre-release publish with local CDK. | -| 2.3.1 | [#31748](https://github.com/airbytehq/airbyte/pull/31748) | Use AsyncClick library instead of base Click. | -| 2.3.0 | [#31699](https://github.com/airbytehq/airbyte/pull/31699) | Support optional concurrent CAT execution. | -| 2.2.6 | [#31752](https://github.com/airbytehq/airbyte/pull/31752) | Only authenticate when secrets are available. | -| 2.2.5 | [#31718](https://github.com/airbytehq/airbyte/pull/31718) | Authenticate the sidecar docker daemon to DockerHub. | -| 2.2.4 | [#31535](https://github.com/airbytehq/airbyte/pull/31535) | Improve gradle caching when building java connectors. | -| 2.2.3 | [#31688](https://github.com/airbytehq/airbyte/pull/31688) | Fix failing `CheckBaseImageUse` step when not running on PR. | -| 2.2.2 | [#31659](https://github.com/airbytehq/airbyte/pull/31659) | Support builds on x86_64 platform | -| 2.2.1 | [#31653](https://github.com/airbytehq/airbyte/pull/31653) | Fix CheckBaseImageIsUsed failing on non certified connectors. | -| 2.2.0 | [#30527](https://github.com/airbytehq/airbyte/pull/30527) | Add a new check for python connectors to make sure certified connectors use our base image. | -| 2.1.1 | [#31488](https://github.com/airbytehq/airbyte/pull/31488) | Improve `airbyte-ci` start time with Click Lazy load | -| 2.1.0 | [#31412](https://github.com/airbytehq/airbyte/pull/31412) | Run airbyte-ci from any where in airbyte project | -| 2.0.4 | [#31487](https://github.com/airbytehq/airbyte/pull/31487) | Allow for third party connector selections | -| 2.0.3 | [#31525](https://github.com/airbytehq/airbyte/pull/31525) | Refactor folder structure | -| 2.0.2 | [#31533](https://github.com/airbytehq/airbyte/pull/31533) | Pip cache volume by python version. | -| 2.0.1 | [#31545](https://github.com/airbytehq/airbyte/pull/31545) | Reword the changelog entry when using `migrate-to-base-image`. | -| 2.0.0 | [#31424](https://github.com/airbytehq/airbyte/pull/31424) | Remove `airbyte-ci connectors format` command. | -| 1.9.4 | [#31478](https://github.com/airbytehq/airbyte/pull/31478) | Fix running tests for connector-ops package. | -| 1.9.3 | [#31457](https://github.com/airbytehq/airbyte/pull/31457) | Improve the connector documentation for connectors migrated to our base image. | -| 1.9.2 | [#31426](https://github.com/airbytehq/airbyte/pull/31426) | Concurrent execution of java connectors tests. | -| 1.9.1 | [#31455](https://github.com/airbytehq/airbyte/pull/31455) | Fix `None` docker credentials on publish. | -| 1.9.0 | [#30520](https://github.com/airbytehq/airbyte/pull/30520) | New commands: `bump-version`, `upgrade_base_image`, `migrate-to-base-image`. | -| 1.8.0 | [#30520](https://github.com/airbytehq/airbyte/pull/30520) | New commands: `bump-version`, `upgrade_base_image`, `migrate-to-base-image`. | -| 1.7.2 | [#31343](https://github.com/airbytehq/airbyte/pull/31343) | Bind Pytest integration tests to a dockerhost. | -| 1.7.1 | [#31332](https://github.com/airbytehq/airbyte/pull/31332) | Disable Gradle step caching on source-postgres. | -| 1.7.0 | [#30526](https://github.com/airbytehq/airbyte/pull/30526) | Implement pre/post install hooks support. | -| 1.6.0 | [#30474](https://github.com/airbytehq/airbyte/pull/30474) | Test connector inside their containers. | -| 1.5.1 | [#31227](https://github.com/airbytehq/airbyte/pull/31227) | Use python 3.11 in amazoncorretto-bazed gradle containers, run 'test' gradle task instead of 'check'. | -| 1.5.0 | [#30456](https://github.com/airbytehq/airbyte/pull/30456) | Start building Python connectors using our base images. | -| 1.4.6 | [ #31087](https://github.com/airbytehq/airbyte/pull/31087) | Throw error if airbyte-ci tools is out of date | -| 1.4.5 | [#31133](https://github.com/airbytehq/airbyte/pull/31133) | Fix bug when building containers using `with_integration_base_java_and_normalization`. | -| 1.4.4 | [#30743](https://github.com/airbytehq/airbyte/pull/30743) | Add `--disable-report-auto-open` and `--use-host-gradle-dist-tar` to allow gradle integration. | -| 1.4.3 | [#30595](https://github.com/airbytehq/airbyte/pull/30595) | Add --version and version check | -| 1.4.2 | [#30595](https://github.com/airbytehq/airbyte/pull/30595) | Remove directory name requirement | -| 1.4.1 | [#30595](https://github.com/airbytehq/airbyte/pull/30595) | Load base migration guide into QA Test container for strict encrypt variants | -| 1.4.0 | [#30330](https://github.com/airbytehq/airbyte/pull/30330) | Add support for pyproject.toml as the prefered entry point for a connector package | -| 1.3.0 | [#30461](https://github.com/airbytehq/airbyte/pull/30461) | Add `--use-local-cdk` flag to all connectors commands | -| 1.2.3 | [#30477](https://github.com/airbytehq/airbyte/pull/30477) | Fix a test regression introduced the previous version. | -| 1.2.2 | [#30438](https://github.com/airbytehq/airbyte/pull/30438) | Add workaround to always stream logs properly with --is-local. | -| 1.2.1 | [#30384](https://github.com/airbytehq/airbyte/pull/30384) | Java connector test performance fixes. | -| 1.2.0 | [#30330](https://github.com/airbytehq/airbyte/pull/30330) | Add `--metadata-query` option to connectors command | -| 1.1.3 | [#30314](https://github.com/airbytehq/airbyte/pull/30314) | Stop patching gradle files to make them work with airbyte-ci. | -| 1.1.2 | [#30279](https://github.com/airbytehq/airbyte/pull/30279) | Fix correctness issues in layer caching by making atomic execution groupings | -| 1.1.1 | [#30252](https://github.com/airbytehq/airbyte/pull/30252) | Fix redundancies and broken logic in GradleTask, to speed up the CI runs. | -| 1.1.0 | [#29509](https://github.com/airbytehq/airbyte/pull/29509) | Refactor the airbyte-ci test command to run tests on any poetry package. | -| 1.0.0 | [#28000](https://github.com/airbytehq/airbyte/pull/29232) | Remove release stages in favor of support level from airbyte-ci. | -| 0.5.0 | [#28000](https://github.com/airbytehq/airbyte/pull/28000) | Run connector acceptance tests with dagger-in-dagger. | -| 0.4.7 | [#29156](https://github.com/airbytehq/airbyte/pull/29156) | Improve how we check existence of requirement.txt or setup.py file to not raise early pip install errors. | -| 0.4.6 | [#28729](https://github.com/airbytehq/airbyte/pull/28729) | Use keyword args instead of positional argument for optional paramater in Dagger's API | -| 0.4.5 | [#29034](https://github.com/airbytehq/airbyte/pull/29034) | Disable Dagger terminal UI when running publish. | -| 0.4.4 | [#29064](https://github.com/airbytehq/airbyte/pull/29064) | Make connector modified files a frozen set. | -| 0.4.3 | [#29033](https://github.com/airbytehq/airbyte/pull/29033) | Disable dependency scanning for Java connectors. | -| 0.4.2 | [#29030](https://github.com/airbytehq/airbyte/pull/29030) | Make report path always have the same prefix: `airbyte-ci/`. | -| 0.4.1 | [#28855](https://github.com/airbytehq/airbyte/pull/28855) | Improve the selected connectors detection for connectors commands. | -| 0.4.0 | [#28947](https://github.com/airbytehq/airbyte/pull/28947) | Show Dagger Cloud run URLs in CI | -| 0.3.2 | [#28789](https://github.com/airbytehq/airbyte/pull/28789) | Do not consider empty reports as successfull. | -| 0.3.1 | [#28938](https://github.com/airbytehq/airbyte/pull/28938) | Handle 5 status code on MetadataUpload as skipped | -| 0.3.0 | [#28869](https://github.com/airbytehq/airbyte/pull/28869) | Enable the Dagger terminal UI on local `airbyte-ci` execution | -| 0.2.3 | [#28907](https://github.com/airbytehq/airbyte/pull/28907) | Make dagger-in-dagger work for `airbyte-ci tests` command | -| 0.2.2 | [#28897](https://github.com/airbytehq/airbyte/pull/28897) | Sentry: Ignore error logs without exceptions from reporting | -| 0.2.1 | [#28767](https://github.com/airbytehq/airbyte/pull/28767) | Improve pytest step result evaluation to prevent false negative/positive. | -| 0.2.0 | [#28857](https://github.com/airbytehq/airbyte/pull/28857) | Add the `airbyte-ci tests` command to run the test suite on any `airbyte-ci` poetry package. | -| 0.1.1 | [#28858](https://github.com/airbytehq/airbyte/pull/28858) | Increase the max duration of Connector Package install to 20mn. | -| 0.1.0 | | Alpha version not in production yet. All the commands described in this doc are available. | - -## More info - -This project is owned by the Connectors Operations team. We share project updates and remaining -stories before its release to production in this -[EPIC](https://github.com/airbytehq/airbyte/issues/24403). - -# Troubleshooting - -## Commands - -### `make tools.airbyte-ci.check` - -This command checks if the `airbyte-ci` command is appropriately installed. - -### `make tools.airbyte-ci.clean` - -This command removes the `airbyte-ci` command from your system. - -## Common issues - -### `airbyte-ci` is not found - -If you get the following error when running `airbyte-ci`: - -```bash -$ airbyte-ci -zsh: command not found: airbyte-ci -``` - -It means that the `airbyte-ci` command is not in your PATH. - -Try running - -```bash -make make tools.airbyte-ci.check -``` - -For some hints on how to fix this. - -But when in doubt it can be best to run - -```bash -make tools.airbyte-ci.clean -``` - -Then reinstall the CLI with - -```bash -make tools.airbyte-ci.install -``` - -## Development - -### `airbyte-ci` is not found - -To fix this, you can either: - -- Ensure that airbyte-ci is installed with pipx. Run `pipx list` to check if airbyte-ci is - installed. -- Run `pipx ensurepath` to add the pipx binary directory to your PATH. -- Add the pipx binary directory to your PATH manually. The pipx binary directory is usually - `~/.local/bin`. - -### python3.10 not found - -If you get the following error when running -`pipx install --editable --force --python=python3.10 airbyte-ci/connectors/pipelines/`: - -```bash -$ pipx install --editable --force --python=python3.10 airbyte-ci/connectors/pipelines/ -Error: Python 3.10 not found on your system. -``` - -It means that you don't have Python 3.10 installed on your system. - -To fix this, you can either: - -- Install Python 3.10 with pyenv. Run `pyenv install 3.10` to install the latest Python version. -- Install Python 3.10 with your system package manager. For instance, on Ubuntu you can run - `sudo apt install python3.10`. -- Ensure that Python 3.10 is in your PATH. Run `which python3.10` to check if Python 3.10 is - installed and in your PATH. - -### Any type of pipeline failure - -First you should check that the version of the CLI you are using is the latest one. You can check -the version of the CLI with the `--version` option: - -```bash -$ airbyte-ci --version -airbyte-ci, version 0.1.0 -``` - -and compare it with the version in the pyproject.toml file: - -```bash -$ cat airbyte-ci/connectors/pipelines/pyproject.toml | grep version -``` - -If you get any type of pipeline failure, you can run the pipeline with the `--show-dagger-logs` -option to get more information about the failure. - -```bash -$ airbyte-ci --show-dagger-logs connectors --name=source-pokeapi test -``` - -and when in doubt, you can reinstall the CLI with the `--force` option: - -```bash -$ pipx reinstall pipelines --force -``` diff --git a/airbyte-ci/connectors/pipelines/pipelines/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/__init__.py deleted file mode 100644 index 4b1a6ecc74dd..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""The pipelines package.""" -import logging -import os -from typing import Union -from rich.logging import RichHandler - -from .helpers import sentry_utils - -sentry_utils.initialize() - -logging.getLogger("requests").setLevel(logging.WARNING) -logging.getLogger("urllib3").setLevel(logging.WARNING) -logging.getLogger("httpx").setLevel(logging.WARNING) - -# RichHandler does not work great in the CI environment, so we use a StreamHandler instead -logging_handler: Union[RichHandler, logging.StreamHandler] = RichHandler(rich_tracebacks=True) if "CI" not in os.environ else logging.StreamHandler() - - -logging.basicConfig( - level=logging.INFO, - format="%(name)s: %(message)s", - datefmt="[%X]", - handlers=[logging_handler], -) - -main_logger = logging.getLogger(__name__) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/commands.py deleted file mode 100644 index b0a7f223af3a..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/commands.py +++ /dev/null @@ -1,85 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from typing import List - -import asyncclick as click -import dagger - -from pipelines import main_logger -from pipelines.airbyte_ci.connectors.build_image.steps import run_connector_build_pipeline -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.airbyte_ci.connectors.pipeline import run_connectors_pipelines -from pipelines.cli.dagger_pipeline_command import DaggerPipelineCommand -from pipelines.consts import BUILD_PLATFORMS, LOCAL_BUILD_PLATFORM - - -@click.command(cls=DaggerPipelineCommand, help="Build all images for the selected connectors.") -@click.option( - "--use-host-gradle-dist-tar", - is_flag=True, - help="Use gradle distTar output from host for java connectors.", - default=False, - type=bool, -) -@click.option( - "-a", - "--architecture", - "build_architectures", - help="Architecture for which to build the connector image. If not specified, the image will be built for the local architecture.", - multiple=True, - default=[LOCAL_BUILD_PLATFORM], - type=click.Choice(BUILD_PLATFORMS, case_sensitive=True), -) -@click.option( - "-t", - "--tag", - help="The tag to use for the built image.", - default="dev", - type=str, -) -@click.pass_context -async def build(ctx: click.Context, use_host_gradle_dist_tar: bool, build_architectures: List[str], tag: str) -> bool: - """Runs a build pipeline for the selected connectors.""" - build_platforms = [dagger.Platform(architecture) for architecture in build_architectures] - main_logger.info(f"Building connectors for {build_platforms}, use --architecture to change this.") - connectors_contexts = [ - ConnectorContext( - pipeline_name=f"Build connector {connector.technical_name}", - connector=connector, - is_local=ctx.obj["is_local"], - git_branch=ctx.obj["git_branch"], - git_revision=ctx.obj["git_revision"], - diffed_branch=ctx.obj["diffed_branch"], - git_repo_url=ctx.obj["git_repo_url"], - ci_report_bucket=ctx.obj["ci_report_bucket_name"], - report_output_prefix=ctx.obj["report_output_prefix"], - gha_workflow_run_url=ctx.obj.get("gha_workflow_run_url"), - dagger_logs_url=ctx.obj.get("dagger_logs_url"), - pipeline_start_timestamp=ctx.obj.get("pipeline_start_timestamp"), - ci_context=ctx.obj.get("ci_context"), - ci_gcp_credentials=ctx.obj["ci_gcp_credentials"], - use_local_cdk=ctx.obj.get("use_local_cdk"), - use_cdk_ref=ctx.obj.get("use_cdk_ref"), - enable_report_auto_open=ctx.obj.get("enable_report_auto_open"), - use_host_gradle_dist_tar=use_host_gradle_dist_tar, - s3_build_cache_access_key_id=ctx.obj.get("s3_build_cache_access_key_id"), - s3_build_cache_secret_key=ctx.obj.get("s3_build_cache_secret_key"), - targeted_platforms=build_platforms, - ) - for connector in ctx.obj["selected_connectors_with_modified_files"] - ] - if use_host_gradle_dist_tar and not ctx.obj["is_local"]: - raise Exception("flag --use-host-gradle-dist-tar requires --is-local") - await run_connectors_pipelines( - connectors_contexts, - run_connector_build_pipeline, - "Build Pipeline", - ctx.obj["concurrency"], - ctx.obj["dagger_logs_path"], - ctx.obj["execute_timeout"], - tag, - ) - - return True diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/pipeline.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/pipeline.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/__init__.py deleted file mode 100644 index 5e2fa42230b9..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/__init__.py +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -"""This module groups factory like functions to dispatch builds steps according to the connector language.""" - -from __future__ import annotations - -import anyio -from connector_ops.utils import ConnectorLanguage # type: ignore -from pipelines.airbyte_ci.connectors.build_image.steps import java_connectors, python_connectors, manifest_only_connectors -from pipelines.airbyte_ci.connectors.build_image.steps.common import LoadContainerToLocalDockerHost, StepStatus -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.airbyte_ci.connectors.reports import ConnectorReport, Report -from pipelines.models.steps import StepResult - - -class NoBuildStepForLanguageError(Exception): - pass - - -LANGUAGE_BUILD_CONNECTOR_MAPPING = { - ConnectorLanguage.PYTHON: python_connectors.run_connector_build, - ConnectorLanguage.LOW_CODE: python_connectors.run_connector_build, - ConnectorLanguage.MANIFEST_ONLY: manifest_only_connectors.run_connector_build, - ConnectorLanguage.JAVA: java_connectors.run_connector_build, -} - - -async def run_connector_build(context: ConnectorContext) -> StepResult: - """Run a build pipeline for a single connector.""" - if context.connector.language not in LANGUAGE_BUILD_CONNECTOR_MAPPING: - raise NoBuildStepForLanguageError(f"No build step for connector language {context.connector.language}.") - return await LANGUAGE_BUILD_CONNECTOR_MAPPING[context.connector.language](context) - - -async def run_connector_build_pipeline(context: ConnectorContext, semaphore: anyio.Semaphore, image_tag: str) -> Report: - """Run a build pipeline for a single connector. - - Args: - context (ConnectorContext): The initialized connector context. - semaphore (anyio.Semaphore): The semaphore to use to limit the number of concurrent builds. - image_tag (str): The tag to use for the built image. - Returns: - ConnectorReport: The reports holding builds results. - """ - step_results = [] - async with semaphore: - async with context: - build_result = await run_connector_build(context) - per_platform_built_containers = build_result.output - step_results.append(build_result) - if context.is_local and build_result.status is StepStatus.SUCCESS: - load_image_result = await LoadContainerToLocalDockerHost(context, image_tag).run(per_platform_built_containers) - step_results.append(load_image_result) - report = ConnectorReport(context, step_results, name="BUILD RESULTS") - context.report = report - return report diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/build_customization.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/build_customization.py deleted file mode 100644 index d0b5fa8acb42..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/build_customization.py +++ /dev/null @@ -1,104 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import importlib -from logging import Logger -from types import ModuleType -from typing import List, Optional - -from connector_ops.utils import Connector # type: ignore -from dagger import Container - -BUILD_CUSTOMIZATION_MODULE_NAME = "build_customization" -BUILD_CUSTOMIZATION_SPEC_NAME = f"{BUILD_CUSTOMIZATION_MODULE_NAME}.py" -DEFAULT_MAIN_FILE_NAME = "main.py" - - -def get_build_customization_module(connector: Connector) -> Optional[ModuleType]: - """Import the build_customization.py file from the connector directory if it exists. - Returns: - Optional[ModuleType]: The build_customization.py module if it exists, None otherwise. - """ - build_customization_spec_path = connector.code_directory / BUILD_CUSTOMIZATION_SPEC_NAME - - if not build_customization_spec_path.exists() or not ( - build_customization_spec := importlib.util.spec_from_file_location( - f"{connector.code_directory.name}_{BUILD_CUSTOMIZATION_MODULE_NAME}", build_customization_spec_path - ) - ): - return None - - if build_customization_spec.loader is None: - return None - - build_customization_module = importlib.util.module_from_spec(build_customization_spec) - build_customization_spec.loader.exec_module(build_customization_module) - return build_customization_module - - -def get_main_file_name(connector: Connector) -> str: - """Get the main file name from the build_customization.py module if it exists, DEFAULT_MAIN_FILE_NAME otherwise. - - Args: - connector (Connector): The connector to build. - - Returns: - str: The main file name. - """ - build_customization_module = get_build_customization_module(connector) - - return ( - build_customization_module.MAIN_FILE_NAME - if build_customization_module and hasattr(build_customization_module, "MAIN_FILE_NAME") - else DEFAULT_MAIN_FILE_NAME - ) - - -def get_entrypoint(connector: Connector) -> List[str]: - main_file_name = get_main_file_name(connector) - return ["python", f"/airbyte/integration_code/{main_file_name}"] - - -def apply_airbyte_entrypoint(connector_container: Container, connector: Connector) -> Container: - entrypoint = get_entrypoint(connector) - - return connector_container.with_env_variable("AIRBYTE_ENTRYPOINT", " ".join(entrypoint)).with_entrypoint(entrypoint) - - -async def pre_install_hooks(connector: Connector, base_container: Container, logger: Logger) -> Container: - """Run the pre_connector_install hook if it exists in the build_customization.py module. - It will mutate the base_container and return it. - - Args: - connector (Connector): The connector to build. - base_container (Container): The base container to mutate. - logger (Logger): The logger to use. - - Returns: - Container: The mutated base_container. - """ - build_customization_module = get_build_customization_module(connector) - if build_customization_module and hasattr(build_customization_module, "pre_connector_install"): - base_container = await build_customization_module.pre_connector_install(base_container) - logger.info(f"Connector {connector.technical_name} pre install hook executed.") - return base_container - - -async def post_install_hooks(connector: Connector, connector_container: Container, logger: Logger) -> Container: - """Run the post_connector_install hook if it exists in the build_customization.py module. - It will mutate the connector_container and return it. - - Args: - connector (Connector): The connector to build. - connector_container (Container): The connector container to mutate. - logger (Logger): The logger to use. - - Returns: - Container: The mutated connector_container. - """ - build_customization_module = get_build_customization_module(connector) - if build_customization_module and hasattr(build_customization_module, "post_connector_install"): - connector_container = await build_customization_module.post_connector_install(connector_container) - logger.info(f"Connector {connector.technical_name} post install hook executed.") - return connector_container diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/common.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/common.py deleted file mode 100644 index e0e3c76c27fb..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/common.py +++ /dev/null @@ -1,147 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -from abc import ABC -from typing import TYPE_CHECKING - -import docker # type: ignore -from click import UsageError -from connector_ops.utils import Connector # type: ignore -from dagger import Container, ExecError, Platform, QueryError - -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.helpers.utils import export_container_to_tarball, sh_dash_c -from pipelines.models.steps import Step, StepResult, StepStatus - -if TYPE_CHECKING: - from typing import Any, Type, TypeVar - - T = TypeVar("T", bound="BuildConnectorImagesBase") - - -def apply_airbyte_docker_labels(connector_container: Container, connector: Connector) -> Container: - return connector_container.with_label("io.airbyte.version", connector.metadata["dockerImageTag"]).with_label( - "io.airbyte.name", connector.metadata["dockerRepository"] - ) - - -class BuildConnectorImagesBase(Step, ABC): - """ - A step to build connector images for a set of platforms. - """ - - context: ConnectorContext - USER = "airbyte" - - @property - def title(self) -> str: - return f"Build {self.context.connector.technical_name} docker image for platform(s) {', '.join(self.build_platforms)}" - - def __init__(self, context: ConnectorContext) -> None: - self.build_platforms = context.targeted_platforms - super().__init__(context) - - async def _run(self, *args: Any) -> StepResult: - build_results_per_platform = {} - for platform in self.build_platforms: - try: - connector_container = await self._build_connector(platform, *args) - connector_container = apply_airbyte_docker_labels(connector_container, self.context.connector) - try: - await connector_container.with_exec(["spec"], use_entrypoint=True) - except ExecError as e: - return StepResult( - step=self, - status=StepStatus.FAILURE, - stderr=str(e), - stdout=f"Failed to run the spec command on the connector container for platform {platform}.", - exc_info=e, - ) - build_results_per_platform[platform] = connector_container - except (QueryError, UsageError) as e: - return StepResult( - step=self, status=StepStatus.FAILURE, stderr=f"Failed to build connector image for platform {platform}: {e}" - ) - success_message = ( - f"The {self.context.connector.technical_name} docker image " - f"was successfully built for platform(s) {', '.join(self.build_platforms)}" - ) - return StepResult(step=self, status=StepStatus.SUCCESS, stdout=success_message, output=build_results_per_platform) - - async def _build_connector(self, platform: Platform, *args: Any, **kwargs: Any) -> Container: - """Implement the generation of the image for the platform and return the corresponding container. - - Returns: - Container: The container to package as a docker image for this platform. - """ - raise NotImplementedError("`BuildConnectorImagesBase`s must define a '_build_connector' attribute.") - - @classmethod - async def get_image_user(cls: Type[T], base_container: Container) -> str: - """If the base image in use has a user named 'airbyte', we will use it as the user for the connector image. - - Args: - base_container (Container): The base container to use to build the connector. - - Returns: - str: The user to use for the connector image. - """ - users = (await base_container.with_exec(sh_dash_c(["cut -d: -f1 /etc/passwd | sort | uniq"])).stdout()).splitlines() - if cls.USER in users: - return cls.USER - return "root" - - -class LoadContainerToLocalDockerHost(Step): - context: ConnectorContext - - def __init__(self, context: ConnectorContext, image_tag: str = "dev") -> None: - super().__init__(context) - self.image_tag = image_tag - - def _generate_dev_tag(self, platform: Platform, multi_platforms: bool) -> str: - """ - When building for multiple platforms, we need to tag the image with the platform name. - There's no way to locally build a multi-arch image, so we need to tag the image with the platform name when the user passed multiple architecture options. - """ - return f"{self.image_tag}-{platform.replace('/', '-')}" if multi_platforms else self.image_tag - - @property - def title(self) -> str: - return f"Load {self.image_name}:{self.image_tag} to the local docker host." - - @property - def image_name(self) -> str: - return f"airbyte/{self.context.connector.technical_name}" - - async def _run(self, containers: dict[Platform, Container]) -> StepResult: - loaded_images = [] - image_sha = None - multi_platforms = len(containers) > 1 - for platform, container in containers.items(): - _, exported_tar_path = await export_container_to_tarball(self.context, container, platform) - if not exported_tar_path: - return StepResult( - step=self, - status=StepStatus.FAILURE, - stderr=f"Failed to export the connector image {self.image_name}:{self.image_tag} to a tarball.", - ) - try: - client = docker.from_env() - image_tag = self._generate_dev_tag(platform, multi_platforms) - full_image_name = f"{self.image_name}:{image_tag}" - with open(exported_tar_path, "rb") as tarball_content: - new_image = client.images.load(tarball_content.read())[0] - new_image.tag(self.image_name, tag=image_tag) - image_sha = new_image.id - loaded_images.append(full_image_name) - except docker.errors.DockerException as e: - return StepResult( - step=self, status=StepStatus.FAILURE, stderr=f"Something went wrong while interacting with the local docker client: {e}" - ) - - return StepResult( - step=self, status=StepStatus.SUCCESS, stdout=f"Loaded image {','.join(loaded_images)} to your Docker host ({image_sha})." - ) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/java_connectors.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/java_connectors.py deleted file mode 100644 index 75bf89a73d0d..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/java_connectors.py +++ /dev/null @@ -1,69 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from dagger import Container, Directory, File, Platform, QueryError - -from pipelines.airbyte_ci.connectors.build_image.steps.common import BuildConnectorImagesBase -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.airbyte_ci.steps.gradle import GradleTask -from pipelines.dagger.containers import java -from pipelines.models.steps import StepResult, StepStatus - - -class BuildConnectorDistributionTar(GradleTask): - """ - A step to build a Java connector image using the distTar Gradle task. - """ - - title = "Build connector tar" - gradle_task_name = "distTar" - - -class BuildConnectorImages(BuildConnectorImagesBase): - """ - A step to build Java connector images using the distTar Gradle task. - """ - - async def _run(self, dist_dir: Directory) -> StepResult: - dist_tar: File - try: - dir_files = await dist_dir.entries() - tar_files = [f for f in dir_files if f.endswith(".tar")] - num_files = len(tar_files) - if num_files != 1: - error_message = ( - "The distribution tar file for the current java connector was not built." - if num_files == 0 - else "More than one distribution tar file was built for the current java connector." - ) - return StepResult(step=self, status=StepStatus.FAILURE, stderr=error_message) - dist_tar = dist_dir.file(tar_files[0]) - except QueryError as e: - return StepResult(step=self, status=StepStatus.FAILURE, stderr=str(e)) - return await super()._run(dist_tar) - - async def _build_connector(self, platform: Platform, dist_tar: File) -> Container: - return await java.with_airbyte_java_connector(self.context, dist_tar, platform) - - -async def run_connector_build(context: ConnectorContext) -> StepResult: - """Create the java connector distribution tar file and build the connector image.""" - - if context.use_host_gradle_dist_tar and context.is_local: - # Special case: use a local dist tar to speed up local development. - dist_dir = await context.dagger_client.host().directory(dist_tar_directory_path(context), include=["*.tar"]) - # Speed things up by only building for the local platform. - return await BuildConnectorImages(context).run(dist_dir) - - # Default case: distribution tar is built by the dagger pipeline. - build_connector_tar_result = await BuildConnectorDistributionTar(context).run() - if build_connector_tar_result.status is not StepStatus.SUCCESS: - return build_connector_tar_result - - dist_dir = await build_connector_tar_result.output.directory("build/distributions") - return await BuildConnectorImages(context).run(dist_dir) - - -def dist_tar_directory_path(context: ConnectorContext) -> str: - return f"{context.connector.code_directory}/build/distributions" diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/manifest_only_connectors.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/manifest_only_connectors.py deleted file mode 100644 index 72c9dc386f1e..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/manifest_only_connectors.py +++ /dev/null @@ -1,71 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - - -from typing import Any - -from dagger import Container, Platform -from pydash.objects import get # type: ignore - -from pipelines.airbyte_ci.connectors.build_image.steps import build_customization -from pipelines.airbyte_ci.connectors.build_image.steps.common import BuildConnectorImagesBase -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.consts import COMPONENTS_FILE_PATH, MANIFEST_FILE_PATH -from pipelines.dagger.actions.python.common import apply_python_development_overrides -from pipelines.models.steps import StepResult - - -class BuildConnectorImages(BuildConnectorImagesBase): - """ - A step to build a manifest only connector image. - A spec command is run on the container to validate it was built successfully. - """ - - context: ConnectorContext - PATH_TO_INTEGRATION_CODE = "/airbyte/integration_code" - - async def _build_connector(self, platform: Platform, *args: Any) -> Container: - baseImage = get(self.context.connector.metadata, "connectorBuildOptions.baseImage") - if not baseImage: - raise ValueError("connectorBuildOptions.baseImage is required to build a manifest only connector.") - - return await self._build_from_base_image(platform) - - def _get_base_container(self, platform: Platform) -> Container: - base_image_name = get(self.context.connector.metadata, "connectorBuildOptions.baseImage") - self.logger.info(f"Building manifest connector from base image {base_image_name}") - return self.dagger_client.container(platform=platform).from_(base_image_name) - - async def _build_from_base_image(self, platform: Platform) -> Container: - """Build the connector container using the base image defined in the metadata, in the connectorBuildOptions.baseImage field. - - Returns: - Container: The connector container built from the base image. - """ - self.logger.info(f"Building connector from base image in metadata for {platform}") - - # Mount manifest file - base_container = self._get_base_container(platform) - user = await self.get_image_user(base_container) - base_container = base_container.with_file( - f"source_declarative_manifest/{MANIFEST_FILE_PATH}", - (await self.context.get_connector_dir(include=[MANIFEST_FILE_PATH])).file(MANIFEST_FILE_PATH), - owner=user, - ) - - # Mount components file if it exists - components_file = self.context.connector.manifest_only_components_path - if components_file.exists(): - base_container = base_container.with_file( - f"source_declarative_manifest/{COMPONENTS_FILE_PATH}", - (await self.context.get_connector_dir(include=[COMPONENTS_FILE_PATH])).file(COMPONENTS_FILE_PATH), - owner=user, - ) - connector_container = build_customization.apply_airbyte_entrypoint(base_container, self.context.connector) - connector_container = await apply_python_development_overrides(self.context, connector_container, user) - return connector_container - - -async def run_connector_build(context: ConnectorContext) -> StepResult: - return await BuildConnectorImages(context).run() diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/normalization.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/normalization.py deleted file mode 100644 index 2cfe294a0cac..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/normalization.py +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from dagger import Platform - -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.dagger.actions.connector import normalization -from pipelines.models.steps import Step, StepResult, StepStatus - - -# TODO this class could be deleted -# if java connectors tests are not relying on an existing local normalization image to run -class BuildOrPullNormalization(Step): - """A step to build or pull the normalization image for a connector according to the image name.""" - - context: ConnectorContext - - def __init__(self, context: ConnectorContext, normalization_image: str, build_platform: Platform) -> None: - """Initialize the step to build or pull the normalization image. - - Args: - context (ConnectorContext): The current connector context. - normalization_image (str): The normalization image to build (if :dev) or pull. - """ - super().__init__(context) - self.build_platform = build_platform - self.use_dev_normalization = normalization_image.endswith(":dev") - self.normalization_image = normalization_image - - @property - def title(self) -> str: - return f"Build {self.normalization_image}" if self.use_dev_normalization else f"Pull {self.normalization_image}" - - async def _run(self) -> StepResult: - if self.use_dev_normalization: - build_normalization_container = normalization.with_normalization(self.context, self.build_platform) - else: - build_normalization_container = self.context.dagger_client.container().from_(self.normalization_image) - return StepResult(step=self, status=StepStatus.SUCCESS, output=build_normalization_container) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/python_connectors.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/python_connectors.py deleted file mode 100644 index aaddf8152ded..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/build_image/steps/python_connectors.py +++ /dev/null @@ -1,113 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - - -from typing import Any - -from dagger import Container, Platform - -from pipelines.airbyte_ci.connectors.build_image.steps import build_customization -from pipelines.airbyte_ci.connectors.build_image.steps.common import BuildConnectorImagesBase -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.dagger.actions.python.common import apply_python_development_overrides, with_python_connector_installed -from pipelines.models.steps import StepResult - - -class BuildConnectorImages(BuildConnectorImagesBase): - """ - A step to build a Python connector image. - A spec command is run on the container to validate it was built successfully. - """ - - context: ConnectorContext - PATH_TO_INTEGRATION_CODE = "/airbyte/integration_code" - - async def _build_connector(self, platform: Platform, *args: Any) -> Container: - if ( - "connectorBuildOptions" in self.context.connector.metadata - and "baseImage" in self.context.connector.metadata["connectorBuildOptions"] - ): - return await self._build_from_base_image(platform) - else: - return await self._build_from_dockerfile(platform) - - def _get_base_container(self, platform: Platform) -> Container: - base_image_name = self.context.connector.metadata["connectorBuildOptions"]["baseImage"] - self.logger.info(f"Building connector from base image {base_image_name}") - return self.dagger_client.container(platform=platform).from_(base_image_name) - - async def _create_builder_container(self, base_container: Container, user: str) -> Container: - """Pre install the connector dependencies in a builder container. - - Args: - base_container (Container): The base container to use to build the connector. - user (str): The user to use in the container. - Returns: - Container: The builder container, with installed dependencies. - """ - ONLY_BUILD_FILES = ["pyproject.toml", "poetry.lock", "poetry.toml", "setup.py", "requirements.txt", "README.md"] - - builder = await with_python_connector_installed( - self.context, - base_container, - str(self.context.connector.code_directory), - user, - install_root_package=False, - include=ONLY_BUILD_FILES, - ) - return builder - - async def _build_from_base_image(self, platform: Platform) -> Container: - """Build the connector container using the base image defined in the metadata, in the connectorBuildOptions.baseImage field. - - Returns: - Container: The connector container built from the base image. - """ - self.logger.info(f"Building connector from base image in metadata for {platform}") - base = self._get_base_container(platform) - user = await self.get_image_user(base) - customized_base = await build_customization.pre_install_hooks(self.context.connector, base, self.logger) - main_file_name = build_customization.get_main_file_name(self.context.connector) - - builder = await self._create_builder_container(customized_base, user) - - # The snake case name of the connector corresponds to the python package name of the connector - # We want to mount it to the container under PATH_TO_INTEGRATION_CODE/connector_snake_case_name - connector_snake_case_name = self.context.connector.technical_name.replace("-", "_") - - base_connector_container = ( - # copy python dependencies from builder to connector container - customized_base.with_directory("/usr/local", builder.directory("/usr/local")) - .with_workdir(self.PATH_TO_INTEGRATION_CODE) - .with_exec(["chown", "-R", f"{user}:{user}", "."]) - .with_file(main_file_name, (await self.context.get_connector_dir(include=[main_file_name])).file(main_file_name), owner=user) - .with_directory( - connector_snake_case_name, - (await self.context.get_connector_dir(include=[connector_snake_case_name])).directory(connector_snake_case_name), - owner=user, - ) - ) - - connector_container = build_customization.apply_airbyte_entrypoint(base_connector_container, self.context.connector) - customized_connector = await build_customization.post_install_hooks(self.context.connector, connector_container, self.logger) - # Make sure the user has access to /tmp - customized_connector = customized_connector.with_exec(["chown", "-R", f"{user}:{user}", "/tmp"]) - return customized_connector.with_user(user) - - async def _build_from_dockerfile(self, platform: Platform) -> Container: - """Build the connector container using its Dockerfile. - - Returns: - Container: The connector container built from its Dockerfile. - """ - self.logger.warn( - "This connector is built from its Dockerfile. This is now deprecated. Please set connectorBuildOptions.baseImage metadata field to use our new build process." - ) - container = self.dagger_client.container(platform=platform).build(await self.context.get_connector_dir()) - container = await apply_python_development_overrides(self.context, container, "root") - return container - - -async def run_connector_build(context: ConnectorContext) -> StepResult: - return await BuildConnectorImages(context).run() diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/commands.py deleted file mode 100644 index 22dee605124b..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/commands.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from typing import Optional - -import asyncclick as click -import semver - -from pipelines.airbyte_ci.connectors.bump_version.pipeline import run_connector_version_bump_pipeline -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.airbyte_ci.connectors.pipeline import run_connectors_pipelines -from pipelines.cli.dagger_pipeline_command import DaggerPipelineCommand - - -class BumpType(click.ParamType): - name = "bump-type" - - def __init__(self) -> None: - self.choices = ["patch", "minor", "major", "rc"] - - def convert(self, value: str, param: Optional[click.Parameter], ctx: Optional[click.Context]) -> str: - if value in self.choices: - return value - if value.startswith("version:"): - version_str = value.split("version:", 1)[1] - if semver.VersionInfo.is_valid(version_str): - return value - self.fail(f"{value} is not a valid bump type. Valid choices are {self.choices} or 'version:'.", param, ctx) - - def __repr__(self) -> str: - return "BumpType" - - -@click.command(cls=DaggerPipelineCommand, short_help="Bump a connector version and update its changelog.") -@click.argument("bump-type", type=BumpType()) -@click.argument("changelog-entry", type=str) -@click.option("--pr-number", type=int, help="Pull request number.") -@click.option("--rc", is_flag=True, help="Bumps version number and appends a release candidate suffix.") -@click.pass_context -async def bump_version( - ctx: click.Context, - bump_type: str, - changelog_entry: str, - pr_number: int | None, - rc: bool, -) -> bool: - """Bump a connector version: update metadata.yaml and changelog.""" - - if rc and bump_type == "rc": - raise click.BadParameter("The `--rc` flag cannot be used when the specified `bump-type` is `rc`.") - - connectors_contexts = [ - ConnectorContext( - pipeline_name=f"Bump version of connector {connector.technical_name}", - connector=connector, - is_local=ctx.obj["is_local"], - git_branch=ctx.obj["git_branch"], - git_revision=ctx.obj["git_revision"], - diffed_branch=ctx.obj["diffed_branch"], - git_repo_url=ctx.obj["git_repo_url"], - ci_report_bucket=ctx.obj["ci_report_bucket_name"], - report_output_prefix=ctx.obj["report_output_prefix"], - gha_workflow_run_url=ctx.obj.get("gha_workflow_run_url"), - dagger_logs_url=ctx.obj.get("dagger_logs_url"), - pipeline_start_timestamp=ctx.obj.get("pipeline_start_timestamp"), - ci_context=ctx.obj.get("ci_context"), - ci_gcp_credentials=ctx.obj["ci_gcp_credentials"], - ci_git_user=ctx.obj["ci_git_user"], - ci_github_access_token=ctx.obj["ci_github_access_token"], - enable_report_auto_open=False, - s3_build_cache_access_key_id=ctx.obj.get("s3_build_cache_access_key_id"), - s3_build_cache_secret_key=ctx.obj.get("s3_build_cache_secret_key"), - docker_hub_username=ctx.obj.get("docker_hub_username"), - docker_hub_password=ctx.obj.get("docker_hub_password"), - ) - for connector in ctx.obj["selected_connectors_with_modified_files"] - ] - - await run_connectors_pipelines( - connectors_contexts, - run_connector_version_bump_pipeline, - "Version bump pipeline pipeline", - ctx.obj["concurrency"], - ctx.obj["dagger_logs_path"], - ctx.obj["execute_timeout"], - bump_type, - changelog_entry, - rc, - pr_number, - ) - - return True diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/pipeline.py deleted file mode 100644 index 57b7ac71c81f..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/bump_version/pipeline.py +++ /dev/null @@ -1,109 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from typing import TYPE_CHECKING - -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.airbyte_ci.connectors.reports import ConnectorReport, Report -from pipelines.airbyte_ci.steps.bump_version import BumpConnectorVersion -from pipelines.airbyte_ci.steps.changelog import AddChangelogEntry -from pipelines.models.steps import Step, StepResult, StepStatus - -if TYPE_CHECKING: - from anyio import Semaphore - - -class RestoreVersionState(Step): - context: ConnectorContext - - title = "Restore original version state" - - def __init__(self, context: ConnectorContext) -> None: - super().__init__(context) - connector = context.connector - if connector.metadata_file_path.is_file(): - self.metadata_content = connector.metadata_file_path.read_text() - else: - self.metadata_content = None - - if connector.dockerfile_file_path.is_file(): - self.dockerfile_content = connector.dockerfile_file_path.read_text() - else: - self.dockerfile_content = None - - if connector.pyproject_file_path.is_file(): - self.poetry_content = connector.pyproject_file_path.read_text() - else: - self.poetry_content = None - - if connector.documentation_file_path and connector.documentation_file_path.is_file(): - self.documentation_content = connector.documentation_file_path.read_text() - else: - self.documentation_content = None - - async def _run(self) -> StepResult: - connector = self.context.connector - if self.metadata_content: - connector.metadata_file_path.write_text(self.metadata_content) - if self.dockerfile_content: - connector.dockerfile_file_path.write_text(self.dockerfile_content) - if self.poetry_content: - connector.pyproject_file_path.write_text(self.poetry_content) - if self.documentation_content and connector.documentation_file_path: - connector.documentation_file_path.write_text(self.documentation_content) - return StepResult(step=self, status=StepStatus.SUCCESS) - - async def _cleanup(self) -> StepResult: - return StepResult(step=self, status=StepStatus.SUCCESS) - - -async def run_connector_version_bump_pipeline( - context: ConnectorContext, - semaphore: "Semaphore", - bump_type: str, - changelog_entry: str, - rc: bool, - pull_request_number: str | int | None = None, -) -> Report: - """Run a pipeline to upgrade for a single connector. - - Args: - context (ConnectorContext): The initialized connector context. - - Returns: - Report: The reports holding the base image version upgrade results. - """ - report_name = "CONNECTOR VERSION BUMP RESULTS" - async with semaphore: - steps_results = [] - async with context: - connector_directory = await context.get_connector_dir() - bump_version = BumpConnectorVersion(context, connector_directory, bump_type, rc) - bump_version_result = await bump_version.run() - steps_results.append(bump_version_result) - if not bump_version_result.success: - report = ConnectorReport(context, steps_results, name=report_name) - context.report = report - return report - - updated_connector_directory = bump_version_result.output - for modified_file in bump_version.modified_files: - await updated_connector_directory.file(modified_file).export(str(context.connector.code_directory / modified_file)) - context.logger.info(f"Exported {modified_file} following the version bump.") - documentation_directory = await context.get_repo_dir( - include=[str(context.connector.local_connector_documentation_directory)] - ).directory(str(context.connector.local_connector_documentation_directory)) - add_changelog_entry = AddChangelogEntry( - context, documentation_directory, bump_version.new_version, changelog_entry, pull_request_number=pull_request_number - ) - add_changelog_entry_result = await add_changelog_entry.run() - steps_results.append(add_changelog_entry_result) - if not add_changelog_entry_result.success: - report = ConnectorReport(context, steps_results, name=report_name) - context.report = report - return report - - await add_changelog_entry.export_modified_files(context.connector.local_connector_documentation_directory) - report = ConnectorReport(context, steps_results, name=report_name) - context.report = report - return report diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/commands.py deleted file mode 100644 index 5fc793533a11..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/commands.py +++ /dev/null @@ -1,275 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import os -from pathlib import Path -from typing import List, Set, Tuple - -import asyncclick as click -from connector_ops.utils import Connector, ConnectorLanguage, SupportLevelEnum, get_all_connectors_in_repo # type: ignore - -from pipelines import main_logger -from pipelines.cli.airbyte_ci import wrap_in_secret -from pipelines.cli.click_decorators import click_ignore_unused_kwargs, click_merge_args_into_context_obj -from pipelines.cli.lazy_group import LazyGroup -from pipelines.helpers.connectors.modifed import ConnectorWithModifiedFiles, get_connector_modified_files, get_modified_connectors -from pipelines.helpers.git import get_modified_files -from pipelines.helpers.utils import transform_strs_to_paths - -ALL_CONNECTORS = get_all_connectors_in_repo() -CONNECTORS_WITH_STRICT_ENCRYPT_VARIANTS = { - Connector(c.relative_connector_path.replace("-strict-encrypt", "")) - for c in ALL_CONNECTORS - if c.technical_name.endswith("-strict-encrypt") -} - - -def log_selected_connectors(selected_connectors_with_modified_files: List[ConnectorWithModifiedFiles]) -> None: - """Logs selected connector names into main logger, or says no connectors to run.""" - if selected_connectors_with_modified_files: - selected_connectors_names = [c.technical_name for c in selected_connectors_with_modified_files] - main_logger.info(f"Will run on the following {len(selected_connectors_names)} connectors: {', '.join(selected_connectors_names)}.") - else: - main_logger.info("No connectors to run.") - - -def get_base_connector_and_variants(connector: Connector) -> Set[Connector]: - """Returns the connector's name and it's strict-encrypt variant.""" - base_connector_path = connector.relative_connector_path.replace("-strict-encrypt", "") - base_connector = Connector(base_connector_path) - strict_encrypt_connector_path = f"{base_connector.relative_connector_path}-strict-encrypt" - if base_connector in CONNECTORS_WITH_STRICT_ENCRYPT_VARIANTS: - return {base_connector, Connector(strict_encrypt_connector_path)} - else: - return {base_connector} - - -def update_selected_connectors_with_variants(selected_connectors: Set[Connector]) -> Set[Connector]: - """Returns the connectors and their variants.""" - updated_selected_connectors = set() - for selected_connector in selected_connectors: - updated_selected_connectors.update(get_base_connector_and_variants(selected_connector)) - return updated_selected_connectors - - -def get_selected_connectors_with_modified_files( - selected_names: Tuple[str], - selected_support_levels: Tuple[str], - selected_languages: Tuple[str], - modified: bool, - metadata_changes_only: bool, - metadata_query: str, - modified_files: Set[Path], - enable_dependency_scanning: bool = False, -) -> List[ConnectorWithModifiedFiles]: - """Get the connectors that match the selected criteria. - - Args: - selected_names (Tuple[str]): Selected connector names. - selected_support_levels (Tuple[str]): Selected connector support levels. - selected_languages (Tuple[str]): Selected connector languages. - modified (bool): Whether to select the modified connectors. - metadata_changes_only (bool): Whether to select only the connectors with metadata changes. - modified_files (Set[Path]): The modified files. - enable_dependency_scanning (bool): Whether to enable the dependency scanning. - Returns: - List[ConnectorWithModifiedFiles]: The connectors that match the selected criteria. - """ - - if metadata_changes_only and not modified: - main_logger.info("--metadata-changes-only overrides --modified") - modified = True - - selected_modified_connectors = ( - get_modified_connectors(modified_files, ALL_CONNECTORS, enable_dependency_scanning) if modified else set() - ) - selected_connectors_by_name = {c for c in ALL_CONNECTORS if c.technical_name in selected_names} - selected_connectors_by_support_level = {connector for connector in ALL_CONNECTORS if connector.support_level in selected_support_levels} - selected_connectors_by_language = {connector for connector in ALL_CONNECTORS if connector.language in selected_languages} - selected_connectors_by_query = ( - {connector for connector in ALL_CONNECTORS if connector.metadata_query_match(metadata_query)} if metadata_query else set() - ) - - non_empty_connector_sets = [ - connector_set - for connector_set in [ - selected_connectors_by_name, - selected_connectors_by_support_level, - selected_connectors_by_language, - selected_connectors_by_query, - selected_modified_connectors, - ] - if connector_set - ] - # The selected connectors are the intersection of the selected connectors by name, support_level, language, simpleeval query and modified. - selected_connectors = set.intersection(*non_empty_connector_sets) if non_empty_connector_sets else set() - - # We always want to pair selection of a base connector with its variant, e vice versa - selected_connectors = update_selected_connectors_with_variants(selected_connectors) - - selected_connectors_with_modified_files = [] - for connector in selected_connectors: - connector_with_modified_files = ConnectorWithModifiedFiles( - relative_connector_path=connector.relative_connector_path, - modified_files=get_connector_modified_files(connector, modified_files), - ) - if not metadata_changes_only: - selected_connectors_with_modified_files.append(connector_with_modified_files) - else: - if connector_with_modified_files.has_metadata_change: - selected_connectors_with_modified_files.append(connector_with_modified_files) - - return selected_connectors_with_modified_files - - -def validate_environment(is_local: bool) -> None: - """Check if the required environment variables exist.""" - if is_local: - if not Path(".git").is_dir(): - raise click.UsageError("You need to run this command from the repository root.") - else: - required_env_vars_for_ci = [ - "CI_GITHUB_ACCESS_TOKEN", - "DOCKER_HUB_USERNAME", - "DOCKER_HUB_PASSWORD", - ] - for required_env_var in required_env_vars_for_ci: - if os.getenv(required_env_var) is None: - raise click.UsageError(f"When running in a CI context a {required_env_var} environment variable must be set.") - - -@click.group( - cls=LazyGroup, - help="Commands related to connectors and connector acceptance tests.", - lazy_subcommands={ - "build": "pipelines.airbyte_ci.connectors.build_image.commands.build", - "test": "pipelines.airbyte_ci.connectors.test.commands.test", - "list": "pipelines.airbyte_ci.connectors.list.commands.list_connectors", - "publish": "pipelines.airbyte_ci.connectors.publish.commands.publish", - "bump-version": "pipelines.airbyte_ci.connectors.bump_version.commands.bump_version", - "migrate-to-manifest-only": "pipelines.airbyte_ci.connectors.migrate_to_manifest_only.commands.migrate_to_manifest_only", - "migrate-to-inline-schemas": "pipelines.airbyte_ci.connectors.migrate_to_inline_schemas.commands.migrate_to_inline_schemas", - "generate-erd": "pipelines.airbyte_ci.connectors.generate_erd.commands.generate_erd", - "upgrade-cdk": "pipelines.airbyte_ci.connectors.upgrade_cdk.commands.upgrade_cdk", - "up-to-date": "pipelines.airbyte_ci.connectors.up_to_date.commands.up_to_date", - "pull-request": "pipelines.airbyte_ci.connectors.pull_request.commands.pull_request", - }, -) -@click.option( - "--name", - "names", - multiple=True, - help="Only test a specific connector. Use its technical name. e.g source-pokeapi.", - type=click.Choice([c.technical_name for c in ALL_CONNECTORS]), -) -@click.option("--language", "languages", multiple=True, help="Filter connectors to test by language.", type=click.Choice(ConnectorLanguage)) -@click.option( - "--support-level", - "support_levels", - multiple=True, - help="Filter connectors to test by support_level.", - type=click.Choice(SupportLevelEnum), -) -@click.option( - "--modified/--not-modified", - help="Only test modified connectors in the current branch. Archived connectors are ignored", - default=False, - type=bool, -) -@click.option( - "--metadata-changes-only/--not-metadata-changes-only", - help="Only test connectors with modified metadata files in the current branch.", - default=False, - type=bool, -) -@click.option( - "--metadata-query", - help="Filter connectors by metadata query using `simpleeval`. e.g. 'data.ab_internal.ql == 200'", - type=str, -) -@click.option("--concurrency", help="Number of connector tests pipeline to run in parallel.", default=5, type=int) -@click.option( - "--execute-timeout", - help="The maximum time in seconds for the execution of a Dagger request before an ExecuteTimeoutError is raised. Passing None results in waiting forever.", - default=None, - type=int, -) -@click.option( - "--enable-dependency-scanning/--disable-dependency-scanning", - help="When enabled, the dependency scanning will be performed to detect the connectors to test according to a dependency change.", - default=False, - type=bool, -) -@click.option( - "--use-local-cdk", - is_flag=True, - help=("Build with the airbyte-cdk from the local repository. " "This is useful for testing changes to the CDK."), - default=False, - type=bool, -) -@click.option( - "--use-cdk-ref", - help=( - "Build with the airbyte-cdk from the specified git ref. " - "This is useful for testing against dev versions or previous versions of the CDK. " - "Ignored for java connectors and if `--use-local-cdk` is set." - ), - type=str, -) -@click.option( - "--enable-report-auto-open/--disable-report-auto-open", - is_flag=True, - help=("When enabled, finishes by opening a browser window to display an HTML report."), - default=True, - type=bool, -) -@click.option( - "--docker-hub-username", - help="Your username to connect to DockerHub.", - type=click.STRING, - required=False, - envvar="DOCKER_HUB_USERNAME", - callback=wrap_in_secret, -) -@click.option( - "--docker-hub-password", - help="Your password to connect to DockerHub.", - type=click.STRING, - required=False, - envvar="DOCKER_HUB_PASSWORD", - callback=wrap_in_secret, -) -@click_merge_args_into_context_obj -@click.pass_context -@click_ignore_unused_kwargs -async def connectors( - ctx: click.Context, -) -> None: - """Group all the connectors-ci command.""" - validate_environment(ctx.obj["is_local"]) - - modified_files = [] - if ctx.obj["modified"] or ctx.obj["metadata_changes_only"]: - modified_files = transform_strs_to_paths( - await get_modified_files( - ctx.obj["git_branch"], - ctx.obj["git_revision"], - ctx.obj["diffed_branch"], - ctx.obj["is_local"], - ctx.obj["ci_context"], - ctx.obj["git_repo_url"], - ) - ) - - ctx.obj["selected_connectors_with_modified_files"] = get_selected_connectors_with_modified_files( - ctx.obj["names"], - ctx.obj["support_levels"], - ctx.obj["languages"], - ctx.obj["modified"], - ctx.obj["metadata_changes_only"], - ctx.obj["metadata_query"], - set(modified_files), - ctx.obj["enable_dependency_scanning"], - ) - log_selected_connectors(ctx.obj["selected_connectors_with_modified_files"]) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/consts.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/consts.py deleted file mode 100644 index b15d82958287..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/consts.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -from enum import Enum - - -class CONNECTOR_TEST_STEP_ID(str, Enum): - """ - An enum for the different step ids of the connector test pipeline. - """ - - ACCEPTANCE = "acceptance" - INCREMENTAL_ACCEPTANCE = "incremental_acceptance" - BUILD_NORMALIZATION = "build_normalization" - BUILD_TAR = "build_tar" - BUILD = "build" - INTEGRATION = "integration" - PYTHON_CLI_VALIDATION = "python_cli_validation" - QA_CHECKS = "qa_checks" - UNIT = "unit" - VERSION_INC_CHECK = "version_inc_check" - CONNECTOR_LIVE_TESTS = "connector_live_tests" - REGRESSION_TEST = "common.regression_test" - ADD_CHANGELOG_ENTRY = "bump_version.changelog" - SET_CONNECTOR_VERSION = "bump_version.set" - CHECK_UPDATE_CANDIDATE = "up_to_date.check" - UPDATE_POETRY = "up_to_date.poetry" - UPDATE_PULL_REQUEST = "up_to_date.pull" - LLM_RELATIONSHIPS = "llm_relationships" - DBML_FILE = "dbml_file" - PUBLISH_ERD = "publish_erd" - PULL_REQUEST_CREATE = "pull_request.create" - PULL_REQUEST_UPDATE = "pull_request.update" - MANIFEST_ONLY_CHECK = "migrate_to_manifest_only.check" - MANIFEST_ONLY_STRIP = "migrate_to_manifest_only.strip" - MANIFEST_ONLY_UPDATE = "migrate_to_manifest_only.update" - INLINE_CANDIDATE = "migration_to_inline_schemas.candidate" - INLINE_MIGRATION = "migration_to_inline_schemas.migration" - INLINE_CLEANUP = "migration_to_inline_schemas.cleanup" - LOAD_IMAGE_TO_LOCAL_DOCKER_HOST = "load_image_to_local_docker_host" - - def __str__(self) -> str: - return self.value diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/context.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/context.py deleted file mode 100644 index ecb901945486..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/context.py +++ /dev/null @@ -1,273 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""Module declaring context related classes.""" - -from __future__ import annotations - -from datetime import datetime -from pathlib import Path -from types import TracebackType -from typing import TYPE_CHECKING - -import yaml # type: ignore -from asyncer import asyncify -from dagger import Directory, Platform -from github import PullRequest - -from pipelines.airbyte_ci.connectors.reports import ConnectorReport -from pipelines.consts import BUILD_PLATFORMS -from pipelines.dagger.actions import secrets -from pipelines.helpers.connectors.modifed import ConnectorWithModifiedFiles -from pipelines.helpers.execution.run_steps import RunStepOptions -from pipelines.helpers.github import update_commit_status_check -from pipelines.helpers.slack import send_message_to_webhook -from pipelines.helpers.utils import METADATA_FILE_NAME -from pipelines.models.contexts.pipeline_context import PipelineContext -from pipelines.models.secrets import LocalDirectorySecretStore, Secret, SecretStore - -if TYPE_CHECKING: - from pathlib import Path as NativePath - from typing import Dict, FrozenSet, List, Optional, Sequence - - -class ConnectorContext(PipelineContext): - """The connector context is used to store configuration for a specific connector pipeline run.""" - - DEFAULT_CONNECTOR_ACCEPTANCE_TEST_IMAGE = "airbyte/connector-acceptance-test:dev" - - def __init__( - self, - pipeline_name: str, - connector: ConnectorWithModifiedFiles, - is_local: bool, - git_branch: str, - git_revision: str, - diffed_branch: str, - git_repo_url: str, - report_output_prefix: str, - ci_report_bucket: Optional[str] = None, - ci_gcp_credentials: Optional[Secret] = None, - ci_git_user: Optional[str] = None, - ci_github_access_token: Optional[Secret] = None, - connector_acceptance_test_image: str = DEFAULT_CONNECTOR_ACCEPTANCE_TEST_IMAGE, - gha_workflow_run_url: Optional[str] = None, - dagger_logs_url: Optional[str] = None, - pipeline_start_timestamp: Optional[int] = None, - ci_context: Optional[str] = None, - slack_webhook: Optional[str] = None, - pull_request: Optional[PullRequest.PullRequest] = None, - should_save_report: bool = True, - code_tests_only: bool = False, - use_local_cdk: bool = False, - use_cdk_ref: Optional[str] = None, - use_host_gradle_dist_tar: bool = False, - enable_report_auto_open: bool = True, - docker_hub_username: Optional[Secret] = None, - docker_hub_password: Optional[Secret] = None, - s3_build_cache_access_key_id: Optional[Secret] = None, - s3_build_cache_secret_key: Optional[Secret] = None, - genai_api_key: Optional[Secret] = None, - dbdocs_token: Optional[Secret] = None, - concurrent_cat: Optional[bool] = False, - run_step_options: RunStepOptions = RunStepOptions(), - targeted_platforms: Sequence[Platform] = BUILD_PLATFORMS, - secret_stores: Dict[str, SecretStore] | None = None, - ) -> None: - """Initialize a connector context. - - Args: - connector (Connector): The connector under test. - is_local (bool): Whether the context is for a local run or a CI run. - git_branch (str): The current git branch name. - git_revision (str): The current git revision, commit hash. - diffed_branch: str: The branch to compare the current branch against. - git_repo_url: str: The URL of the git repository. - report_output_prefix (str): The S3 key to upload the test report to. - connector_acceptance_test_image (Optional[str], optional): The image to use to run connector acceptance tests. Defaults to DEFAULT_CONNECTOR_ACCEPTANCE_TEST_IMAGE. - gha_workflow_run_url (Optional[str], optional): URL to the github action workflow run. Only valid for CI run. Defaults to None. - dagger_logs_url (Optional[str], optional): URL to the dagger logs. Only valid for CI run. Defaults to None. - pipeline_start_timestamp (Optional[int], optional): Timestamp at which the pipeline started. Defaults to None. - ci_context (Optional[str], optional): Pull requests, workflow dispatch or nightly build. Defaults to None. - slack_webhook (Optional[str], optional): The slack webhook to send messages to. Defaults to None. - pull_request (PullRequest, optional): The pull request object if the pipeline was triggered by a pull request. Defaults to None. - code_tests_only (bool, optional): Whether to ignore non-code tests like QA and metadata checks. Defaults to False. - use_host_gradle_dist_tar (bool, optional): Used when developing java connectors with gradle. Defaults to False. - enable_report_auto_open (bool, optional): Open HTML report in browser window. Defaults to True. - docker_hub_username (Optional[Secret], optional): Docker Hub username to use to read registries. Defaults to None. - docker_hub_password (Optional[Secret], optional): Docker Hub password to use to read registries. Defaults to None. - s3_build_cache_access_key_id (Optional[Secret], optional): Gradle S3 Build Cache credentials. Defaults to None. - s3_build_cache_secret_key (Optional[Secret], optional): Gradle S3 Build Cache credentials. Defaults to None. - concurrent_cat (bool, optional): Whether to run the CAT tests in parallel. Defaults to False. - targeted_platforms (Optional[Iterable[Platform]], optional): The platforms to build the connector image for. Defaults to BUILD_PLATFORMS. - """ - - self.pipeline_name = pipeline_name - self.connector = connector - self.connector_acceptance_test_image = connector_acceptance_test_image - self._secrets_dir: Optional[Directory] = None - self._updated_secrets_dir: Optional[Directory] = None - self.cdk_version: Optional[str] = None - self.should_save_report = should_save_report - self.code_tests_only = code_tests_only - self.use_local_cdk = use_local_cdk - self.use_cdk_ref = use_cdk_ref - self.use_host_gradle_dist_tar = use_host_gradle_dist_tar - self.enable_report_auto_open = enable_report_auto_open - self.docker_hub_username = docker_hub_username - self.docker_hub_password = docker_hub_password - self.s3_build_cache_access_key_id = s3_build_cache_access_key_id - self.s3_build_cache_secret_key = s3_build_cache_secret_key - self.genai_api_key = genai_api_key - self.dbdocs_token = dbdocs_token - self.concurrent_cat = concurrent_cat - self.targeted_platforms = targeted_platforms - super().__init__( - pipeline_name=pipeline_name, - is_local=is_local, - git_branch=git_branch, - git_revision=git_revision, - diffed_branch=diffed_branch, - git_repo_url=git_repo_url, - report_output_prefix=report_output_prefix, - gha_workflow_run_url=gha_workflow_run_url, - dagger_logs_url=dagger_logs_url, - pipeline_start_timestamp=pipeline_start_timestamp, - ci_context=ci_context, - slack_webhook=slack_webhook, - pull_request=pull_request, - ci_report_bucket=ci_report_bucket, - ci_gcp_credentials=ci_gcp_credentials, - ci_git_user=ci_git_user, - ci_github_access_token=ci_github_access_token, - run_step_options=run_step_options, - enable_report_auto_open=enable_report_auto_open, - secret_stores=secret_stores, - ) - - @property - def modified_files(self) -> FrozenSet[NativePath]: - return self.connector.modified_files - - @property - def secrets_dir(self) -> Optional[Directory]: - return self._secrets_dir - - @secrets_dir.setter - def secrets_dir(self, secrets_dir: Directory) -> None: - self._secrets_dir = secrets_dir - - @property - def updated_secrets_dir(self) -> Optional[Directory]: - return self._updated_secrets_dir - - @updated_secrets_dir.setter - def updated_secrets_dir(self, updated_secrets_dir: Directory) -> None: - self._updated_secrets_dir = updated_secrets_dir - - @property - def connector_acceptance_test_source_dir(self) -> Directory: - return self.get_repo_dir("airbyte-integrations/bases/connector-acceptance-test") - - @property - def live_tests_dir(self) -> Directory: - return self.get_repo_dir("airbyte-ci/connectors/live-tests") - - @property - def erd_package_dir(self) -> Directory: - return self.get_repo_dir("airbyte-ci/connectors/erd") - - @property - def should_save_updated_secrets(self) -> bool: - return self.ci_gcp_credentials is not None and self.updated_secrets_dir is not None - - @property - def host_image_export_dir_path(self) -> str: - return "." if self.is_ci else "/tmp" - - @property - def metadata_path(self) -> Path: - return self.connector.code_directory / METADATA_FILE_NAME - - @property - def metadata(self) -> dict: - return yaml.safe_load(self.metadata_path.read_text())["data"] - - @property - def docker_repository(self) -> str: - return self.metadata["dockerRepository"] - - @property - def docker_image_tag(self) -> str: - return self.metadata["dockerImageTag"] - - @property - def docker_image(self) -> str: - return f"{self.docker_repository}:{self.docker_image_tag}" - - @property - def local_secret_store_name(self) -> str: - return f"{self.connector.technical_name}-local" - - @property - def local_secret_store(self) -> Optional[LocalDirectorySecretStore]: - connector_secrets_path = self.connector.code_directory / "secrets" - if connector_secrets_path.is_dir(): - return LocalDirectorySecretStore(connector_secrets_path) - return None - - async def get_connector_dir(self, exclude: Optional[List[str]] = None, include: Optional[List[str]] = None) -> Directory: - """Get the connector under test source code directory. - - Args: - exclude ([List[str], optional): List of files or directories to exclude from the directory. Defaults to None. - include ([List[str], optional): List of files or directories to include in the directory. Defaults to None. - - Returns: - Directory: The connector under test source code directory. - """ - vanilla_connector_dir = self.get_repo_dir(str(self.connector.code_directory), exclude=exclude, include=include) - return await vanilla_connector_dir.with_timestamps(1) - - async def __aexit__( - self, exception_type: Optional[type[BaseException]], exception_value: Optional[BaseException], traceback: Optional[TracebackType] - ) -> bool: - """Perform teardown operation for the ConnectorContext. - - On the context exit the following operations will happen: - - Upload updated connector secrets back to Google Secret Manager - - Write a test report in JSON format locally and to S3 if running in a CI environment - - Update the commit status check on GitHub if running in a CI environment. - It should gracefully handle the execution error that happens and always upload a test report and update commit status check. - Args: - exception_type (Optional[type[BaseException]]): The exception type if an exception was raised in the context execution, None otherwise. - exception_value (Optional[BaseException]): The exception value if an exception was raised in the context execution, None otherwise. - traceback (Optional[TracebackType]): The traceback if an exception was raised in the context execution, None otherwise. - Returns: - bool: Whether the teardown operation ran successfully. - """ - self.stopped_at = datetime.utcnow() - self.state = self.determine_final_state(self.report, exception_value) - if exception_value: - self.logger.error("An error got handled by the ConnectorContext", exc_info=True) - if self.report is None: - self.logger.error("No test report was provided. This is probably due to an upstream error") - self.report = ConnectorReport(self, []) - - if self.should_save_updated_secrets: - await secrets.upload(self) - - self.report.print() - - if self.should_save_report: - await self.report.save() - - await asyncify(update_commit_status_check)(**self.github_commit_status) - - if self.should_send_slack_message: - # Using a type ignore here because the should_send_slack_message property is checking for non nullity of the slack_webhook - await asyncify(send_message_to_webhook)(self.create_slack_message(), self.get_slack_channels(), self.slack_webhook) # type: ignore - - # Supress the exception if any - return True diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/generate_erd/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/generate_erd/__init__.py deleted file mode 100644 index 7f66676b8716..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/generate_erd/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/generate_erd/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/generate_erd/commands.py deleted file mode 100644 index 6203febb51b9..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/generate_erd/commands.py +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from typing import List - -import asyncclick as click - -from pipelines.airbyte_ci.connectors.consts import CONNECTOR_TEST_STEP_ID -from pipelines.airbyte_ci.connectors.generate_erd.pipeline import run_connector_generate_erd_pipeline -from pipelines.cli.click_decorators import click_ignore_unused_kwargs, click_merge_args_into_context_obj -from pipelines.cli.dagger_pipeline_command import DaggerPipelineCommand -from pipelines.cli.secrets import wrap_in_secret -from pipelines.helpers.connectors.command import run_connector_pipeline - - -@click.command( - cls=DaggerPipelineCommand, - short_help="Generate ERD", -) -@click.option( - "--dbdocs-token", - help="The token to use with dbdocs CLI.", - type=click.STRING, - required=False, - envvar="DBDOCS_TOKEN", - callback=wrap_in_secret, -) -@click.option( - "--genai-api-key", - help="The API key to interact with GENAI.", - type=click.STRING, - required=False, - envvar="GENAI_API_KEY", - callback=wrap_in_secret, -) -@click.option( - "--skip-step", - "-x", - "skip_steps", - multiple=True, - type=click.Choice([step_id.value for step_id in [CONNECTOR_TEST_STEP_ID.LLM_RELATIONSHIPS, CONNECTOR_TEST_STEP_ID.PUBLISH_ERD]]), - help="Skip a step by name. Can be used multiple times to skip multiple steps.", -) -@click_merge_args_into_context_obj -@click.pass_context -@click_ignore_unused_kwargs -async def generate_erd(ctx: click.Context, skip_steps: List[str]) -> bool: - """ - dbdocs_token and genai_api_key and unused because they are set as part of the context in the helpers - """ - return await run_connector_pipeline( - ctx, - "Generate ERD schema", - False, - run_connector_generate_erd_pipeline, - skip_steps, - ) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/generate_erd/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/generate_erd/pipeline.py deleted file mode 100644 index 3c066307586b..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/generate_erd/pipeline.py +++ /dev/null @@ -1,169 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -import json -from pathlib import Path -from typing import TYPE_CHECKING, List - -from dagger import Container, Directory - -from pipelines.airbyte_ci.connectors.build_image.steps.python_connectors import BuildConnectorImages -from pipelines.airbyte_ci.connectors.consts import CONNECTOR_TEST_STEP_ID -from pipelines.airbyte_ci.connectors.context import ConnectorContext, PipelineContext -from pipelines.airbyte_ci.connectors.reports import Report -from pipelines.consts import LOCAL_BUILD_PLATFORM -from pipelines.dagger.actions.python.poetry import with_poetry -from pipelines.helpers.connectors.command import run_connector_steps -from pipelines.helpers.execution.run_steps import STEP_TREE, StepToRun -from pipelines.models.secrets import Secret -from pipelines.models.steps import Step, StepResult, StepStatus - -if TYPE_CHECKING: - from anyio import Semaphore - - -def _get_erd_folder(code_directory: Path) -> Path: - path = code_directory / "erd" - if not path.exists(): - path.mkdir() - return path - - -class GenerateDbml(Step): - context: ConnectorContext - - title = "Generate DBML file" - - def __init__(self, context: PipelineContext, skip_relationship_generation: bool) -> None: - super().__init__(context) - self._skip_relationship_generation = skip_relationship_generation - - async def _run(self, connector_to_discover: Container) -> StepResult: - if not self._skip_relationship_generation and not self.context.genai_api_key: - raise ValueError("GENAI_API_KEY needs to be provided if the relationship generation is not skipped") - - discovered_catalog = await self._get_discovered_catalog(connector_to_discover) - - connector_directory = await self.context.get_connector_dir() - command = ["poetry", "run", "erd", "--source-path", "/source", "--source-technical-name", self.context.connector.technical_name] - if self._skip_relationship_generation: - command.append("--skip-llm-relationships") - - erd_directory = self._build_erd_container(connector_directory, discovered_catalog).with_exec(command).directory("/source/erd") - await erd_directory.export(str(_get_erd_folder(self.context.connector.code_directory))) - - return StepResult(step=self, status=StepStatus.SUCCESS, output=erd_directory) - - async def _get_discovered_catalog(self, connector_to_discover: Container) -> str: - source_config_path_in_container = "/data/config.json" - discover_output = ( - await connector_to_discover.with_new_file(source_config_path_in_container, contents=self._get_default_config().value) - .with_exec(["discover", "--config", source_config_path_in_container], use_entrypoint=True) - .stdout() - ) - return self._get_schema_from_discover_output(discover_output) - - def _get_default_config(self) -> Secret: - if not self.context.local_secret_store: - raise ValueError("Expecting local secret store to be set up but couldn't find it") - - filtered_secrets = [secret for secret in self.context.local_secret_store.get_all_secrets() if secret.file_name == "config.json"] - if not filtered_secrets: - raise ValueError("Expecting at least one secret to match name `config.json`") - elif len(filtered_secrets) > 1: - self.logger.warning( - f"Expecting only one secret with name `config.json but got {len(filtered_secrets)}. Will take the first one in the list." - ) - - return filtered_secrets[0] - - @staticmethod - def _get_schema_from_discover_output(discover_output: str) -> str: - for line in discover_output.split("\n"): - json_line = json.loads(line) - if json_line.get("type") == "CATALOG": - return json.dumps(json.loads(line).get("catalog")) - raise ValueError("No catalog was found in output") - - def _build_erd_container(self, connector_directory: Directory, discovered_catalog: str) -> Container: - """Create a container to run ERD generation.""" - container = with_poetry(self.context) - if self.context.genai_api_key: - container = container.with_secret_variable("GENAI_API_KEY", self.context.genai_api_key.as_dagger_secret(self.dagger_client)) - - container = ( - container.with_mounted_directory("/source", connector_directory) - .with_new_file("/source/erd/discovered_catalog.json", contents=discovered_catalog) - .with_mounted_directory("/app", self.context.erd_package_dir) - .with_workdir("/app") - ) - - return container.with_exec(["poetry", "lock"], use_entrypoint=True).with_exec(["poetry", "install"], use_entrypoint=True) - - -class UploadDbmlSchema(Step): - context: ConnectorContext - - title = "Upload DBML file to dbdocs.io" - - def __init__(self, context: PipelineContext) -> None: - super().__init__(context) - - async def _run(self, erd_directory: Directory) -> StepResult: - if not self.context.dbdocs_token: - raise ValueError( - "In order to publish to dbdocs, DBDOCS_TOKEN needs to be provided. Either pass the value or skip the publish step" - ) - - dbdocs_container = ( - self.dagger_client.container() - .from_("node:lts-bullseye-slim") - .with_exec(["npm", "install", "-g", "dbdocs"], use_entrypoint=True) - .with_env_variable("DBDOCS_TOKEN", self.context.dbdocs_token.value) - .with_workdir("/airbyte_dbdocs") - .with_file("/airbyte_dbdocs/dbdocs.dbml", erd_directory.file("source.dbml")) - ) - - db_docs_build = ["dbdocs", "build", "dbdocs.dbml", f"--project={self.context.connector.technical_name}"] - await dbdocs_container.with_exec(db_docs_build).stdout() - # TODO: produce link to dbdocs in output logs - - return StepResult(step=self, status=StepStatus.SUCCESS) - - -async def run_connector_generate_erd_pipeline( - context: ConnectorContext, - semaphore: "Semaphore", - skip_steps: List[str], -) -> Report: - context.targeted_platforms = [LOCAL_BUILD_PLATFORM] - steps_to_run: STEP_TREE = [] - - steps_to_run.append([StepToRun(id=CONNECTOR_TEST_STEP_ID.BUILD, step=BuildConnectorImages(context))]) - - steps_to_run.append( - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.DBML_FILE, - step=GenerateDbml(context, CONNECTOR_TEST_STEP_ID.LLM_RELATIONSHIPS in skip_steps), - args=lambda results: {"connector_to_discover": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ), - ] - ) - - if CONNECTOR_TEST_STEP_ID.PUBLISH_ERD not in skip_steps: - steps_to_run.append( - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.PUBLISH_ERD, - step=UploadDbmlSchema(context), - args=lambda results: {"erd_directory": results[CONNECTOR_TEST_STEP_ID.DBML_FILE].output}, - depends_on=[CONNECTOR_TEST_STEP_ID.DBML_FILE], - ), - ] - ) - - return await run_connector_steps(context, semaphore, steps_to_run) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/list/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/list/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/list/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/list/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/list/commands.py deleted file mode 100644 index dea261788ba5..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/list/commands.py +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import json -from pathlib import Path - -import asyncclick as click -from connector_ops.utils import console # type: ignore -from rich.table import Table -from rich.text import Text - -from pipelines.cli.dagger_pipeline_command import DaggerPipelineCommand - - -@click.command(cls=DaggerPipelineCommand, help="List all selected connectors.", name="list") -@click.option( - "-o", - "--output", - "output_path", - type=click.Path(dir_okay=False, writable=True, path_type=Path), - help="Path where the JSON output will be saved.", -) -@click.pass_context -async def list_connectors( - ctx: click.Context, - output_path: Path, -) -> bool: - selected_connectors = sorted(ctx.obj["selected_connectors_with_modified_files"], key=lambda x: x.technical_name) - table = Table(title=f"{len(selected_connectors)} selected connectors") - table.add_column("Modified") - table.add_column("Connector") - table.add_column("Language") - table.add_column("Release stage") - table.add_column("Version") - table.add_column("Folder") - - for connector in selected_connectors: - modified = "X" if connector.modified_files else "" - connector_name = Text(connector.technical_name) - language: Text = Text(connector.language.value) if connector.language else Text("N/A") - try: - support_level: Text = Text(connector.support_level) - except Exception: - support_level = Text("N/A") - try: - version: Text = Text(connector.version) - except Exception: - version = Text("N/A") - folder = Text(str(connector.code_directory)) - table.add_row(modified, connector_name, language, support_level, version, folder) - if output_path: - with open(output_path, "w") as f: - json.dump([connector.technical_name for connector in selected_connectors], f) - console.print(table) - return True diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_inline_schemas/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_inline_schemas/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_inline_schemas/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_inline_schemas/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_inline_schemas/commands.py deleted file mode 100644 index da73b3ebc022..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_inline_schemas/commands.py +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - - -import asyncclick as click - -from pipelines.airbyte_ci.connectors.migrate_to_inline_schemas.pipeline import run_connector_migrate_to_inline_schemas_pipeline -from pipelines.cli.dagger_pipeline_command import DaggerPipelineCommand -from pipelines.helpers.connectors.command import run_connector_pipeline -from pipelines.helpers.connectors.format import verify_formatters - - -@click.command( - cls=DaggerPipelineCommand, - short_help="Where possible (have a metadata.yaml), move stream schemas to inline schemas.", -) -@click.option( - "--report", - is_flag=True, - type=bool, - default=False, - help="Auto open report browser.", -) -@click.pass_context -async def migrate_to_inline_schemas(ctx: click.Context, report: bool) -> bool: - verify_formatters() - return await run_connector_pipeline( - ctx, - "Migrate to inline schemas", - report, - run_connector_migrate_to_inline_schemas_pipeline, - ) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_inline_schemas/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_inline_schemas/pipeline.py deleted file mode 100644 index ba880ae73840..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_inline_schemas/pipeline.py +++ /dev/null @@ -1,437 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -import json -import os -import shutil -import tempfile -from dataclasses import dataclass -from pathlib import Path -from typing import TYPE_CHECKING, Any, List - -from connector_ops.utils import ConnectorLanguage # type: ignore - -from pipelines import main_logger -from pipelines.airbyte_ci.connectors.consts import CONNECTOR_TEST_STEP_ID -from pipelines.airbyte_ci.connectors.context import ConnectorContext, PipelineContext -from pipelines.airbyte_ci.connectors.reports import Report -from pipelines.consts import LOCAL_BUILD_PLATFORM -from pipelines.helpers.connectors.command import run_connector_steps -from pipelines.helpers.connectors.yaml import read_yaml, write_yaml -from pipelines.helpers.execution.run_steps import STEP_TREE, StepToRun -from pipelines.models.steps import Step, StepResult, StepStatus - -if TYPE_CHECKING: - from anyio import Semaphore - -SCHEMAS_DIR_NAME = "schemas" - - -class CheckIsInlineCandidate(Step): - """Check if the connector is a candidate to get inline schemas. - Candidate conditions: - - The connector is a Python connector. - - The connector is a source connector. - - The connector has a manifest file. - - The connector has schemas directory. - """ - - context: ConnectorContext - - title = "Check if the connector is a candidate for inline schema migration." - - def __init__(self, context: PipelineContext) -> None: - super().__init__(context) - - async def _run(self) -> StepResult: - connector = self.context.connector - manifest_path = connector.manifest_path - python_path = connector.python_source_dir_path - if connector.language not in [ - ConnectorLanguage.PYTHON, - ConnectorLanguage.LOW_CODE, - ConnectorLanguage.MANIFEST_ONLY, - ]: - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stderr="The connector is not a Python connector.", - ) - if connector.connector_type != "source": - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stderr="The connector is not a source connector.", - ) - - if not manifest_path.is_file(): - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stderr="The connector does not have a manifest file.", - ) - - schemas_dir = python_path / SCHEMAS_DIR_NAME - if not schemas_dir.is_dir(): - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stderr="The connector does not have a schemas directory.", - ) - - # TODO: does this help or not? - # if _has_subdirectory(schemas_dir): - # return StepResult(step=self, status=StepStatus.SKIPPED, stderr="This has subdirectories. It's probably complicated.") - - return StepResult( - step=self, - status=StepStatus.SUCCESS, - ) - - -class RestoreInlineState(Step): - context: ConnectorContext - - title = "Restore original state" - - def __init__(self, context: ConnectorContext) -> None: - super().__init__(context) - self.manifest_path = context.connector.manifest_path - self.original_manifest = None - if self.manifest_path.is_file(): - self.original_manifest = self.manifest_path.read_text() - - self.schemas_path = context.connector.python_source_dir_path / SCHEMAS_DIR_NAME - self.backup_schema_path = None - if self.schemas_path.is_dir(): - self.backup_schema_path = Path(tempfile.mkdtemp()) - copy_directory(self.schemas_path, self.backup_schema_path) - - async def _run(self) -> StepResult: - if self.original_manifest: - self.manifest_path.write_text(self.original_manifest) - - if self.backup_schema_path: - copy_directory(self.backup_schema_path, self.schemas_path) - - return StepResult( - step=self, - status=StepStatus.SUCCESS, - ) - - async def _cleanup(self) -> StepResult: - if self.backup_schema_path: - shutil.rmtree(self.backup_schema_path) - return StepResult( - step=self, - status=StepStatus.SUCCESS, - ) - - -class InlineSchemas(Step): - context: ConnectorContext - - title = "Migrate connector to inline schemas." - - def __init__(self, context: PipelineContext) -> None: - super().__init__(context) - - async def _run(self) -> StepResult: - connector = self.context.connector - connector_path = connector.code_directory - manifest_path = connector.manifest_path - python_path = connector.python_source_dir_path - logger = self.logger - - json_streams = _parse_json_streams(python_path) - if len(json_streams) == 0: - return StepResult(step=self, status=StepStatus.SKIPPED, stderr="No JSON streams found.") - - data = read_yaml(manifest_path) - if "streams" not in data: - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stderr="No manifest streams found.", - ) - - # find the explit ones and remove or udpate - json_loaders = _find_json_loaders(data, []) - for loader in json_loaders: - logger.info(f" JSON loader ref: {loader.ref} -> {loader.file_path}") - - _update_json_loaders(connector_path, data, json_streams, json_loaders) - - # go through the declared streams and update the inline schemas - for stream in data["streams"]: - if isinstance(stream, str): - # see if reference - if stream.startswith("#"): - yaml_stream = _load_reference(data, stream) - if not yaml_stream: - logger.info(f" Stream reference not found: {stream}") - continue - if not _get_stream_name(yaml_stream): - logger.info(f" Stream reference name not found: {stream}") - continue - else: - logger.info(f" Stream reference unknown: {stream}") - continue - else: - yaml_stream = stream - - if not yaml_stream: - logger.info(f" !! Yaml stream not found: {stream}") - continue - - stream_name = _get_stream_name(yaml_stream) - if not stream_name: - logger.info(f" !! Stream name not found: {stream}") - continue - if yaml_stream.get("schema_loader") and yaml_stream["schema_loader"].get("type") == "InlineSchemaLoader": - continue - - yaml_stream["schema_loader"] = {} - schema_loader = yaml_stream["schema_loader"] - _update_inline_schema(schema_loader, json_streams, stream_name) - - write_yaml(data, manifest_path) - # await format_prettier([manifest_path], logger=logger) - - for json_stream in json_streams.values(): - logger.info(f" !! JSON schema not found: {json_stream.name}") - - return StepResult(step=self, status=StepStatus.SUCCESS) - - -class RemoveUnusedJsonSchamas(Step): - context: ConnectorContext - - title = "Cleanup json schemas that are dangling but unused." - - async def _run(self) -> StepResult: - connector = self.context.connector - python_path = connector.python_source_dir_path - schemas_path = python_path / SCHEMAS_DIR_NAME - logger = self.logger - - manifest = connector.manifest_path.read_text() - - if manifest.find("JsonFileSchemaLoader") != -1: - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stderr="Skipping: the manifest is still using JSON Schema loader.", - ) - - if schemas_path.exists(): - logger.info(f" Removing schemnas dir: {schemas_path}") - shutil.rmtree(schemas_path) - - return StepResult(step=self, status=StepStatus.SUCCESS) - - -@dataclass -class JsonStream: - name: str - schema: dict - file_path: Path - - -@dataclass -class JsonLoaderNode: - ref: str - file_path: str - - -def copy_directory(src: Path, dest: Path) -> None: - if dest.exists(): - shutil.rmtree(dest) - shutil.copytree(src, dest) - - -def _has_subdirectory(directory: Path) -> bool: - # Iterate through all items in the directory - for entry in directory.iterdir(): - # Check if this entry is a directory - if entry.is_dir(): - return True - - return False - - -def _get_stream_name(yaml_stream: dict) -> str | None: - if "name" in yaml_stream: - return yaml_stream["name"] - if "$parameters" in yaml_stream and "name" in yaml_stream["$parameters"]: - return yaml_stream["$parameters"]["name"] - return None - - -def _update_json_loaders( - connector_path: Path, - data: dict, - streams: dict[str, JsonStream], - loaders: List[JsonLoaderNode], -) -> None: - logger = main_logger - for loader in loaders: - if "{{" in loader.file_path: - # remove templated paths and their references - (f" Removing reference: {loader.ref}") - _remove_reference(data, None, loader, []) - continue - else: - # direct pointer to a file. update. - file_path = Path(os.path.abspath(os.path.join(connector_path, loader.file_path))) - if not file_path.is_file(): - logger.info(f" JsonFileSchemaLoader not found: {file_path}") - continue - schema_loader = _load_reference(data, loader.ref) - if not schema_loader: - logger.info(f" JsonFileSchemaLoader reference not found: {loader.ref}") - continue - _update_inline_schema(schema_loader, streams, file_path.stem) - - -def _update_inline_schema(schema_loader: dict, json_streams: dict[str, JsonStream], file_name: str) -> None: - logger = main_logger - if file_name not in json_streams: - logger.info(f" Stream {file_name} not found in JSON schemas.") - return - - json_stream = json_streams[file_name] - schema_loader["type"] = "InlineSchemaLoader" - schema_loader["schema"] = json_stream.schema - - json_stream.file_path.unlink() - json_streams.pop(file_name) - - -def _remove_reference(parent: Any, key: str | int | None, loader: JsonLoaderNode, path: List[str]) -> bool: # noqa: ANN401 - logger = main_logger - if key is None: - data = parent - else: - data = parent[key] - - if isinstance(data, dict): - ref = f"#/{'/'.join(path)}" - if ref == loader.ref: - logger.info(f" Removing reference: {ref}") - return True - elif "$ref" in data and data["$ref"] == loader.ref: - logger.info(f" Found reference: {ref}") - return True - else: - todelete = [] - for key, value in data.items(): - if _remove_reference(data, key, loader, path + [str(key)]): - todelete.append(key) - for key in todelete: - del data[key] - elif isinstance(data, list): - for i, value in enumerate(data): - ref = f"Array[{str(i)}]" - _remove_reference(data, i, loader, path + [ref]) - - return False - - -def _load_reference(data: dict, ref: str) -> dict | None: - yaml_stream = data - path = ref.split("/") - for p in path: - if p == "#": - continue - if p.startswith("Array["): - i = int(p[6:-1]) - if not isinstance(yaml_stream, list) or len(yaml_stream) <= i: - return None - yaml_stream = yaml_stream[i] - continue - if p not in yaml_stream: - return None - yaml_stream = yaml_stream[p] - return yaml_stream - - -def _find_json_loaders(data: Any, path: List[str]) -> List[JsonLoaderNode]: # noqa: ANN401 - logger = main_logger - loaders: List[JsonLoaderNode] = [] - if isinstance(data, dict): - if "type" in data and data["type"] == "JsonFileSchemaLoader": - ref = f"#/{'/'.join(path)}" - if "file_path" in data: - loaders.append(JsonLoaderNode(ref, data["file_path"])) - else: - logger.info(f" !! JsonFileSchemaLoader missing file_path: {ref}") - else: - for key, value in data.items(): - loaders += _find_json_loaders(value, path + [key]) - elif isinstance(data, list): - for i, value in enumerate(data): - loaders += _find_json_loaders(value, path + [f"Array[{str(i)}]"]) - return loaders - - -def _parse_json_streams(python_path: Path) -> dict[str, JsonStream]: - streams: dict[str, JsonStream] = {} - schemas_path = python_path / SCHEMAS_DIR_NAME - if not schemas_path.is_dir(): - return streams - - for schema_file in schemas_path.iterdir(): - if schema_file.is_file() and schema_file.suffix == ".json": - stream_name = schema_file.stem - with schema_file.open("r") as file: - # read json - schema = json.load(file) - streams[stream_name] = JsonStream( - name=stream_name, - schema=schema, - file_path=schema_file, - ) - - return streams - - -async def run_connector_migrate_to_inline_schemas_pipeline(context: ConnectorContext, semaphore: "Semaphore") -> Report: - restore_original_state = RestoreInlineState(context) - - context.targeted_platforms = [LOCAL_BUILD_PLATFORM] - - steps_to_run: STEP_TREE = [] - - steps_to_run.append( - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.INLINE_CANDIDATE, - step=CheckIsInlineCandidate(context), - ) - ] - ) - - steps_to_run.append( - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.INLINE_MIGRATION, - step=InlineSchemas(context), - depends_on=[CONNECTOR_TEST_STEP_ID.INLINE_CANDIDATE], - ) - ] - ) - - steps_to_run.append( - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.INLINE_CLEANUP, - step=RemoveUnusedJsonSchamas(context), - depends_on=[CONNECTOR_TEST_STEP_ID.INLINE_MIGRATION], - ) - ] - ) - - return await run_connector_steps(context, semaphore, steps_to_run, restore_original_state=restore_original_state) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/commands.py deleted file mode 100644 index f7440de7479a..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/commands.py +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -# - -import asyncclick as click - -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.airbyte_ci.connectors.migrate_to_manifest_only.pipeline import run_connectors_manifest_only_pipeline -from pipelines.airbyte_ci.connectors.pipeline import run_connectors_pipelines -from pipelines.cli.dagger_pipeline_command import DaggerPipelineCommand - - -@click.command(cls=DaggerPipelineCommand, short_help="Migrate a low-code connector to manifest-only") -@click.pass_context -async def migrate_to_manifest_only(ctx: click.Context) -> bool: - connectors_contexts = [ - ConnectorContext( - pipeline_name=f"Migrate connector {connector.technical_name} to manifest-only", - connector=connector, - is_local=ctx.obj["is_local"], - git_branch=ctx.obj["git_branch"], - git_revision=ctx.obj["git_revision"], - diffed_branch=ctx.obj["diffed_branch"], - git_repo_url=ctx.obj["git_repo_url"], - report_output_prefix=ctx.obj["report_output_prefix"], - pipeline_start_timestamp=ctx.obj.get("pipeline_start_timestamp"), - ) - for connector in ctx.obj["selected_connectors_with_modified_files"] - ] - - await run_connectors_pipelines( - connectors_contexts, - run_connectors_manifest_only_pipeline, - "Migrate connector to manifest-only pipeline", - ctx.obj["concurrency"], - ctx.obj["dagger_logs_path"], - ctx.obj["execute_timeout"], - ctx.obj["git_branch"], - ctx.obj["git_revision"], - ctx.obj["diffed_branch"], - ctx.obj["is_local"], - ctx.obj["ci_context"], - ctx.obj["git_repo_url"], - ) - - return True diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/declarative_component_schema.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/declarative_component_schema.py deleted file mode 100644 index c58c68dc0968..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/declarative_component_schema.py +++ /dev/null @@ -1,1598 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -# generated by datamodel-codegen: -# filename: declarative_component_schema.yaml - -from __future__ import annotations - -from enum import Enum -from typing import Any, Dict, List, Optional, Union - -from pydantic import BaseModel, Extra, Field -from typing_extensions import Literal - -## WARNING -## This is a hack. I've copied the current version of the models from the generated code and pasted them here since we can't access the CDK from the current directory. -## These are from CDK 4.5.3. -## These models won't update alongside the CDK, so this is a temporary solution to unblock manifest-only migrations. - - -class AuthFlowType(Enum): - oauth2_0 = "oauth2.0" - oauth1_0 = "oauth1.0" - - -class BasicHttpAuthenticator(BaseModel): - type: Literal["BasicHttpAuthenticator"] - username: str = Field( - ..., - description="The username that will be combined with the password, base64 encoded and used to make requests. Fill it in the user inputs.", - examples=["{{ config['username'] }}", "{{ config['api_key'] }}"], - title="Username", - ) - password: Optional[str] = Field( - "", - description="The password that will be combined with the username, base64 encoded and used to make requests. Fill it in the user inputs.", - examples=["{{ config['password'] }}", ""], - title="Password", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class BearerAuthenticator(BaseModel): - type: Literal["BearerAuthenticator"] - api_token: str = Field( - ..., - description="Token to inject as request header for authenticating with the API.", - examples=["{{ config['api_key'] }}", "{{ config['token'] }}"], - title="Bearer Token", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class CheckStream(BaseModel): - type: Literal["CheckStream"] - stream_names: List[str] = Field( - ..., - description="Names of the streams to try reading from when running a check operation.", - examples=[["users"], ["users", "contacts"]], - title="Stream Names", - ) - - -class ConstantBackoffStrategy(BaseModel): - type: Literal["ConstantBackoffStrategy"] - backoff_time_in_seconds: Union[float, str] = Field( - ..., - description="Backoff time in seconds.", - examples=[30, 30.5, "{{ config['backoff_time'] }}"], - title="Backoff Time", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class CustomAuthenticator(BaseModel): - class Config: - extra = Extra.allow - - type: Literal["CustomAuthenticator"] - class_name: str = Field( - ..., - description="Fully-qualified name of the class that will be implementing the custom authentication strategy. Has to be a sub class of DeclarativeAuthenticator. The format is `source_..`.", - examples=["source_railz.components.ShortLivedTokenAuthenticator"], - title="Class Name", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class CustomBackoffStrategy(BaseModel): - class Config: - extra = Extra.allow - - type: Literal["CustomBackoffStrategy"] - class_name: str = Field( - ..., - description="Fully-qualified name of the class that will be implementing the custom backoff strategy. The format is `source_..`.", - examples=["source_railz.components.MyCustomBackoffStrategy"], - title="Class Name", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class CustomErrorHandler(BaseModel): - class Config: - extra = Extra.allow - - type: Literal["CustomErrorHandler"] - class_name: str = Field( - ..., - description="Fully-qualified name of the class that will be implementing the custom error handler. The format is `source_..`.", - examples=["source_railz.components.MyCustomErrorHandler"], - title="Class Name", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class CustomIncrementalSync(BaseModel): - class Config: - extra = Extra.allow - - type: Literal["CustomIncrementalSync"] - class_name: str = Field( - ..., - description="Fully-qualified name of the class that will be implementing the custom incremental sync. The format is `source_..`.", - examples=["source_railz.components.MyCustomIncrementalSync"], - title="Class Name", - ) - cursor_field: str = Field( - ..., - description="The location of the value on a record that will be used as a bookmark during sync.", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class CustomPaginationStrategy(BaseModel): - class Config: - extra = Extra.allow - - type: Literal["CustomPaginationStrategy"] - class_name: str = Field( - ..., - description="Fully-qualified name of the class that will be implementing the custom pagination strategy. The format is `source_..`.", - examples=["source_railz.components.MyCustomPaginationStrategy"], - title="Class Name", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class CustomRecordExtractor(BaseModel): - class Config: - extra = Extra.allow - - type: Literal["CustomRecordExtractor"] - class_name: str = Field( - ..., - description="Fully-qualified name of the class that will be implementing the custom record extraction strategy. The format is `source_..`.", - examples=["source_railz.components.MyCustomRecordExtractor"], - title="Class Name", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class CustomRecordFilter(BaseModel): - class Config: - extra = Extra.allow - - type: Literal["CustomRecordFilter"] - class_name: str = Field( - ..., - description="Fully-qualified name of the class that will be implementing the custom record filter strategy. The format is `source_..`.", - examples=["source_railz.components.MyCustomCustomRecordFilter"], - title="Class Name", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class CustomRequester(BaseModel): - class Config: - extra = Extra.allow - - type: Literal["CustomRequester"] - class_name: str = Field( - ..., - description="Fully-qualified name of the class that will be implementing the custom requester strategy. The format is `source_..`.", - examples=["source_railz.components.MyCustomRecordExtractor"], - title="Class Name", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class CustomRetriever(BaseModel): - class Config: - extra = Extra.allow - - type: Literal["CustomRetriever"] - class_name: str = Field( - ..., - description="Fully-qualified name of the class that will be implementing the custom retriever strategy. The format is `source_..`.", - examples=["source_railz.components.MyCustomRetriever"], - title="Class Name", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class CustomPartitionRouter(BaseModel): - class Config: - extra = Extra.allow - - type: Literal["CustomPartitionRouter"] - class_name: str = Field( - ..., - description="Fully-qualified name of the class that will be implementing the custom partition router. The format is `source_..`.", - examples=["source_railz.components.MyCustomPartitionRouter"], - title="Class Name", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class CustomSchemaLoader(BaseModel): - class Config: - extra = Extra.allow - - type: Literal["CustomSchemaLoader"] - class_name: str = Field( - ..., - description="Fully-qualified name of the class that will be implementing the custom schema loader. The format is `source_..`.", - examples=["source_railz.components.MyCustomSchemaLoader"], - title="Class Name", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class CustomStateMigration(BaseModel): - class Config: - extra = Extra.allow - - type: Literal["CustomStateMigration"] - class_name: str = Field( - ..., - description="Fully-qualified name of the class that will be implementing the custom state migration. The format is `source_..`.", - examples=["source_railz.components.MyCustomStateMigration"], - title="Class Name", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class CustomTransformation(BaseModel): - class Config: - extra = Extra.allow - - type: Literal["CustomTransformation"] - class_name: str = Field( - ..., - description="Fully-qualified name of the class that will be implementing the custom transformation. The format is `source_..`.", - examples=["source_railz.components.MyCustomTransformation"], - title="Class Name", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class LegacyToPerPartitionStateMigration(BaseModel): - class Config: - extra = Extra.allow - - type: Optional[Literal["LegacyToPerPartitionStateMigration"]] = None - - -class Algorithm(Enum): - HS256 = "HS256" - HS384 = "HS384" - HS512 = "HS512" - ES256 = "ES256" - ES256K = "ES256K" - ES384 = "ES384" - ES512 = "ES512" - RS256 = "RS256" - RS384 = "RS384" - RS512 = "RS512" - PS256 = "PS256" - PS384 = "PS384" - PS512 = "PS512" - EdDSA = "EdDSA" - - -class JwtHeaders(BaseModel): - class Config: - extra = Extra.forbid - - kid: Optional[str] = Field( - None, - description="Private key ID for user account.", - examples=["{{ config['kid'] }}"], - title="Key Identifier", - ) - typ: Optional[str] = Field( - "JWT", - description="The media type of the complete JWT.", - examples=["JWT"], - title="Type", - ) - cty: Optional[str] = Field( - None, - description="Content type of JWT header.", - examples=["JWT"], - title="Content Type", - ) - - -class JwtPayload(BaseModel): - class Config: - extra = Extra.forbid - - iss: Optional[str] = Field( - None, - description="The user/principal that issued the JWT. Commonly a value unique to the user.", - examples=["{{ config['iss'] }}"], - title="Issuer", - ) - sub: Optional[str] = Field( - None, - description="The subject of the JWT. Commonly defined by the API.", - title="Subject", - ) - aud: Optional[str] = Field( - None, - description="The recipient that the JWT is intended for. Commonly defined by the API.", - examples=["appstoreconnect-v1"], - title="Audience", - ) - - -class JwtAuthenticator(BaseModel): - type: Literal["JwtAuthenticator"] - secret_key: str = Field( - ..., - description="Secret used to sign the JSON web token.", - examples=["{{ config['secret_key'] }}"], - ) - base64_encode_secret_key: Optional[bool] = Field( - False, - description='When set to true, the secret key will be base64 encoded prior to being encoded as part of the JWT. Only set to "true" when required by the API.', - ) - algorithm: Algorithm = Field( - ..., - description="Algorithm used to sign the JSON web token.", - examples=["ES256", "HS256", "RS256", "{{ config['algorithm'] }}"], - ) - token_duration: Optional[int] = Field( - 1200, - description="The amount of time in seconds a JWT token can be valid after being issued.", - examples=[1200, 3600], - title="Token Duration", - ) - header_prefix: Optional[str] = Field( - None, - description="The prefix to be used within the Authentication header.", - examples=["Bearer", "Basic"], - title="Header Prefix", - ) - jwt_headers: Optional[JwtHeaders] = Field( - None, - description="JWT headers used when signing JSON web token.", - title="JWT Headers", - ) - additional_jwt_headers: Optional[Dict[str, Any]] = Field( - None, - description="Additional headers to be included with the JWT headers object.", - title="Additional JWT Headers", - ) - jwt_payload: Optional[JwtPayload] = Field( - None, - description="JWT Payload used when signing JSON web token.", - title="JWT Payload", - ) - additional_jwt_payload: Optional[Dict[str, Any]] = Field( - None, - description="Additional properties to be added to the JWT payload.", - title="Additional JWT Payload Properties", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class RefreshTokenUpdater(BaseModel): - refresh_token_name: Optional[str] = Field( - "refresh_token", - description="The name of the property which contains the updated refresh token in the response from the token refresh endpoint.", - examples=["refresh_token"], - title="Refresh Token Property Name", - ) - access_token_config_path: Optional[List[str]] = Field( - ["credentials", "access_token"], - description="Config path to the access token. Make sure the field actually exists in the config.", - examples=[["credentials", "access_token"], ["access_token"]], - title="Config Path To Access Token", - ) - refresh_token_config_path: Optional[List[str]] = Field( - ["credentials", "refresh_token"], - description="Config path to the access token. Make sure the field actually exists in the config.", - examples=[["credentials", "refresh_token"], ["refresh_token"]], - title="Config Path To Refresh Token", - ) - token_expiry_date_config_path: Optional[List[str]] = Field( - ["credentials", "token_expiry_date"], - description="Config path to the expiry date. Make sure actually exists in the config.", - examples=[["credentials", "token_expiry_date"]], - title="Config Path To Expiry Date", - ) - refresh_token_error_status_codes: Optional[List[int]] = Field( - [], - description="Status Codes to Identify refresh token error in response (Refresh Token Error Key and Refresh Token Error Values should be also specified). Responses with one of the error status code and containing an error value will be flagged as a config error", - examples=[[400, 500]], - title="Refresh Token Error Status Codes", - ) - refresh_token_error_key: Optional[str] = Field( - "", - description="Key to Identify refresh token error in response (Refresh Token Error Status Codes and Refresh Token Error Values should be also specified).", - examples=["error"], - title="Refresh Token Error Key", - ) - refresh_token_error_values: Optional[List[str]] = Field( - [], - description='List of values to check for exception during token refresh process. Used to check if the error found in the response matches the key from the Refresh Token Error Key field (e.g. response={"error": "invalid_grant"}). Only responses with one of the error status code and containing an error value will be flagged as a config error', - examples=[["invalid_grant", "invalid_permissions"]], - title="Refresh Token Error Values", - ) - - -class OAuthAuthenticator(BaseModel): - type: Literal["OAuthAuthenticator"] - client_id: str = Field( - ..., - description="The OAuth client ID. Fill it in the user inputs.", - examples=["{{ config['client_id }}", "{{ config['credentials']['client_id }}"], - title="Client ID", - ) - client_secret: str = Field( - ..., - description="The OAuth client secret. Fill it in the user inputs.", - examples=[ - "{{ config['client_secret }}", - "{{ config['credentials']['client_secret }}", - ], - title="Client Secret", - ) - refresh_token: Optional[str] = Field( - None, - description="Credential artifact used to get a new access token.", - examples=[ - "{{ config['refresh_token'] }}", - "{{ config['credentials]['refresh_token'] }}", - ], - title="Refresh Token", - ) - token_refresh_endpoint: str = Field( - ..., - description="The full URL to call to obtain a new access token.", - examples=["https://connect.squareup.com/oauth2/token"], - title="Token Refresh Endpoint", - ) - access_token_name: Optional[str] = Field( - "access_token", - description="The name of the property which contains the access token in the response from the token refresh endpoint.", - examples=["access_token"], - title="Access Token Property Name", - ) - expires_in_name: Optional[str] = Field( - "expires_in", - description="The name of the property which contains the expiry date in the response from the token refresh endpoint.", - examples=["expires_in"], - title="Token Expiry Property Name", - ) - grant_type: Optional[str] = Field( - "refresh_token", - description="Specifies the OAuth2 grant type. If set to refresh_token, the refresh_token needs to be provided as well. For client_credentials, only client id and secret are required. Other grant types are not officially supported.", - examples=["refresh_token", "client_credentials"], - title="Grant Type", - ) - refresh_request_body: Optional[Dict[str, Any]] = Field( - None, - description="Body of the request sent to get a new access token.", - examples=[ - { - "applicationId": "{{ config['application_id'] }}", - "applicationSecret": "{{ config['application_secret'] }}", - "token": "{{ config['token'] }}", - } - ], - title="Refresh Request Body", - ) - scopes: Optional[List[str]] = Field( - None, - description="List of scopes that should be granted to the access token.", - examples=[["crm.list.read", "crm.objects.contacts.read", "crm.schema.contacts.read"]], - title="Scopes", - ) - token_expiry_date: Optional[str] = Field( - None, - description="The access token expiry date.", - examples=["2023-04-06T07:12:10.421833+00:00", 1680842386], - title="Token Expiry Date", - ) - token_expiry_date_format: Optional[str] = Field( - None, - description="The format of the time to expiration datetime. Provide it if the time is returned as a date-time string instead of seconds.", - examples=["%Y-%m-%d %H:%M:%S.%f+00:00"], - title="Token Expiry Date Format", - ) - refresh_token_updater: Optional[RefreshTokenUpdater] = Field( - None, - description="When the token updater is defined, new refresh tokens, access tokens and the access token expiry date are written back from the authentication response to the config object. This is important if the refresh token can only used once.", - title="Token Updater", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class ExponentialBackoffStrategy(BaseModel): - type: Literal["ExponentialBackoffStrategy"] - factor: Optional[Union[float, str]] = Field( - 5, - description="Multiplicative constant applied on each retry.", - examples=[5, 5.5, "10"], - title="Factor", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class SessionTokenRequestBearerAuthenticator(BaseModel): - type: Literal["Bearer"] - - -class HttpMethod(Enum): - GET = "GET" - POST = "POST" - - -class Action(Enum): - SUCCESS = "SUCCESS" - FAIL = "FAIL" - RETRY = "RETRY" - IGNORE = "IGNORE" - RATE_LIMITED = "RATE_LIMITED" - - -class FailureType(Enum): - system_error = "system_error" - config_error = "config_error" - transient_error = "transient_error" - - -class HttpResponseFilter(BaseModel): - type: Literal["HttpResponseFilter"] - action: Optional[Action] = Field( - None, - description="Action to execute if a response matches the filter.", - examples=["SUCCESS", "FAIL", "RETRY", "IGNORE", "RATE_LIMITED"], - title="Action", - ) - failure_type: Optional[FailureType] = Field( - None, - description="Failure type of traced exception if a response matches the filter.", - examples=["system_error", "config_error", "transient_error"], - title="Failure Type", - ) - error_message: Optional[str] = Field( - None, - description="Error Message to display if the response matches the filter.", - title="Error Message", - ) - error_message_contains: Optional[str] = Field( - None, - description="Match the response if its error message contains the substring.", - example=["This API operation is not enabled for this site"], - title="Error Message Substring", - ) - http_codes: Optional[List[int]] = Field( - None, - description="Match the response if its HTTP code is included in this list.", - examples=[[420, 429], [500]], - title="HTTP Codes", - ) - predicate: Optional[str] = Field( - None, - description="Match the response if the predicate evaluates to true.", - examples=[ - "{{ 'Too much requests' in response }}", - "{{ 'error_code' in response and response['error_code'] == 'ComplexityException' }}", - ], - title="Predicate", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class InlineSchemaLoader(BaseModel): - type: Literal["InlineSchemaLoader"] - schema_: Optional[Dict[str, Any]] = Field( - None, - alias="schema", - description='Describes a streams\' schema. Refer to the Data Types documentation for more details on which types are valid.', - title="Schema", - ) - - -class JsonFileSchemaLoader(BaseModel): - type: Literal["JsonFileSchemaLoader"] - file_path: Optional[str] = Field( - None, - description="Path to the JSON file defining the schema. The path is relative to the connector module's root.", - example=["./schemas/users.json"], - title="File Path", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class JsonDecoder(BaseModel): - type: Literal["JsonDecoder"] - - -class JsonlDecoder(BaseModel): - type: Literal["JsonlDecoder"] - - -class IterableDecoder(BaseModel): - type: Literal["IterableDecoder"] - - -class MinMaxDatetime(BaseModel): - type: Literal["MinMaxDatetime"] - datetime: str = Field( - ..., - description="Datetime value.", - examples=["2021-01-01", "2021-01-01T00:00:00Z", "{{ config['start_time'] }}"], - title="Datetime", - ) - datetime_format: Optional[str] = Field( - "", - description='Format of the datetime value. Defaults to "%Y-%m-%dT%H:%M:%S.%f%z" if left empty. Use placeholders starting with "%" to describe the format the API is using. The following placeholders are available:\n * **%s**: Epoch unix timestamp - `1686218963`\n * **%s_as_float**: Epoch unix timestamp in seconds as float with microsecond precision - `1686218963.123456`\n * **%ms**: Epoch unix timestamp - `1686218963123`\n * **%a**: Weekday (abbreviated) - `Sun`\n * **%A**: Weekday (full) - `Sunday`\n * **%w**: Weekday (decimal) - `0` (Sunday), `6` (Saturday)\n * **%d**: Day of the month (zero-padded) - `01`, `02`, ..., `31`\n * **%b**: Month (abbreviated) - `Jan`\n * **%B**: Month (full) - `January`\n * **%m**: Month (zero-padded) - `01`, `02`, ..., `12`\n * **%y**: Year (without century, zero-padded) - `00`, `01`, ..., `99`\n * **%Y**: Year (with century) - `0001`, `0002`, ..., `9999`\n * **%H**: Hour (24-hour, zero-padded) - `00`, `01`, ..., `23`\n * **%I**: Hour (12-hour, zero-padded) - `01`, `02`, ..., `12`\n * **%p**: AM/PM indicator\n * **%M**: Minute (zero-padded) - `00`, `01`, ..., `59`\n * **%S**: Second (zero-padded) - `00`, `01`, ..., `59`\n * **%f**: Microsecond (zero-padded to 6 digits) - `000000`, `000001`, ..., `999999`\n * **%z**: UTC offset - `(empty)`, `+0000`, `-04:00`\n * **%Z**: Time zone name - `(empty)`, `UTC`, `GMT`\n * **%j**: Day of the year (zero-padded) - `001`, `002`, ..., `366`\n * **%U**: Week number of the year (Sunday as first day) - `00`, `01`, ..., `53`\n * **%W**: Week number of the year (Monday as first day) - `00`, `01`, ..., `53`\n * **%c**: Date and time representation - `Tue Aug 16 21:30:00 1988`\n * **%x**: Date representation - `08/16/1988`\n * **%X**: Time representation - `21:30:00`\n * **%%**: Literal \'%\' character\n\n Some placeholders depend on the locale of the underlying system - in most cases this locale is configured as en/US. For more information see the [Python documentation](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes).\n', - examples=["%Y-%m-%dT%H:%M:%S.%f%z", "%Y-%m-%d", "%s"], - title="Datetime Format", - ) - max_datetime: Optional[str] = Field( - None, - description="Ceiling applied on the datetime value. Must be formatted with the datetime_format field.", - examples=["2021-01-01T00:00:00Z", "2021-01-01"], - title="Max Datetime", - ) - min_datetime: Optional[str] = Field( - None, - description="Floor applied on the datetime value. Must be formatted with the datetime_format field.", - examples=["2010-01-01T00:00:00Z", "2010-01-01"], - title="Min Datetime", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class NoAuth(BaseModel): - type: Literal["NoAuth"] - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class NoPagination(BaseModel): - type: Literal["NoPagination"] - - -class OAuthConfigSpecification(BaseModel): - class Config: - extra = Extra.allow - - oauth_user_input_from_connector_config_specification: Optional[Dict[str, Any]] = Field( - None, - description="OAuth specific blob. This is a Json Schema used to validate Json configurations used as input to OAuth.\nMust be a valid non-nested JSON that refers to properties from ConnectorSpecification.connectionSpecification\nusing special annotation 'path_in_connector_config'.\nThese are input values the user is entering through the UI to authenticate to the connector, that might also shared\nas inputs for syncing data via the connector.\nExamples:\nif no connector values is shared during oauth flow, oauth_user_input_from_connector_config_specification=[]\nif connector values such as 'app_id' inside the top level are used to generate the API url for the oauth flow,\n oauth_user_input_from_connector_config_specification={\n app_id: {\n type: string\n path_in_connector_config: ['app_id']\n }\n }\nif connector values such as 'info.app_id' nested inside another object are used to generate the API url for the oauth flow,\n oauth_user_input_from_connector_config_specification={\n app_id: {\n type: string\n path_in_connector_config: ['info', 'app_id']\n }\n }", - examples=[ - {"app_id": {"type": "string", "path_in_connector_config": ["app_id"]}}, - { - "app_id": { - "type": "string", - "path_in_connector_config": ["info", "app_id"], - } - }, - ], - title="OAuth user input", - ) - complete_oauth_output_specification: Optional[Dict[str, Any]] = Field( - None, - description="OAuth specific blob. This is a Json Schema used to validate Json configurations produced by the OAuth flows as they are\nreturned by the distant OAuth APIs.\nMust be a valid JSON describing the fields to merge back to `ConnectorSpecification.connectionSpecification`.\nFor each field, a special annotation `path_in_connector_config` can be specified to determine where to merge it,\nExamples:\n complete_oauth_output_specification={\n refresh_token: {\n type: string,\n path_in_connector_config: ['credentials', 'refresh_token']\n }\n }", - examples=[ - { - "refresh_token": { - "type": "string,", - "path_in_connector_config": ["credentials", "refresh_token"], - } - } - ], - title="OAuth output specification", - ) - complete_oauth_server_input_specification: Optional[Dict[str, Any]] = Field( - None, - description="OAuth specific blob. This is a Json Schema used to validate Json configurations persisted as Airbyte Server configurations.\nMust be a valid non-nested JSON describing additional fields configured by the Airbyte Instance or Workspace Admins to be used by the\nserver when completing an OAuth flow (typically exchanging an auth code for refresh token).\nExamples:\n complete_oauth_server_input_specification={\n client_id: {\n type: string\n },\n client_secret: {\n type: string\n }\n }", - examples=[{"client_id": {"type": "string"}, "client_secret": {"type": "string"}}], - title="OAuth input specification", - ) - complete_oauth_server_output_specification: Optional[Dict[str, Any]] = Field( - None, - description="OAuth specific blob. This is a Json Schema used to validate Json configurations persisted as Airbyte Server configurations that\nalso need to be merged back into the connector configuration at runtime.\nThis is a subset configuration of `complete_oauth_server_input_specification` that filters fields out to retain only the ones that\nare necessary for the connector to function with OAuth. (some fields could be used during oauth flows but not needed afterwards, therefore\nthey would be listed in the `complete_oauth_server_input_specification` but not `complete_oauth_server_output_specification`)\nMust be a valid non-nested JSON describing additional fields configured by the Airbyte Instance or Workspace Admins to be used by the\nconnector when using OAuth flow APIs.\nThese fields are to be merged back to `ConnectorSpecification.connectionSpecification`.\nFor each field, a special annotation `path_in_connector_config` can be specified to determine where to merge it,\nExamples:\n complete_oauth_server_output_specification={\n client_id: {\n type: string,\n path_in_connector_config: ['credentials', 'client_id']\n },\n client_secret: {\n type: string,\n path_in_connector_config: ['credentials', 'client_secret']\n }\n }", - examples=[ - { - "client_id": { - "type": "string,", - "path_in_connector_config": ["credentials", "client_id"], - }, - "client_secret": { - "type": "string,", - "path_in_connector_config": ["credentials", "client_secret"], - }, - } - ], - title="OAuth server output specification", - ) - - -class OffsetIncrement(BaseModel): - type: Literal["OffsetIncrement"] - page_size: Optional[Union[int, str]] = Field( - None, - description="The number of records to include in each pages.", - examples=[100, "{{ config['page_size'] }}"], - title="Limit", - ) - inject_on_first_request: Optional[bool] = Field( - False, - description="Using the `offset` with value `0` during the first request", - title="Inject Offset", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class PageIncrement(BaseModel): - type: Literal["PageIncrement"] - page_size: Optional[Union[int, str]] = Field( - None, - description="The number of records to include in each pages.", - examples=[100, "100", "{{ config['page_size'] }}"], - title="Page Size", - ) - start_from_page: Optional[int] = Field( - 0, - description="Index of the first page to request.", - examples=[0, 1], - title="Start From Page", - ) - inject_on_first_request: Optional[bool] = Field( - False, - description="Using the `page number` with value defined by `start_from_page` during the first request", - title="Inject Page Number", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class PrimaryKey(BaseModel): - __root__: Union[str, List[str], List[List[str]]] = Field( - ..., - description="The stream field to be used to distinguish unique records. Can either be a single field, an array of fields representing a composite key, or an array of arrays representing a composite key where the fields are nested fields.", - examples=["id", ["code", "type"]], - title="Primary Key", - ) - - -class RecordFilter(BaseModel): - type: Literal["RecordFilter"] - condition: Optional[str] = Field( - "", - description="The predicate to filter a record. Records will be removed if evaluated to False.", - examples=[ - "{{ record['created_at'] >= stream_interval['start_time'] }}", - "{{ record.status in ['active', 'expired'] }}", - ], - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class SchemaNormalization(Enum): - None_ = "None" - Default = "Default" - - -class RemoveFields(BaseModel): - type: Literal["RemoveFields"] - condition: Optional[str] = Field( - "", - description="The predicate to filter a property by a property value. Property will be removed if it is empty OR expression is evaluated to True.,", - examples=[ - "{{ property|string == '' }}", - "{{ property is integer }}", - "{{ property|length > 5 }}", - "{{ property == 'some_string_to_match' }}", - ], - ) - field_pointers: List[List[str]] = Field( - ..., - description="Array of paths defining the field to remove. Each item is an array whose field describe the path of a field to remove.", - examples=[["tags"], [["content", "html"], ["content", "plain_text"]]], - title="Field Paths", - ) - - -class RequestPath(BaseModel): - type: Literal["RequestPath"] - - -class InjectInto(Enum): - request_parameter = "request_parameter" - header = "header" - body_data = "body_data" - body_json = "body_json" - - -class RequestOption(BaseModel): - type: Literal["RequestOption"] - field_name: str = Field( - ..., - description="Configures which key should be used in the location that the descriptor is being injected into", - examples=["segment_id"], - title="Request Option", - ) - inject_into: InjectInto = Field( - ..., - description="Configures where the descriptor should be set on the HTTP requests. Note that request parameters that are already encoded in the URL path will not be duplicated.", - examples=["request_parameter", "header", "body_data", "body_json"], - title="Inject Into", - ) - - -class Schemas(BaseModel): - pass - - class Config: - extra = Extra.allow - - -class LegacySessionTokenAuthenticator(BaseModel): - type: Literal["LegacySessionTokenAuthenticator"] - header: str = Field( - ..., - description="The name of the session token header that will be injected in the request", - examples=["X-Session"], - title="Session Request Header", - ) - login_url: str = Field( - ..., - description="Path of the login URL (do not include the base URL)", - examples=["session"], - title="Login Path", - ) - session_token: Optional[str] = Field( - None, - description="Session token to use if using a pre-defined token. Not needed if authenticating with username + password pair", - example=["{{ config['session_token'] }}"], - title="Session Token", - ) - session_token_response_key: str = Field( - ..., - description="Name of the key of the session token to be extracted from the response", - examples=["id"], - title="Response Token Response Key", - ) - username: Optional[str] = Field( - None, - description="Username used to authenticate and obtain a session token", - examples=[" {{ config['username'] }}"], - title="Username", - ) - password: Optional[str] = Field( - "", - description="Password used to authenticate and obtain a session token", - examples=["{{ config['password'] }}", ""], - title="Password", - ) - validate_session_url: str = Field( - ..., - description="Path of the URL to use to validate that the session token is valid (do not include the base URL)", - examples=["user/current"], - title="Validate Session Path", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class ValueType(Enum): - string = "string" - number = "number" - integer = "integer" - boolean = "boolean" - - -class WaitTimeFromHeader(BaseModel): - type: Literal["WaitTimeFromHeader"] - header: str = Field( - ..., - description="The name of the response header defining how long to wait before retrying.", - examples=["Retry-After"], - title="Response Header Name", - ) - regex: Optional[str] = Field( - None, - description="Optional regex to apply on the header to extract its value. The regex should define a capture group defining the wait time.", - examples=["([-+]?\\d+)"], - title="Extraction Regex", - ) - max_waiting_time_in_seconds: Optional[float] = Field( - None, - description="Given the value extracted from the header is greater than this value, stop the stream.", - examples=[3600], - title="Max Waiting Time in Seconds", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class WaitUntilTimeFromHeader(BaseModel): - type: Literal["WaitUntilTimeFromHeader"] - header: str = Field( - ..., - description="The name of the response header defining how long to wait before retrying.", - examples=["wait_time"], - title="Response Header", - ) - min_wait: Optional[Union[float, str]] = Field( - None, - description="Minimum time to wait before retrying.", - examples=[10, "60"], - title="Minimum Wait Time", - ) - regex: Optional[str] = Field( - None, - description="Optional regex to apply on the header to extract its value. The regex should define a capture group defining the wait time.", - examples=["([-+]?\\d+)"], - title="Extraction Regex", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class AddedFieldDefinition(BaseModel): - type: Literal["AddedFieldDefinition"] - path: List[str] = Field( - ..., - description="List of strings defining the path where to add the value on the record.", - examples=[["segment_id"], ["metadata", "segment_id"]], - title="Path", - ) - value: str = Field( - ..., - description="Value of the new field. Use {{ record['existing_field'] }} syntax to refer to other fields in the record.", - examples=[ - "{{ record['updates'] }}", - "{{ record['MetaData']['LastUpdatedTime'] }}", - "{{ stream_partition['segment_id'] }}", - ], - title="Value", - ) - value_type: Optional[ValueType] = Field( - None, - description="Type of the value. If not specified, the type will be inferred from the value.", - title="Value Type", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class AddFields(BaseModel): - type: Literal["AddFields"] - fields: List[AddedFieldDefinition] = Field( - ..., - description="List of transformations (path and corresponding value) that will be added to the record.", - title="Fields", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class ApiKeyAuthenticator(BaseModel): - type: Literal["ApiKeyAuthenticator"] - api_token: Optional[str] = Field( - None, - description="The API key to inject in the request. Fill it in the user inputs.", - examples=["{{ config['api_key'] }}", "Token token={{ config['api_key'] }}"], - title="API Key", - ) - header: Optional[str] = Field( - None, - description="The name of the HTTP header that will be set to the API key. This setting is deprecated, use inject_into instead. Header and inject_into can not be defined at the same time.", - examples=["Authorization", "Api-Token", "X-Auth-Token"], - title="Header Name", - ) - inject_into: Optional[RequestOption] = Field( - None, - description="Configure how the API Key will be sent in requests to the source API. Either inject_into or header has to be defined.", - examples=[ - {"inject_into": "header", "field_name": "Authorization"}, - {"inject_into": "request_parameter", "field_name": "authKey"}, - ], - title="Inject API Key Into Outgoing HTTP Request", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class AuthFlow(BaseModel): - auth_flow_type: Optional[AuthFlowType] = Field(None, description="The type of auth to use", title="Auth flow type") - predicate_key: Optional[List[str]] = Field( - None, - description="JSON path to a field in the connectorSpecification that should exist for the advanced auth to be applicable.", - examples=[["credentials", "auth_type"]], - title="Predicate key", - ) - predicate_value: Optional[str] = Field( - None, - description="Value of the predicate_key fields for the advanced auth to be applicable.", - examples=["Oauth"], - title="Predicate value", - ) - oauth_config_specification: Optional[OAuthConfigSpecification] = None - - -class CursorPagination(BaseModel): - type: Literal["CursorPagination"] - cursor_value: str = Field( - ..., - description="Value of the cursor defining the next page to fetch.", - examples=[ - "{{ headers.link.next.cursor }}", - "{{ last_record['key'] }}", - "{{ response['nextPage'] }}", - ], - title="Cursor Value", - ) - page_size: Optional[int] = Field( - None, - description="The number of records to include in each pages.", - examples=[100], - title="Page Size", - ) - stop_condition: Optional[str] = Field( - None, - description="Template string evaluating when to stop paginating.", - examples=[ - "{{ response.data.has_more is false }}", - "{{ 'next' not in headers['link'] }}", - ], - title="Stop Condition", - ) - decoder: Optional[JsonDecoder] = Field( - None, - description="Component decoding the response so records can be extracted.", - title="Decoder", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class DatetimeBasedCursor(BaseModel): - type: Literal["DatetimeBasedCursor"] - cursor_field: str = Field( - ..., - description="The location of the value on a record that will be used as a bookmark during sync. To ensure no data loss, the API must return records in ascending order based on the cursor field. Nested fields are not supported, so the field must be at the top level of the record. You can use a combination of Add Field and Remove Field transformations to move the nested field to the top.", - examples=["created_at", "{{ config['record_cursor'] }}"], - title="Cursor Field", - ) - datetime_format: str = Field( - ..., - description="The datetime format used to format the datetime values that are sent in outgoing requests to the API. Use placeholders starting with \"%\" to describe the format the API is using. The following placeholders are available:\n * **%s**: Epoch unix timestamp - `1686218963`\n * **%s_as_float**: Epoch unix timestamp in seconds as float with microsecond precision - `1686218963.123456`\n * **%ms**: Epoch unix timestamp (milliseconds) - `1686218963123`\n * **%a**: Weekday (abbreviated) - `Sun`\n * **%A**: Weekday (full) - `Sunday`\n * **%w**: Weekday (decimal) - `0` (Sunday), `6` (Saturday)\n * **%d**: Day of the month (zero-padded) - `01`, `02`, ..., `31`\n * **%b**: Month (abbreviated) - `Jan`\n * **%B**: Month (full) - `January`\n * **%m**: Month (zero-padded) - `01`, `02`, ..., `12`\n * **%y**: Year (without century, zero-padded) - `00`, `01`, ..., `99`\n * **%Y**: Year (with century) - `0001`, `0002`, ..., `9999`\n * **%H**: Hour (24-hour, zero-padded) - `00`, `01`, ..., `23`\n * **%I**: Hour (12-hour, zero-padded) - `01`, `02`, ..., `12`\n * **%p**: AM/PM indicator\n * **%M**: Minute (zero-padded) - `00`, `01`, ..., `59`\n * **%S**: Second (zero-padded) - `00`, `01`, ..., `59`\n * **%f**: Microsecond (zero-padded to 6 digits) - `000000`\n * **%z**: UTC offset - `(empty)`, `+0000`, `-04:00`\n * **%Z**: Time zone name - `(empty)`, `UTC`, `GMT`\n * **%j**: Day of the year (zero-padded) - `001`, `002`, ..., `366`\n * **%U**: Week number of the year (starting Sunday) - `00`, ..., `53`\n * **%W**: Week number of the year (starting Monday) - `00`, ..., `53`\n * **%c**: Date and time - `Tue Aug 16 21:30:00 1988`\n * **%x**: Date standard format - `08/16/1988`\n * **%X**: Time standard format - `21:30:00`\n * **%%**: Literal '%' character\n\n Some placeholders depend on the locale of the underlying system - in most cases this locale is configured as en/US. For more information see the [Python documentation](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes).\n", - examples=["%Y-%m-%dT%H:%M:%S.%f%z", "%Y-%m-%d", "%s", "%ms", "%s_as_float"], - title="Outgoing Datetime Format", - ) - start_datetime: Union[str, MinMaxDatetime] = Field( - ..., - description="The datetime that determines the earliest record that should be synced.", - examples=["2020-01-1T00:00:00Z", "{{ config['start_time'] }}"], - title="Start Datetime", - ) - cursor_datetime_formats: Optional[List[str]] = Field( - None, - description="The possible formats for the cursor field, in order of preference. The first format that matches the cursor field value will be used to parse it. If not provided, the `datetime_format` will be used.", - title="Cursor Datetime Formats", - ) - cursor_granularity: Optional[str] = Field( - None, - description="Smallest increment the datetime_format has (ISO 8601 duration) that is used to ensure the start of a slice does not overlap with the end of the previous one, e.g. for %Y-%m-%d the granularity should be P1D, for %Y-%m-%dT%H:%M:%SZ the granularity should be PT1S. Given this field is provided, `step` needs to be provided as well.", - examples=["PT1S"], - title="Cursor Granularity", - ) - end_datetime: Optional[Union[str, MinMaxDatetime]] = Field( - None, - description="The datetime that determines the last record that should be synced. If not provided, `{{ now_utc() }}` will be used.", - examples=["2021-01-1T00:00:00Z", "{{ now_utc() }}", "{{ day_delta(-1) }}"], - title="End Datetime", - ) - end_time_option: Optional[RequestOption] = Field( - None, - description="Optionally configures how the end datetime will be sent in requests to the source API.", - title="Inject End Time Into Outgoing HTTP Request", - ) - is_data_feed: Optional[bool] = Field( - None, - description="A data feed API is an API that does not allow filtering and paginates the content from the most recent to the least recent. Given this, the CDK needs to know when to stop paginating and this field will generate a stop condition for pagination.", - title="Whether the target API is formatted as a data feed", - ) - is_client_side_incremental: Optional[bool] = Field( - None, - description="If the target API endpoint does not take cursor values to filter records and returns all records anyway, the connector with this cursor will filter out records locally, and only emit new records from the last sync, hence incremental. This means that all records would be read from the API, but only new records will be emitted to the destination.", - title="Whether the target API does not support filtering and returns all data (the cursor filters records in the client instead of the API side)", - ) - is_compare_strictly: Optional[bool] = Field( - False, - description="Set to True if the target API does not accept queries where the start time equal the end time.", - title="Whether to skip requests if the start time equals the end time", - ) - lookback_window: Optional[str] = Field( - None, - description="Time interval before the start_datetime to read data for, e.g. P1M for looking back one month.", - examples=["P1D", "P{{ config['lookback_days'] }}D"], - title="Lookback Window", - ) - partition_field_end: Optional[str] = Field( - None, - description="Name of the partition start time field.", - examples=["ending_time"], - title="Partition Field End", - ) - partition_field_start: Optional[str] = Field( - None, - description="Name of the partition end time field.", - examples=["starting_time"], - title="Partition Field Start", - ) - start_time_option: Optional[RequestOption] = Field( - None, - description="Optionally configures how the start datetime will be sent in requests to the source API.", - title="Inject Start Time Into Outgoing HTTP Request", - ) - step: Optional[str] = Field( - None, - description="The size of the time window (ISO8601 duration). Given this field is provided, `cursor_granularity` needs to be provided as well.", - examples=["P1W", "{{ config['step_increment'] }}"], - title="Step", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class DefaultErrorHandler(BaseModel): - type: Literal["DefaultErrorHandler"] - backoff_strategies: Optional[ - List[ - Union[ - ConstantBackoffStrategy, - CustomBackoffStrategy, - ExponentialBackoffStrategy, - WaitTimeFromHeader, - WaitUntilTimeFromHeader, - ] - ] - ] = Field( - None, - description="List of backoff strategies to use to determine how long to wait before retrying a retryable request.", - title="Backoff Strategies", - ) - max_retries: Optional[int] = Field( - 5, - description="The maximum number of time to retry a retryable request before giving up and failing.", - examples=[5, 0, 10], - title="Max Retry Count", - ) - response_filters: Optional[List[HttpResponseFilter]] = Field( - None, - description="List of response filters to iterate on when deciding how to handle an error. When using an array of multiple filters, the filters will be applied sequentially and the response will be selected if it matches any of the filter's predicate.", - title="Response Filters", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class DefaultPaginator(BaseModel): - type: Literal["DefaultPaginator"] - pagination_strategy: Union[CursorPagination, CustomPaginationStrategy, OffsetIncrement, PageIncrement] = Field( - ..., - description="Strategy defining how records are paginated.", - title="Pagination Strategy", - ) - decoder: Optional[JsonDecoder] = Field( - None, - description="Component decoding the response so records can be extracted.", - title="Decoder", - ) - page_size_option: Optional[RequestOption] = None - page_token_option: Optional[Union[RequestOption, RequestPath]] = None - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class DpathExtractor(BaseModel): - type: Literal["DpathExtractor"] - field_path: List[str] = Field( - ..., - description='List of potentially nested fields describing the full path of the field to extract. Use "*" to extract all values from an array. See more info in the [docs](https://docs.airbyte.com/connector-development/config-based/understanding-the-yaml-file/record-selector).', - examples=[ - ["data"], - ["data", "records"], - ["data", "{{ parameters.name }}"], - ["data", "*", "record"], - ], - title="Field Path", - ) - decoder: Optional[Union[JsonDecoder, JsonlDecoder, IterableDecoder]] = Field(None, title="Decoder") - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class SessionTokenRequestApiKeyAuthenticator(BaseModel): - type: Literal["ApiKey"] - inject_into: RequestOption = Field( - ..., - description="Configure how the API Key will be sent in requests to the source API.", - examples=[ - {"inject_into": "header", "field_name": "Authorization"}, - {"inject_into": "request_parameter", "field_name": "authKey"}, - ], - title="Inject API Key Into Outgoing HTTP Request", - ) - - -class ListPartitionRouter(BaseModel): - type: Literal["ListPartitionRouter"] - cursor_field: str = Field( - ..., - description='While iterating over list values, the name of field used to reference a list value. The partition value can be accessed with string interpolation. e.g. "{{ stream_partition[\'my_key\'] }}" where "my_key" is the value of the cursor_field.', - examples=["section", "{{ config['section_key'] }}"], - title="Current Partition Value Identifier", - ) - values: Union[str, List[str]] = Field( - ..., - description="The list of attributes being iterated over and used as input for the requests made to the source API.", - examples=[["section_a", "section_b", "section_c"], "{{ config['sections'] }}"], - title="Partition Values", - ) - request_option: Optional[RequestOption] = Field( - None, - description="A request option describing where the list value should be injected into and under what field name if applicable.", - title="Inject Partition Value Into Outgoing HTTP Request", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class RecordSelector(BaseModel): - type: Literal["RecordSelector"] - extractor: Union[CustomRecordExtractor, DpathExtractor] - record_filter: Optional[Union[CustomRecordFilter, RecordFilter]] = Field( - None, - description="Responsible for filtering records to be emitted by the Source.", - title="Record Filter", - ) - schema_normalization: Optional[SchemaNormalization] = SchemaNormalization.None_ - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class Spec(BaseModel): - type: Literal["Spec"] - connection_specification: Dict[str, Any] = Field( - ..., - description="A connection specification describing how a the connector can be configured.", - title="Connection Specification", - ) - documentation_url: Optional[str] = Field( - None, - description="URL of the connector's documentation page.", - examples=["https://docs.airbyte.com/integrations/sources/dremio"], - title="Documentation URL", - ) - advanced_auth: Optional[AuthFlow] = Field( - None, - description="Advanced specification for configuring the authentication flow.", - title="Advanced Auth", - ) - - -class CompositeErrorHandler(BaseModel): - type: Literal["CompositeErrorHandler"] - error_handlers: List[Union[CompositeErrorHandler, DefaultErrorHandler]] = Field( - ..., - description="List of error handlers to iterate on to determine how to handle a failed response.", - title="Error Handlers", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class DeclarativeSource(BaseModel): - class Config: - extra = Extra.forbid - - type: Literal["DeclarativeSource"] - check: CheckStream - streams: List[DeclarativeStream] - version: str = Field( - ..., - description="The version of the Airbyte CDK used to build and test the source.", - ) - schemas: Optional[Schemas] = None - definitions: Optional[Dict[str, Any]] = None - spec: Optional[Spec] = None - metadata: Optional[Dict[str, Any]] = Field( - None, - description="For internal Airbyte use only - DO NOT modify manually. Used by consumers of declarative manifests for storing related metadata.", - ) - description: Optional[str] = Field( - None, - description="A description of the connector. It will be presented on the Source documentation page.", - ) - - -class SelectiveAuthenticator(BaseModel): - class Config: - extra = Extra.allow - - type: Literal["SelectiveAuthenticator"] - authenticator_selection_path: List[str] = Field( - ..., - description="Path of the field in config with selected authenticator name", - examples=[["auth"], ["auth", "type"]], - title="Authenticator Selection Path", - ) - authenticators: Dict[ - str, - Union[ - ApiKeyAuthenticator, - BasicHttpAuthenticator, - BearerAuthenticator, - CustomAuthenticator, - OAuthAuthenticator, - JwtAuthenticator, - NoAuth, - SessionTokenAuthenticator, - LegacySessionTokenAuthenticator, - ], - ] = Field( - ..., - description="Authenticators to select from.", - examples=[ - { - "authenticators": { - "token": "#/definitions/ApiKeyAuthenticator", - "oauth": "#/definitions/OAuthAuthenticator", - "jwt": "#/definitions/JwtAuthenticator", - } - } - ], - title="Authenticators", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class DeclarativeStream(BaseModel): - class Config: - extra = Extra.allow - - type: Literal["DeclarativeStream"] - retriever: Union[CustomRetriever, SimpleRetriever] = Field( - ..., - description="Component used to coordinate how records are extracted across stream slices and request pages.", - title="Retriever", - ) - incremental_sync: Optional[Union[CustomIncrementalSync, DatetimeBasedCursor]] = Field( - None, - description="Component used to fetch data incrementally based on a time field in the data.", - title="Incremental Sync", - ) - name: Optional[str] = Field("", description="The stream name.", example=["Users"], title="Name") - primary_key: Optional[PrimaryKey] = Field("", description="The primary key of the stream.", title="Primary Key") - schema_loader: Optional[Union[InlineSchemaLoader, JsonFileSchemaLoader, CustomSchemaLoader]] = Field( - None, - description="Component used to retrieve the schema for the current stream.", - title="Schema Loader", - ) - transformations: Optional[List[Union[AddFields, CustomTransformation, RemoveFields]]] = Field( - None, - description="A list of transformations to be applied to each output record.", - title="Transformations", - ) - state_migrations: Optional[List[Union[LegacyToPerPartitionStateMigration, CustomStateMigration]]] = Field( - [], - description="Array of state migrations to be applied on the input state", - title="State Migrations", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class SessionTokenAuthenticator(BaseModel): - type: Literal["SessionTokenAuthenticator"] - login_requester: HttpRequester = Field( - ..., - description="Description of the request to perform to obtain a session token to perform data requests. The response body is expected to be a JSON object with a session token property.", - examples=[ - { - "type": "HttpRequester", - "url_base": "https://my_api.com", - "path": "/login", - "authenticator": { - "type": "BasicHttpAuthenticator", - "username": "{{ config.username }}", - "password": "{{ config.password }}", - }, - } - ], - title="Login Requester", - ) - session_token_path: List[str] = Field( - ..., - description="The path in the response body returned from the login requester to the session token.", - examples=[["access_token"], ["result", "token"]], - title="Session Token Path", - ) - expiration_duration: Optional[str] = Field( - None, - description="The duration in ISO 8601 duration notation after which the session token expires, starting from the time it was obtained. Omitting it will result in the session token being refreshed for every request.", - examples=["PT1H", "P1D"], - title="Expiration Duration", - ) - request_authentication: Union[SessionTokenRequestApiKeyAuthenticator, SessionTokenRequestBearerAuthenticator] = Field( - ..., - description="Authentication method to use for requests sent to the API, specifying how to inject the session token.", - title="Data Request Authentication", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class HttpRequester(BaseModel): - type: Literal["HttpRequester"] - url_base: str = Field( - ..., - description="Base URL of the API source. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.", - examples=[ - "https://connect.squareup.com/v2", - "{{ config['base_url'] or 'https://app.posthog.com'}}/api/", - ], - title="API Base URL", - ) - path: str = Field( - ..., - description="Path the specific API endpoint that this stream represents. Do not put sensitive information (e.g. API tokens) into this field - Use the Authentication component for this.", - examples=[ - "/products", - "/quotes/{{ stream_partition['id'] }}/quote_line_groups", - "/trades/{{ config['symbol_id'] }}/history", - ], - title="URL Path", - ) - authenticator: Optional[ - Union[ - ApiKeyAuthenticator, - BasicHttpAuthenticator, - BearerAuthenticator, - CustomAuthenticator, - OAuthAuthenticator, - JwtAuthenticator, - NoAuth, - SessionTokenAuthenticator, - LegacySessionTokenAuthenticator, - SelectiveAuthenticator, - ] - ] = Field( - None, - description="Authentication method to use for requests sent to the API.", - title="Authenticator", - ) - error_handler: Optional[Union[DefaultErrorHandler, CustomErrorHandler, CompositeErrorHandler]] = Field( - None, - description="Error handler component that defines how to handle errors.", - title="Error Handler", - ) - http_method: Optional[HttpMethod] = Field( - HttpMethod.GET, - description="The HTTP method used to fetch data from the source (can be GET or POST).", - examples=["GET", "POST"], - title="HTTP Method", - ) - request_body_data: Optional[Union[str, Dict[str, str]]] = Field( - None, - description="Specifies how to populate the body of the request with a non-JSON payload. Plain text will be sent as is, whereas objects will be converted to a urlencoded form.", - examples=[ - '[{"clause": {"type": "timestamp", "operator": 10, "parameters":\n [{"value": {{ stream_interval[\'start_time\'] | int * 1000 }} }]\n }, "orderBy": 1, "columnName": "Timestamp"}]/\n' - ], - title="Request Body Payload (Non-JSON)", - ) - request_body_json: Optional[Union[str, Dict[str, Any]]] = Field( - None, - description="Specifies how to populate the body of the request with a JSON payload. Can contain nested objects.", - examples=[ - {"sort_order": "ASC", "sort_field": "CREATED_AT"}, - {"key": "{{ config['value'] }}"}, - {"sort": {"field": "updated_at", "order": "ascending"}}, - ], - title="Request Body JSON Payload", - ) - request_headers: Optional[Union[str, Dict[str, str]]] = Field( - None, - description="Return any non-auth headers. Authentication headers will overwrite any overlapping headers returned from this method.", - examples=[{"Output-Format": "JSON"}, {"Version": "{{ config['version'] }}"}], - title="Request Headers", - ) - request_parameters: Optional[Union[str, Dict[str, str]]] = Field( - None, - description="Specifies the query parameters that should be set on an outgoing HTTP request given the inputs.", - examples=[ - {"unit": "day"}, - { - "query": 'last_event_time BETWEEN TIMESTAMP "{{ stream_interval.start_time }}" AND TIMESTAMP "{{ stream_interval.end_time }}"' - }, - {"searchIn": "{{ ','.join(config.get('search_in', [])) }}"}, - {"sort_by[asc]": "updated_at"}, - ], - title="Query Parameters", - ) - use_cache: Optional[bool] = Field( - False, - description="Enables stream requests caching. This field is automatically set by the CDK.", - title="Use Cache", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class ParentStreamConfig(BaseModel): - type: Literal["ParentStreamConfig"] - parent_key: str = Field( - ..., - description="The primary key of records from the parent stream that will be used during the retrieval of records for the current substream. This parent identifier field is typically a characteristic of the child records being extracted from the source API.", - examples=["id", "{{ config['parent_record_id'] }}"], - title="Parent Key", - ) - stream: DeclarativeStream = Field(..., description="Reference to the parent stream.", title="Parent Stream") - partition_field: str = Field( - ..., - description="While iterating over parent records during a sync, the parent_key value can be referenced by using this field.", - examples=["parent_id", "{{ config['parent_partition_field'] }}"], - title="Current Parent Key Value Identifier", - ) - request_option: Optional[RequestOption] = Field( - None, - description="A request option describing where the parent key value should be injected into and under what field name if applicable.", - title="Request Option", - ) - incremental_dependency: Optional[bool] = Field( - False, - description="Indicates whether the parent stream should be read incrementally based on updates in the child stream.", - title="Incremental Dependency", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class SimpleRetriever(BaseModel): - type: Literal["SimpleRetriever"] - record_selector: RecordSelector = Field( - ..., - description="Component that describes how to extract records from a HTTP response.", - ) - requester: Union[CustomRequester, HttpRequester] = Field( - ..., - description="Requester component that describes how to prepare HTTP requests to send to the source API.", - ) - paginator: Optional[Union[DefaultPaginator, NoPagination]] = Field( - None, - description="Paginator component that describes how to navigate through the API's pages.", - ) - ignore_stream_slicer_parameters_on_paginated_requests: Optional[bool] = Field( - False, - description="If true, the partition router and incremental request options will be ignored when paginating requests. Request options set directly on the requester will not be ignored.", - ) - partition_router: Optional[ - Union[ - CustomPartitionRouter, - ListPartitionRouter, - SubstreamPartitionRouter, - List[Union[CustomPartitionRouter, ListPartitionRouter, SubstreamPartitionRouter]], - ] - ] = Field( - [], - description="PartitionRouter component that describes how to partition the stream, enabling incremental syncs and checkpointing.", - title="Partition Router", - ) - decoder: Optional[Union[JsonDecoder, JsonlDecoder, IterableDecoder]] = Field( - None, - description="Component decoding the response so records can be extracted.", - title="Decoder", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -class SubstreamPartitionRouter(BaseModel): - type: Literal["SubstreamPartitionRouter"] - parent_stream_configs: List[ParentStreamConfig] = Field( - ..., - description="Specifies which parent streams are being iterated over and how parent records should be used to partition the child stream data set.", - title="Parent Stream Configs", - ) - parameters: Optional[Dict[str, Any]] = Field(None, alias="$parameters") - - -CompositeErrorHandler.update_forward_refs() -DeclarativeSource.update_forward_refs() -SelectiveAuthenticator.update_forward_refs() -DeclarativeStream.update_forward_refs() -SessionTokenAuthenticator.update_forward_refs() -SimpleRetriever.update_forward_refs() diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/manifest_component_transformer.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/manifest_component_transformer.py deleted file mode 100644 index e94ffaa1f430..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/manifest_component_transformer.py +++ /dev/null @@ -1,268 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import copy -import logging -import typing -from typing import Any, Dict, Mapping, Optional, Set, Type - -from pydantic import BaseModel - -from .declarative_component_schema import ( - ApiKeyAuthenticator, - BasicHttpAuthenticator, - BearerAuthenticator, - CompositeErrorHandler, - ConstantBackoffStrategy, - CursorPagination, - CustomAuthenticator, - CustomBackoffStrategy, - CustomErrorHandler, - CustomIncrementalSync, - CustomPaginationStrategy, - CustomPartitionRouter, - CustomRecordExtractor, - CustomRecordFilter, - CustomRequester, - CustomRetriever, - CustomSchemaLoader, - CustomStateMigration, - CustomTransformation, - DatetimeBasedCursor, - DeclarativeSource, - DeclarativeStream, - DefaultErrorHandler, - DefaultPaginator, - DpathExtractor, - ExponentialBackoffStrategy, - HttpRequester, - HttpResponseFilter, - JsonFileSchemaLoader, - JwtAuthenticator, - LegacySessionTokenAuthenticator, - ListPartitionRouter, - MinMaxDatetime, - OAuthAuthenticator, - OffsetIncrement, - PageIncrement, - ParentStreamConfig, - RecordFilter, - RecordSelector, - SelectiveAuthenticator, - SessionTokenAuthenticator, - SimpleRetriever, - SubstreamPartitionRouter, - WaitTimeFromHeader, - WaitUntilTimeFromHeader, -) - -PARAMETERS_STR = "$parameters" - -# Mapping of component type to the class that implements it. This is used to fetch the Pydantic model class for a component type -COMPONENT_TYPE_REGISTY: Dict[str, type] = { - "BasicHttpAuthenticator": BasicHttpAuthenticator, - "BearerAuthenticator": BearerAuthenticator, - "ConstantBackoffStrategy": ConstantBackoffStrategy, - "CustomAuthenticator": CustomAuthenticator, - "CustomBackoffStrategy": CustomBackoffStrategy, - "CustomErrorHandler": CustomErrorHandler, - "CustomIncrementalSync": CustomIncrementalSync, - "CustomPaginationStrategy": CustomPaginationStrategy, - "CustomRecordExtractor": CustomRecordExtractor, - "CustomRecordFilter": CustomRecordFilter, - "CustomRequester": CustomRequester, - "CustomRetriever": CustomRetriever, - "CustomPartitionRouter": CustomPartitionRouter, - "CustomSchemaLoader": CustomSchemaLoader, - "CustomStateMigration": CustomStateMigration, - "CustomTransformation": CustomTransformation, - "JwtAuthenticator": JwtAuthenticator, - "OAuthAuthenticator": OAuthAuthenticator, - "ExponentialBackoffStrategy": ExponentialBackoffStrategy, - "HttpResponseFilter": HttpResponseFilter, - "JsonFileSchemaLoader": JsonFileSchemaLoader, - "MinMaxDatetime": MinMaxDatetime, - "OffsetIncrement": OffsetIncrement, - "PageIncrement": PageIncrement, - "RecordFilter": RecordFilter, - "LegacySessionTokenAuthenticator": LegacySessionTokenAuthenticator, - "WaitTimeFromHeader": WaitTimeFromHeader, - "WaitUntilTimeFromHeader": WaitUntilTimeFromHeader, - "ApiKeyAuthenticator": ApiKeyAuthenticator, - "CursorPagination": CursorPagination, - "DatetimeBasedCursor": DatetimeBasedCursor, - "DefaultErrorHandler": DefaultErrorHandler, - "DefaultPaginator": DefaultPaginator, - "DpathExtractor": DpathExtractor, - "ListPartitionRouter": ListPartitionRouter, - "RecordSelector": RecordSelector, - "CompositeErrorHandler": CompositeErrorHandler, - "SelectiveAuthenticator": SelectiveAuthenticator, - "DeclarativeStream": DeclarativeStream, - "SessionTokenAuthenticator": SessionTokenAuthenticator, - "HttpRequester": HttpRequester, - "ParentStreamConfig": ParentStreamConfig, - "SimpleRetriever": SimpleRetriever, - "SubstreamPartitionRouter": SubstreamPartitionRouter, - "DeclarativeSource": DeclarativeSource, -} - -DEFAULT_MODEL_TYPES: Mapping[str, str] = { - # CompositeErrorHandler - "CompositeErrorHandler.error_handlers": "DefaultErrorHandler", - # CursorPagination - "CursorPagination.decoder": "JsonDecoder", - # DatetimeBasedCursor - "DatetimeBasedCursor.end_datetime": "MinMaxDatetime", - "DatetimeBasedCursor.end_time_option": "RequestOption", - "DatetimeBasedCursor.start_datetime": "MinMaxDatetime", - "DatetimeBasedCursor.start_time_option": "RequestOption", - # CustomIncrementalSync - "CustomIncrementalSync.end_datetime": "MinMaxDatetime", - "CustomIncrementalSync.end_time_option": "RequestOption", - "CustomIncrementalSync.start_datetime": "MinMaxDatetime", - "CustomIncrementalSync.start_time_option": "RequestOption", - # DeclarativeSource - "DeclarativeSource.check": "CheckStream", - "DeclarativeSource.spec": "Spec", - "DeclarativeSource.streams": "DeclarativeStream", - # DeclarativeStream - "DeclarativeStream.retriever": "SimpleRetriever", - "DeclarativeStream.schema_loader": "JsonFileSchemaLoader", - # DefaultErrorHandler - "DefaultErrorHandler.response_filters": "HttpResponseFilter", - # DefaultPaginator - "DefaultPaginator.decoder": "JsonDecoder", - "DefaultPaginator.page_size_option": "RequestOption", - # DpathExtractor - "DpathExtractor.decoder": "JsonDecoder", - # HttpRequester - "HttpRequester.error_handler": "DefaultErrorHandler", - # ListPartitionRouter - "ListPartitionRouter.request_option": "RequestOption", - # ParentStreamConfig - "ParentStreamConfig.request_option": "RequestOption", - "ParentStreamConfig.stream": "DeclarativeStream", - # RecordSelector - "RecordSelector.extractor": "DpathExtractor", - "RecordSelector.record_filter": "RecordFilter", - # SimpleRetriever - "SimpleRetriever.paginator": "NoPagination", - "SimpleRetriever.record_selector": "RecordSelector", - "SimpleRetriever.requester": "HttpRequester", - # SubstreamPartitionRouter - "SubstreamPartitionRouter.parent_stream_configs": "ParentStreamConfig", - # AddFields - "AddFields.fields": "AddedFieldDefinition", - # CustomPartitionRouter - "CustomPartitionRouter.parent_stream_configs": "ParentStreamConfig", -} - -# We retain a separate registry for custom components to automatically insert the type if it is missing. This is intended to -# be a short term fix because once we have migrated, then type and class_name should be requirements for all custom components. -CUSTOM_COMPONENTS_MAPPING: Mapping[str, str] = { - "CompositeErrorHandler.backoff_strategies": "CustomBackoffStrategy", - "DeclarativeStream.retriever": "CustomRetriever", - "DeclarativeStream.transformations": "CustomTransformation", - "DefaultErrorHandler.backoff_strategies": "CustomBackoffStrategy", - "DefaultPaginator.pagination_strategy": "CustomPaginationStrategy", - "HttpRequester.authenticator": "CustomAuthenticator", - "HttpRequester.error_handler": "CustomErrorHandler", - "RecordSelector.extractor": "CustomRecordExtractor", - "SimpleRetriever.partition_router": "CustomPartitionRouter", -} - -logger = logging.getLogger(__name__) - - -def get_model_fields(model_class: Optional[Type[BaseModel]]) -> Set[str]: - """Fetches field names from a Pydantic model class if available.""" - if model_class is not None: - return set(model_class.__fields__.keys()) - return set() - - -class ManifestComponentTransformer: - def propagate_types_and_parameters( - self, - parent_field_identifier: str, - declarative_component: Mapping[str, Any], - parent_parameters: Mapping[str, Any], - ) -> Mapping[str, Any]: - """ - Recursively transforms the specified declarative component and subcomponents to propagate parameters and insert the - default component type if it was not already present. The resulting transformed components are a deep copy of the input - components, not an in-place transformation. - :param declarative_component: The current component that is having type and parameters added - :param parent_field_identifier: The name of the field of the current component coming from the parent component - :param parent_parameters: The parameters set on parent components defined before the current component - :return: A deep copy of the transformed component with types and parameters persisted to it - """ - propagated_component = dict(copy.deepcopy(declarative_component)) - if "type" not in propagated_component: - # If the component has class_name we assume that this is a reference to a custom component. This is a slight change to - # existing behavior because we originally allowed for either class or type to be specified. After the pydantic migration, - # class_name will only be a valid field on custom components and this change reflects that. I checked, and we currently - # have no low-code connectors that use class_name except for custom components. - if "class_name" in propagated_component: - found_type = CUSTOM_COMPONENTS_MAPPING.get(parent_field_identifier) - else: - found_type = DEFAULT_MODEL_TYPES.get(parent_field_identifier) - if found_type: - propagated_component["type"] = found_type - - # When there is no resolved type, we're not processing a component (likely a regular object) and don't need to propagate parameters - # When the type refers to a json schema, we're not processing a component as well. This check is currently imperfect as there could - # be json_schema are not objects but we believe this is not likely in our case because: - # * records are Mapping so objects hence SchemaLoader root should be an object - # * connection_specification is a Mapping - if "type" not in propagated_component or self._is_json_schema_object(propagated_component): - return propagated_component - - component_type = propagated_component.get("type", "") - model_class = COMPONENT_TYPE_REGISTY.get(component_type) - # Grab the list of expected fields for the component type - valid_fields = get_model_fields(model_class) - - # Combines parameters defined at the current level with parameters from parent components. Parameters at the current - # level take precedence - current_parameters = dict(copy.deepcopy(parent_parameters)) - component_parameters = propagated_component.pop(PARAMETERS_STR, {}) - current_parameters = {**current_parameters, **component_parameters} - - # Parameters should be applied to the current component fields with the existing field taking precedence over parameters if - # both exist - for parameter_key, parameter_value in current_parameters.items(): - if parameter_key in valid_fields: - propagated_component[parameter_key] = propagated_component.get(parameter_key) or parameter_value - - for field_name, field_value in propagated_component.items(): - if isinstance(field_value, dict): - # We exclude propagating a parameter that matches the current field name because that would result in an infinite cycle - excluded_parameter = current_parameters.pop(field_name, None) - parent_type_field_identifier = f"{propagated_component.get('type')}.{field_name}" - propagated_component[field_name] = self.propagate_types_and_parameters( - parent_type_field_identifier, field_value, current_parameters - ) - if excluded_parameter: - current_parameters[field_name] = excluded_parameter - elif isinstance(field_value, typing.List): - # We exclude propagating a parameter that matches the current field name because that would result in an infinite cycle - excluded_parameter = current_parameters.pop(field_name, None) - for i, element in enumerate(field_value): - if isinstance(element, dict): - parent_type_field_identifier = f"{propagated_component.get('type')}.{field_name}" - field_value[i] = self.propagate_types_and_parameters(parent_type_field_identifier, element, current_parameters) - if excluded_parameter: - current_parameters[field_name] = excluded_parameter - - return propagated_component - - @staticmethod - def _is_json_schema_object(propagated_component: Mapping[str, Any]) -> bool: - component_type = propagated_component.get("type") - if isinstance(component_type, list): - # Handle nullable types, ie ["null", "object"] - return "object" in component_type - return component_type == "object" diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/manifest_resolver.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/manifest_resolver.py deleted file mode 100644 index a6dbebffd7d0..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/manifest_resolver.py +++ /dev/null @@ -1,204 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import re -from typing import Any, Mapping, Set, Tuple, Union - -REF_TAG = "$ref" - - -class ManifestReferenceResolver: - """ - An incoming manifest can contain references to values previously defined. - This parser will dereference these values to produce a complete ConnectionDefinition. - - References can be defined using a #/ string. - ``` - key: 1234 - reference: "#/key" - ``` - will produce the following definition: - ``` - key: 1234 - reference: 1234 - ``` - This also works with objects: - ``` - key_value_pairs: - k1: v1 - k2: v2 - same_key_value_pairs: "#/key_value_pairs" - ``` - will produce the following definition: - ``` - key_value_pairs: - k1: v1 - k2: v2 - same_key_value_pairs: - k1: v1 - k2: v2 - ``` - - The $ref keyword can be used to refer to an object and enhance it with addition key-value pairs - ``` - key_value_pairs: - k1: v1 - k2: v2 - same_key_value_pairs: - $ref: "#/key_value_pairs" - k3: v3 - ``` - will produce the following definition: - ``` - key_value_pairs: - k1: v1 - k2: v2 - same_key_value_pairs: - k1: v1 - k2: v2 - k3: v3 - ``` - - References can also point to nested values. - Nested references are ambiguous because one could define a key containing with `.` - in this example, we want to refer to the limit key in the dict object: - ``` - dict: - limit: 50 - limit_ref: "#/dict/limit" - ``` - will produce the following definition: - ``` - dict - limit: 50 - limit-ref: 50 - ``` - - whereas here we want to access the `nested/path` value. - ``` - nested: - path: "first one" - nested/path: "uh oh" - value: "#/nested/path - ``` - will produce the following definition: - ``` - nested: - path: "first one" - nested/path: "uh oh" - value: "uh oh" - ``` - - to resolve the ambiguity, we try looking for the reference key at the top level, and then traverse the structs downward - until we find a key with the given path, or until there is nothing to traverse. - """ - - def preprocess_manifest(self, manifest: Mapping[str, Any]) -> Mapping[str, Any]: - """ - :param manifest: incoming manifest that could have references to previously defined components - :return: - """ - return self._evaluate_node(manifest, manifest, set()) # type: ignore[no-any-return] - - def _evaluate_node(self, node: Any, manifest: Mapping[str, Any], visited: Set[Any]) -> Any: # noqa: ANN401 - if isinstance(node, dict): - evaluated_dict = {k: self._evaluate_node(v, manifest, visited) for k, v in node.items() if not self._is_ref_key(k)} - if REF_TAG in node: - # The node includes a $ref key, so we splat the referenced value(s) into the evaluated dict - evaluated_ref = self._evaluate_node(node[REF_TAG], manifest, visited) - if not isinstance(evaluated_ref, dict): - return evaluated_ref - else: - # The values defined on the component take precedence over the reference values - return evaluated_ref | evaluated_dict - else: - return evaluated_dict - elif isinstance(node, list): - return [self._evaluate_node(v, manifest, visited) for v in node] - elif self._is_ref(node): - if node in visited: - raise ValueError(node) - visited.add(node) - ret = self._evaluate_node(self._lookup_ref_value(node, manifest), manifest, visited) - visited.remove(node) - return ret - else: - return node - - def _lookup_ref_value(self, ref: str, manifest: Mapping[str, Any]) -> Any: # noqa: ANN401 - ref_match = re.match(r"#/(.*)", ref) - if not ref_match: - raise ValueError(f"Invalid reference format {ref}") - try: - path = ref_match.groups()[0] - return self._read_ref_value(path, manifest) - except (AttributeError, KeyError, IndexError): - raise ValueError(f"{path}, {ref}") - - @staticmethod - def _is_ref(node: Any) -> bool: # noqa: ANN401 - return isinstance(node, str) and node.startswith("#/") - - @staticmethod - def _is_ref_key(key: str) -> bool: - return bool(key == REF_TAG) - - @staticmethod - def _read_ref_value(ref: str, manifest_node: Mapping[str, Any]) -> Any: # noqa: ANN401 - """ - Read the value at the referenced location of the manifest. - - References are ambiguous because one could define a key containing `/` - In this example, we want to refer to the `limit` key in the `dict` object: - dict: - limit: 50 - limit_ref: "#/dict/limit" - - Whereas here we want to access the `nested/path` value. - nested: - path: "first one" - nested/path: "uh oh" - value: "#/nested/path" - - To resolve the ambiguity, we try looking for the reference key at the top level, and then traverse the structs downward - until we find a key with the given path, or until there is nothing to traverse. - - Consider the path foo/bar/baz. To resolve the ambiguity, we first try 'foo/bar/baz' in its entirety as a top-level key. If this - fails, we try 'foo' as the top-level key, and if this succeeds, pass 'bar/baz' on as the key to be tried at the next level. - """ - while ref: - try: - return manifest_node[ref] - except (KeyError, TypeError): - head, ref = _parse_path(ref) - manifest_node = manifest_node[head] # type: ignore # Couldn't figure out how to fix this since manifest_node can get reassigned into other types like lists - return manifest_node - - -def _parse_path(ref: str) -> Tuple[Union[str, int], str]: - """ - Return the next path component, together with the rest of the path. - - A path component may be a string key, or an int index. - - >>> _parse_path("foo/bar") - "foo", "bar" - >>> _parse_path("foo/7/8/bar") - "foo", "7/8/bar" - >>> _parse_path("7/8/bar") - 7, "8/bar" - >>> _parse_path("8/bar") - 8, "bar" - >>> _parse_path("8foo/bar") - "8foo", "bar" - """ - match = re.match(r"([^/]*)/?(.*)", ref) - if match: - first, rest = match.groups() - try: - return int(first), rest - except ValueError: - return first, rest - else: - raise ValueError(f"Invalid path {ref} specified") diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/pipeline.py deleted file mode 100644 index 89e167de379e..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/pipeline.py +++ /dev/null @@ -1,324 +0,0 @@ -# -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -# - -import json -import shutil -from pathlib import Path -from typing import Any - -import git # type: ignore -from anyio import Semaphore # type: ignore -from connector_ops.utils import ConnectorLanguage # type: ignore - -from pipelines.airbyte_ci.connectors.consts import CONNECTOR_TEST_STEP_ID -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.airbyte_ci.connectors.migrate_to_manifest_only.manifest_component_transformer import ManifestComponentTransformer -from pipelines.airbyte_ci.connectors.migrate_to_manifest_only.manifest_resolver import ManifestReferenceResolver -from pipelines.airbyte_ci.connectors.migrate_to_manifest_only.utils import ( - get_latest_base_image, - readme_for_connector, - remove_parameters_from_manifest, -) -from pipelines.airbyte_ci.connectors.reports import Report -from pipelines.helpers.connectors.command import run_connector_steps -from pipelines.helpers.connectors.yaml import read_yaml, write_yaml -from pipelines.helpers.execution.run_steps import STEP_TREE, StepToRun -from pipelines.models.steps import Step, StepResult, StepStatus - -## GLOBAL VARIABLES ## - -# spec.yaml and spec.json will be removed as part of the conversion. But if they are present, it's fine to convert still. -MANIFEST_ONLY_COMPATIBLE_FILES = [ - "manifest.yaml", - "components.py", - "run.py", - "__init__.py", - "source.py", - "spec.json", - "spec.yaml", - "__pycache__", -] -MANIFEST_ONLY_FILES_TO_KEEP = [ - "manifest.yaml", - "components.py", - "metadata.yaml", - "icon.svg", - "unit_tests", - "integration_tests", - "acceptance-test-config.yml", - "secrets", -] - - -## STEPS ## - - -class CheckIsManifestMigrationCandidate(Step): - """ - Pipeline step to check if the connector is a candidate for migration to manifest-only. - """ - - context: ConnectorContext - title: str = "Validate Manifest Migration Candidate" - airbyte_repo: git.Repo = git.Repo(search_parent_directories=True) - - async def _run(self) -> StepResult: - connector = self.context.connector - invalid_files: list = [] - - ## 1. Confirm the connector is low-code and not already manifest-only - if connector.language != ConnectorLanguage.LOW_CODE: - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stderr="The connector is not a low-code connector.", - ) - - if connector.language == ConnectorLanguage.MANIFEST_ONLY: - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stderr="The connector is already in manifest-only format.", - ) - - ## 2. Detect invalid python files in the connector's source directory - for file in connector.python_source_dir_path.iterdir(): - if file.name not in MANIFEST_ONLY_COMPATIBLE_FILES: - invalid_files.append(file.name) - if invalid_files: - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stdout=f"The connector has unrecognized source files: {', '.join(invalid_files)}", - ) - - ## 3. Detect connector class name to make sure it's inherited from source-declarative-manifest - # and does not override the `streams` method - connector_source_py = (connector.python_source_dir_path / "source.py").read_text() - - if "YamlDeclarativeSource" not in connector_source_py: - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stdout="The connector does not use the YamlDeclarativeSource class.", - ) - - if "def streams" in connector_source_py: - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stdout="The connector overrides the streams method.", - ) - - # All checks passed, the connector is a valid candidate for migration - return StepResult(step=self, status=StepStatus.SUCCESS, stdout=f"{connector.technical_name} is a valid candidate for migration.") - - -class StripConnector(Step): - """ - Pipeline step to strip a low-code connector to manifest-only files. - """ - - context: ConnectorContext - title = "Strip Out Unnecessary Files" - - def _delete_directory_item(self, file: Path) -> None: - """ - Deletes the passed file or folder. - """ - self.logger.info(f"Deleting {file.name}") - try: - if file.is_dir(): - shutil.rmtree(file) - else: - file.unlink() - except Exception as e: - raise ValueError(f"Failed to delete {file.name}: {e}") - - def _check_if_non_inline_spec(self, path: Path) -> Path | None: - """ - Checks if a non-inline spec file exists and return its path. - """ - spec_file_yaml = path / "spec.yaml" - spec_file_json = path / "spec.json" - - if spec_file_yaml.exists(): - return spec_file_yaml - elif spec_file_json.exists(): - return spec_file_json - return None - - def _read_spec_from_file(self, spec_file: Path) -> dict: - """ - Grabs the relevant data from a non-inline spec, to be added to the manifest. - """ - try: - if spec_file.suffix == ".json": - with open(spec_file, "r") as file: - spec = json.load(file) - else: - spec = read_yaml(spec_file) - - documentation_url = spec.get("documentationUrl") or spec.get("documentation_url") - connection_specification = spec.get("connection_specification") or spec.get("connectionSpecification") - advanced_auth = spec.get("advanced_auth") - return { - "documentation_url": documentation_url, - "connection_specification": connection_specification, - "advanced_auth": advanced_auth, - } - - except Exception as e: - raise ValueError(f"Failed to read data in spec file: {e}") - - async def _run(self) -> StepResult: - connector = self.context.connector - - ## 1a. Move manifest.yaml to the root level of the directory - self.logger.info("Moving manifest to the root level of the directory") - root_manifest_path = connector.code_directory / "manifest.yaml" - connector.manifest_path.rename(root_manifest_path) - - ## 1b. Move components.py to the root level of the directory if it exists - components_path = connector.python_source_dir_path / "components.py" - if components_path.exists(): - self.logger.info("Custom components file found. Moving to the root level of the directory") - root_components_path = connector.manifest_only_components_path - components_path.rename(root_components_path) - - ## 2. Update the version in manifest.yaml - try: - manifest = read_yaml(root_manifest_path) - manifest["version"] = "5.15.0" - manifest["type"] = "DeclarativeSource" - - # Resolve $parameters and types with CDK magic - resolved_manifest = ManifestReferenceResolver().preprocess_manifest(manifest) - propagated_manifest = ManifestComponentTransformer().propagate_types_and_parameters("", resolved_manifest, {}) - cleaned_manifest = remove_parameters_from_manifest(propagated_manifest) - - write_yaml(cleaned_manifest, root_manifest_path) - except Exception as e: - return StepResult(step=self, status=StepStatus.FAILURE, stdout=f"Failed to update version in manifest.yaml: {e}") - - ## 3. Check for non-inline spec files and add the data to manifest.yaml - spec_file = self._check_if_non_inline_spec(connector.python_source_dir_path) - if spec_file: - self.logger.info("Non-inline spec file found. Migrating spec to manifest") - try: - spec_data = self._read_spec_from_file(spec_file) - manifest = read_yaml(root_manifest_path) - - # Confirm the connector does not have both inline and non-inline specs - if "spec" in manifest: - return StepResult(step=self, status=StepStatus.FAILURE, stdout="Connector has both inline and non-inline specs.") - - manifest["spec"] = { - "type": "Spec", - "documentation_url": spec_data.get("documentation_url"), - "connection_specification": spec_data.get("connection_specification"), - "advanced_auth": spec_data.get("advanced_auth"), - } - write_yaml(manifest, root_manifest_path) - except Exception as e: - return StepResult(step=self, status=StepStatus.FAILURE, stdout=f"Failed to add spec data to manifest.yaml: {e}") - - ## 4. Delete all non-essential files - try: - for item in connector.code_directory.iterdir(): - if item.name in MANIFEST_ONLY_FILES_TO_KEEP: - continue # Preserve the allowed files - else: - self._delete_directory_item(item) - except Exception as e: - return StepResult(step=self, status=StepStatus.FAILURE, stdout=f"Failed to delete files: {e}") - - return StepResult(step=self, status=StepStatus.SUCCESS, stdout="The connector has been successfully stripped.") - - -class UpdateManifestOnlyFiles(Step): - """ - Pipeline step to update connector's metadata, acceptance-test-config and readme to manifest-only. - """ - - context: ConnectorContext - title = "Update Connector Metadata" - - async def _run(self) -> StepResult: - connector = self.context.connector - - ## 1. Update the acceptance test config to point to the right spec path - try: - acceptance_test_config_data = read_yaml(connector.acceptance_test_config_path) - # Handle legacy acceptance-test-config: - if "acceptance_tests" in acceptance_test_config_data: - acceptance_test_config_data["acceptance_tests"]["spec"]["tests"][0]["spec_path"] = "manifest.yaml" - else: - acceptance_test_config_data["tests"]["spec"][0]["spec_path"] = "manifest.yaml" - write_yaml(acceptance_test_config_data, connector.acceptance_test_config_path) - except Exception as e: - return StepResult(step=self, status=StepStatus.FAILURE, stdout=f"Failed to update acceptance-test-config.yml: {e}") - - ## 2. Update the connector's metadata - self.logger.info("Updating metadata file") - try: - metadata = read_yaml(connector.metadata_file_path) - - # Remove any existing language tags and append the manifest-only tag - tags = metadata.get("data", {}).get("tags", []) - for tag in tags: - if "language:" in tag: - tags.remove(tag) - tags.append("language:manifest-only") - - pypi_package = metadata.get("data", {}).get("remoteRegistries", {}).get("pypi") - if pypi_package: - pypi_package["enabled"] = False - - # Update the base image - latest_base_image = get_latest_base_image("airbyte/source-declarative-manifest") - connector_base_image = metadata.get("data", {}).get("connectorBuildOptions") - connector_base_image["baseImage"] = latest_base_image - - # Write the changes to metadata.yaml - write_yaml(metadata, connector.metadata_file_path) - except Exception as e: - return StepResult(step=self, status=StepStatus.FAILURE, stdout=f"Failed to update metadata.yaml: {e}") - - ## 3. Update the connector's README - self.logger.info("Updating README file") - readme = readme_for_connector(connector.technical_name) - - with open(connector.code_directory / "README.md", "w") as file: - file.write(readme) - - return StepResult(step=self, status=StepStatus.SUCCESS, stdout="The connector has been successfully migrated to manifest-only.") - - -## MAIN FUNCTION ## -async def run_connectors_manifest_only_pipeline(context: ConnectorContext, semaphore: "Semaphore", *args: Any) -> Report: - steps_to_run: STEP_TREE = [] - steps_to_run.append([StepToRun(id=CONNECTOR_TEST_STEP_ID.MANIFEST_ONLY_CHECK, step=CheckIsManifestMigrationCandidate(context))]) - - steps_to_run.append( - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.MANIFEST_ONLY_STRIP, - step=StripConnector(context), - depends_on=[CONNECTOR_TEST_STEP_ID.MANIFEST_ONLY_CHECK], - ) - ] - ) - - steps_to_run.append( - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.MANIFEST_ONLY_UPDATE, - step=UpdateManifestOnlyFiles(context), - depends_on=[CONNECTOR_TEST_STEP_ID.MANIFEST_ONLY_STRIP], - ) - ] - ) - - return await run_connector_steps(context, semaphore, steps_to_run) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/templates/README.md.j2 b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/templates/README.md.j2 deleted file mode 100644 index 6c86747bc7ad..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/templates/README.md.j2 +++ /dev/null @@ -1,65 +0,0 @@ -# {{ source_name.capitalize().replace("-", " ") }} source connector - -This directory contains the manifest-only connector for `source-{{ source_name }}`. -This _manifest-only_ connector is not a Python package on its own, as it runs inside of the base `source-declarative-manifest` image. - -For information about how to configure and use this connector within Airbyte, see [the connector's full documentation](https://docs.airbyte.com/integrations/sources/{{source_name}}). - -## Local development - -We recommend using the Connector Builder to edit this connector. -Using either Airbyte Cloud or your local Airbyte OSS instance, navigate to the **Builder** tab and select **Import a YAML**. -Then select the connector's `manifest.yaml` file to load the connector into the Builder. You're now ready to make changes to the connector! - -If you prefer to develop locally, you can follow the instructions below. - -### Building the docker image - -You can build any manifest-only connector with `airbyte-ci`: - -1. Install [`airbyte-ci`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/README.md) -2. Run the following command to build the docker image: - -```bash -airbyte-ci connectors --name=source-{{source_name}} build -``` - -An image will be available on your host with the tag `airbyte/source-{{source_name}}:dev`. - -### Creating credentials - -**If you are a community contributor**, follow the instructions in the [documentation](https://docs.airbyte.com/integrations/sources/{{source_name}}) -to generate the necessary credentials. Then create a file `secrets/config.json` conforming to the `spec` object in the connector's `manifest.yaml` file. -Note that any directory named `secrets` is gitignored across the entire Airbyte repo, so there is no danger of accidentally checking in sensitive information. - -### Running as a docker container - -Then run any of the standard source connector commands: - -```bash -docker run --rm airbyte/source-{{source_name}}:dev spec -docker run --rm -v $(pwd)/secrets:/secrets airbyte/source-{{source_name}}:dev check --config /secrets/config.json -docker run --rm -v $(pwd)/secrets:/secrets airbyte/source-{{source_name}}:dev discover --config /secrets/config.json -docker run --rm -v $(pwd)/secrets:/secrets -v $(pwd)/integration_tests:/integration_tests airbyte/source-{{source_name}}:dev read --config /secrets/config.json --catalog /integration_tests/configured_catalog.json -``` - -### Running the CI test suite - -You can run our full test suite locally using [`airbyte-ci`](https://github.com/airbytehq/airbyte/blob/master/airbyte-ci/connectors/pipelines/README.md): - -```bash -airbyte-ci connectors --name=source-{{source_name}} test -``` - -## Publishing a new version of the connector - -If you want to contribute changes to `source-{{source_name}}`, here's how you can do that: -1. Make your changes locally, or load the connector's manifest into Connector Builder and make changes there. -2. Make sure your changes are passing our test suite with `airbyte-ci connectors --name=source-{{source_name}} test` -3. Bump the connector version (please follow [semantic versioning for connectors](https://docs.airbyte.com/contributing-to-airbyte/resources/pull-requests-handbook/#semantic-versioning-for-connectors)): - - bump the `dockerImageTag` value in in `metadata.yaml` -4. Make sure the connector documentation and its changelog is up to date (`docs/integrations/sources/{{ source_name}}.md`). -5. Create a Pull Request: use [our PR naming conventions](https://docs.airbyte.com/contributing-to-airbyte/resources/pull-requests-handbook/#pull-request-title-convention). -6. Pat yourself on the back for being an awesome contributor. -7. Someone from Airbyte will take a look at your PR and iterate with you to merge it into master. -8. Once your PR is merged, the new version of the connector will be automatically published to Docker Hub and our connector registry. diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/utils.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/utils.py deleted file mode 100644 index 2336de957705..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/migrate_to_manifest_only/utils.py +++ /dev/null @@ -1,88 +0,0 @@ -# -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -# - -import subprocess -from pathlib import Path -from typing import Any, List, Mapping - -import jinja2 -import requests - - -def readme_for_connector(name: str) -> str: - """ - Generate a manifest-only README.md file for a connector using a Jinja2 template. - """ - dir_path = Path(__file__).parent / "templates" - env = jinja2.Environment(loader=jinja2.FileSystemLoader(searchpath=str(dir_path))) - template = env.get_template("README.md.j2") - readme_name = name.replace("source-", "") - rendered = template.render(source_name=readme_name) - return rendered - - -def get_latest_base_image(image_name: str) -> str: - """ - Fetch the latest base image from Docker Hub for a given image name. - """ - base_url = "https://hub.docker.com/v2/repositories/" - - tags_url = f"{base_url}{image_name}/tags/?page_size=10&ordering=last_updated" - response = requests.get(tags_url) - if response.status_code != 200: - raise requests.ConnectionError(f"Error fetching tags: {response.status_code}") - - tags_data = response.json() - if not tags_data["results"]: - raise ValueError("No tags found for the image") - - # iterate through the tags to find the latest one that doesn't contain "dev" or "latest" - for tag in tags_data["results"]: - if "dev" not in tag["name"] and "latest" not in tag["name"]: - latest_tag = tag["name"] - break - - if not latest_tag: - raise ValueError("No valid tags found for the image") - - manifest_url = f"{base_url}{image_name}/tags/{latest_tag}" - response = requests.get(manifest_url) - if response.status_code != 200: - raise requests.ConnectionError(f"Error fetching manifest: {response.status_code}") - - manifest_data = response.json() - digest = manifest_data.get("digest") - - if not digest: - raise ValueError("No digest found for the image") - - full_reference = f"docker.io/{image_name}:{latest_tag}@{digest}" - return full_reference - - -def revert_connector_directory(directory: Path) -> None: - """ - Revert changes to a connector directory to the state at the last commit. - Used as a cleanup step in the manifest-only pipeline. - """ - try: - # Restore the directory to its state at the last commit - subprocess.run(["git", "restore", directory], check=True) - # Remove untracked files and directories - subprocess.run(["git", "clean", "-fd", directory], check=True) - except subprocess.CalledProcessError as e: - # Handle errors in the subprocess calls - print(f"An error occurred while reverting changes: {str(e)}") - - -def remove_parameters_from_manifest(d: dict | List | Mapping[str, Any]) -> dict | List: - """ - Takes a dictionary (or a list) of keys and removes all instances of the key "$parameters" from it. - """ - if isinstance(d, dict) or isinstance(d, Mapping): - return {k: remove_parameters_from_manifest(v) for k, v in d.items() if k != "$parameters"} - elif isinstance(d, list): - return [remove_parameters_from_manifest(item) for item in d] - else: - return d diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pipeline.py deleted file mode 100644 index 2ca0f8c55b08..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pipeline.py +++ /dev/null @@ -1,126 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""This module groups the functions to run full pipelines for connector testing.""" - -from __future__ import annotations - -import sys -from pathlib import Path -from typing import TYPE_CHECKING, Any, Callable, List, Optional - -import anyio -import dagger -from connector_ops.utils import ConnectorLanguage # type: ignore -from dagger import Config - -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.airbyte_ci.connectors.publish.context import PublishConnectorContext -from pipelines.airbyte_ci.connectors.test.context import ConnectorTestContext -from pipelines.airbyte_ci.steps.no_op import NoOpStep -from pipelines.consts import ContextState -from pipelines.dagger.actions.system import docker -from pipelines.helpers.utils import create_and_open_file -from pipelines.models.reports import Report -from pipelines.models.steps import StepResult, StepStatus - -if TYPE_CHECKING: - from pipelines.models.contexts.pipeline_context import PipelineContext - -GITHUB_GLOBAL_CONTEXT = "[POC please ignore] Connectors CI" -GITHUB_GLOBAL_DESCRIPTION = "Running connectors tests" - -CONNECTOR_LANGUAGE_TO_FORCED_CONCURRENCY_MAPPING = { - # We run the Java connectors tests sequentially because we currently have memory issues when Java integration tests are run in parallel. - # See https://github.com/airbytehq/airbyte/issues/27168 - ConnectorLanguage.JAVA: anyio.Semaphore(1), -} - - -async def context_to_step_result(context: PipelineContext) -> StepResult: - if context.state == ContextState.SUCCESSFUL: - return await NoOpStep(context, StepStatus.SUCCESS).run() - - if context.state == ContextState.FAILURE: - return await NoOpStep(context, StepStatus.FAILURE).run() - - if context.state == ContextState.ERROR: - return await NoOpStep(context, StepStatus.FAILURE).run() - - raise ValueError(f"Could not convert context state: {context.state} to step status") - - -# HACK: This is to avoid wrapping the whole pipeline in a dagger pipeline to avoid instability just prior to launch -# TODO (ben): Refactor run_connectors_pipelines to wrap the whole pipeline in a dagger pipeline once Steps are refactored -async def run_report_complete_pipeline( - dagger_client: dagger.Client, - contexts: List[ConnectorContext] | List[PublishConnectorContext] | List[PipelineContext] | List[ConnectorTestContext], -) -> None: - """Create and Save a report representing the run of the encompassing pipeline. - - This is to denote when the pipeline is complete, useful for long running pipelines like nightlies. - """ - - if not contexts: - return - - # Repurpose the first context to be the pipeline upload context to preserve timestamps - first_connector_context = contexts[0] - - pipeline_name = f"Report upload {first_connector_context.report_output_prefix}" - first_connector_context.pipeline_name = pipeline_name - - # Transform contexts into a list of steps - steps_results = [await context_to_step_result(context) for context in contexts] - - report = Report( - name=pipeline_name, - pipeline_context=first_connector_context, - steps_results=steps_results, - filename="complete", - ) - - await report.save() - - -async def run_connectors_pipelines( - contexts: List[ConnectorContext] | List[PublishConnectorContext] | List[ConnectorTestContext], - connector_pipeline: Callable, - pipeline_name: str, - concurrency: int, - dagger_logs_path: Optional[Path], - execute_timeout: Optional[int], - *args: Any, -) -> List[ConnectorContext] | List[PublishConnectorContext] | List[ConnectorTestContext]: - """Run a connector pipeline for all the connector contexts.""" - - default_connectors_semaphore = anyio.Semaphore(concurrency) - dagger_logs_output = sys.stderr if not dagger_logs_path else create_and_open_file(dagger_logs_path) - async with dagger.Connection(Config(log_output=dagger_logs_output, execute_timeout=execute_timeout)) as dagger_client: - docker_hub_username = contexts[0].docker_hub_username - docker_hub_password = contexts[0].docker_hub_password - - if docker_hub_username and docker_hub_password: - dockerd_service = docker.with_global_dockerd_service(dagger_client, docker_hub_username, docker_hub_password) - else: - dockerd_service = docker.with_global_dockerd_service(dagger_client) - - await dockerd_service.start() - - async with anyio.create_task_group() as tg_connectors: - for context in contexts: - context.dagger_client = dagger_client - context.dockerd_service = dockerd_service - tg_connectors.start_soon( - connector_pipeline, - context, - CONNECTOR_LANGUAGE_TO_FORCED_CONCURRENCY_MAPPING.get(context.connector.language, default_connectors_semaphore), - *args, - ) - - # When the connectors pipelines are done, we can stop the dockerd service - await dockerd_service.stop() - await run_report_complete_pipeline(dagger_client, contexts) - - return contexts diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/commands.py deleted file mode 100644 index 67df171d49b3..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/commands.py +++ /dev/null @@ -1,212 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from typing import Callable, Dict, Iterable, List - -import asyncclick as click - -from pipelines import main_logger -from pipelines.airbyte_ci.connectors.pipeline import run_connectors_pipelines -from pipelines.airbyte_ci.connectors.publish.context import PublishConnectorContext, RolloutMode -from pipelines.airbyte_ci.connectors.publish.pipeline import ( - reorder_contexts, - run_connector_promote_pipeline, - run_connector_publish_pipeline, - run_connector_rollback_pipeline, -) -from pipelines.cli.click_decorators import click_ci_requirements_option -from pipelines.cli.confirm_prompt import confirm -from pipelines.cli.dagger_pipeline_command import DaggerPipelineCommand -from pipelines.cli.secrets import wrap_gcp_credentials_in_secret, wrap_in_secret -from pipelines.consts import DEFAULT_PYTHON_PACKAGE_REGISTRY_CHECK_URL, DEFAULT_PYTHON_PACKAGE_REGISTRY_URL, ContextState -from pipelines.helpers.connectors.modifed import ConnectorWithModifiedFiles -from pipelines.helpers.utils import fail_if_missing_docker_hub_creds -from pipelines.models.secrets import Secret - -ROLLOUT_MODE_TO_PIPELINE_FUNCTION: Dict[RolloutMode, Callable] = { - RolloutMode.PUBLISH: run_connector_publish_pipeline, - RolloutMode.PROMOTE: run_connector_promote_pipeline, - RolloutMode.ROLLBACK: run_connector_rollback_pipeline, -} - - -# Third-party connectors can't be published with this pipeline, skip them. -# This is not the same as partner connectors. Partner connectors use our tech stack and can -# be published just fine. Third-party connectors are in their own subdirectory. -def filter_out_third_party_connectors( - selected_connectors_with_modified_files: Iterable[ConnectorWithModifiedFiles], -) -> List[ConnectorWithModifiedFiles]: - """ - Return the list of connectors filtering out the connectors stored in connectors/third-party directory. - """ - filtered_connectors = [] - for connector in selected_connectors_with_modified_files: - if connector.is_third_party: - main_logger.info(f"Skipping third party connector {connector.technical_name} from the list of connectors") - else: - filtered_connectors.append(connector) - return filtered_connectors - - -@click.command(cls=DaggerPipelineCommand, help="Publish all images for the selected connectors.") -@click_ci_requirements_option() -@click.option("--pre-release/--main-release", help="Use this flag if you want to publish pre-release images.", default=True, type=bool) -@click.option( - "--spec-cache-gcs-credentials", - help="The service account key to upload files to the GCS bucket hosting spec cache.", - type=click.STRING, - required=True, - envvar="SPEC_CACHE_GCS_CREDENTIALS", - callback=wrap_gcp_credentials_in_secret, -) -@click.option( - "--spec-cache-bucket-name", - help="The name of the GCS bucket where specs will be cached.", - type=click.STRING, - required=True, - envvar="SPEC_CACHE_BUCKET_NAME", -) -@click.option( - "--metadata-service-gcs-credentials", - help="The service account key to upload files to the GCS bucket hosting the metadata files.", - type=click.STRING, - required=True, - envvar="METADATA_SERVICE_GCS_CREDENTIALS", - callback=wrap_gcp_credentials_in_secret, -) -@click.option( - "--metadata-service-bucket-name", - help="The name of the GCS bucket where metadata files will be uploaded.", - type=click.STRING, - required=True, - envvar="METADATA_SERVICE_BUCKET_NAME", -) -@click.option( - "--slack-webhook", - help="The Slack webhook URL to send notifications to.", - type=click.STRING, - envvar="SLACK_WEBHOOK", -) -@click.option( - "--python-registry-token", - help="Access token for python registry", - type=click.STRING, - envvar="PYTHON_REGISTRY_TOKEN", - callback=wrap_in_secret, -) -@click.option( - "--python-registry-url", - help="Which python registry url to publish to. If not set, the default pypi is used. For test pypi, use https://test.pypi.org/legacy/", - type=click.STRING, - default=DEFAULT_PYTHON_PACKAGE_REGISTRY_URL, - envvar="PYTHON_REGISTRY_URL", -) -@click.option( - "--python-registry-check-url", - help="Which url to check whether a certain version is published already. If not set, the default pypi is used. For test pypi, use https://test.pypi.org/pypi/", - type=click.STRING, - default=DEFAULT_PYTHON_PACKAGE_REGISTRY_CHECK_URL, - envvar="PYTHON_REGISTRY_CHECK_URL", -) -@click.option( - "--promote-release-candidate", - help="Promote a release candidate to a main release.", - type=click.BOOL, - default=False, - is_flag=True, -) -@click.option( - "--rollback-release-candidate", - help="Rollback a release candidate to a previous version.", - type=click.BOOL, - default=False, - is_flag=True, -) -@click.pass_context -async def publish( - ctx: click.Context, - pre_release: bool, - spec_cache_gcs_credentials: Secret, - spec_cache_bucket_name: str, - metadata_service_bucket_name: str, - metadata_service_gcs_credentials: Secret, - slack_webhook: str, - python_registry_token: Secret, - python_registry_url: str, - python_registry_check_url: str, - promote_release_candidate: bool, - rollback_release_candidate: bool, -) -> bool: - if promote_release_candidate and rollback_release_candidate: - raise click.UsageError("You can't promote and rollback a release candidate at the same time.") - elif promote_release_candidate: - rollout_mode = RolloutMode.PROMOTE - elif rollback_release_candidate: - rollout_mode = RolloutMode.ROLLBACK - else: - rollout_mode = RolloutMode.PUBLISH - - ctx.obj["selected_connectors_with_modified_files"] = filter_out_third_party_connectors( - ctx.obj["selected_connectors_with_modified_files"] - ) - if not ctx.obj["selected_connectors_with_modified_files"]: - return True - - if ctx.obj["is_local"]: - confirm( - "Publishing from a local environment is not recommended and requires to be logged in Airbyte's DockerHub registry, do you want to continue?", - abort=True, - ) - - fail_if_missing_docker_hub_creds(ctx) - - publish_connector_contexts = reorder_contexts( - [ - PublishConnectorContext( - connector=connector, - pre_release=pre_release, - spec_cache_gcs_credentials=spec_cache_gcs_credentials, - spec_cache_bucket_name=spec_cache_bucket_name, - metadata_service_gcs_credentials=metadata_service_gcs_credentials, - metadata_bucket_name=metadata_service_bucket_name, - docker_hub_username=Secret("docker_hub_username", ctx.obj["secret_stores"]["in_memory"]), - docker_hub_password=Secret("docker_hub_password", ctx.obj["secret_stores"]["in_memory"]), - slack_webhook=slack_webhook, - ci_report_bucket=ctx.obj["ci_report_bucket_name"], - report_output_prefix=ctx.obj["report_output_prefix"], - is_local=ctx.obj["is_local"], - git_branch=ctx.obj["git_branch"], - git_revision=ctx.obj["git_revision"], - diffed_branch=ctx.obj["diffed_branch"], - git_repo_url=ctx.obj["git_repo_url"], - gha_workflow_run_url=ctx.obj.get("gha_workflow_run_url"), - dagger_logs_url=ctx.obj.get("dagger_logs_url"), - pipeline_start_timestamp=ctx.obj.get("pipeline_start_timestamp"), - ci_context=ctx.obj.get("ci_context"), - ci_gcp_credentials=ctx.obj["ci_gcp_credentials"], - pull_request=ctx.obj.get("pull_request"), - s3_build_cache_access_key_id=ctx.obj.get("s3_build_cache_access_key_id"), - s3_build_cache_secret_key=ctx.obj.get("s3_build_cache_secret_key"), - use_local_cdk=ctx.obj.get("use_local_cdk"), - use_cdk_ref=ctx.obj.get("use_cdk_ref"), - python_registry_token=python_registry_token, - python_registry_url=python_registry_url, - python_registry_check_url=python_registry_check_url, - rollout_mode=rollout_mode, - ci_github_access_token=ctx.obj.get("ci_github_access_token"), - ) - for connector in ctx.obj["selected_connectors_with_modified_files"] - ] - ) - main_logger.warn("Concurrency is forced to 1. For stability reasons we disable parallel publish pipelines.") - ctx.obj["concurrency"] = 1 - - ran_publish_connector_contexts = await run_connectors_pipelines( - publish_connector_contexts, - ROLLOUT_MODE_TO_PIPELINE_FUNCTION[rollout_mode], - f"{rollout_mode.value} connectors", - ctx.obj["concurrency"], - ctx.obj["dagger_logs_path"], - ctx.obj["execute_timeout"], - ) - return all(context.state is ContextState.SUCCESSFUL for context in ran_publish_connector_contexts) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/context.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/context.py deleted file mode 100644 index 8eb1dc271897..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/context.py +++ /dev/null @@ -1,164 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""Module declaring context related classes.""" - -from enum import Enum -from typing import List, Optional - -import asyncclick as click -from github import PullRequest - -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.consts import PUBLISH_FAILURE_SLACK_CHANNEL, PUBLISH_UPDATES_SLACK_CHANNEL, ContextState -from pipelines.helpers.connectors.modifed import ConnectorWithModifiedFiles -from pipelines.helpers.github import AIRBYTE_GITHUB_REPO_URL_PREFIX -from pipelines.helpers.utils import format_duration -from pipelines.models.secrets import Secret - - -class RolloutMode(Enum): - ROLLBACK = "Rollback" - PUBLISH = "Publish" - PROMOTE = "Promote" - - -class PublishConnectorContext(ConnectorContext): - def __init__( - self, - connector: ConnectorWithModifiedFiles, - pre_release: bool, - spec_cache_gcs_credentials: Secret, - spec_cache_bucket_name: str, - metadata_service_gcs_credentials: Secret, - metadata_bucket_name: str, - docker_hub_username: Secret, - docker_hub_password: Secret, - ci_gcp_credentials: Secret, - slack_webhook: str, - ci_report_bucket: str, - report_output_prefix: str, - is_local: bool, - git_branch: str, - git_revision: str, - diffed_branch: str, - git_repo_url: str, - python_registry_url: str, - python_registry_check_url: str, - rollout_mode: RolloutMode, - gha_workflow_run_url: Optional[str] = None, - dagger_logs_url: Optional[str] = None, - pipeline_start_timestamp: Optional[int] = None, - ci_context: Optional[str] = None, - pull_request: Optional[PullRequest.PullRequest] = None, - s3_build_cache_access_key_id: Optional[Secret] = None, - s3_build_cache_secret_key: Optional[Secret] = None, - use_local_cdk: bool = False, - use_cdk_ref: Optional[str] = None, - python_registry_token: Optional[Secret] = None, - ci_github_access_token: Optional[Secret] = None, - ) -> None: - self.pre_release = pre_release - self.spec_cache_bucket_name = spec_cache_bucket_name - self.metadata_bucket_name = metadata_bucket_name - self.spec_cache_gcs_credentials = spec_cache_gcs_credentials - self.metadata_service_gcs_credentials = metadata_service_gcs_credentials - self.python_registry_token = python_registry_token - self.python_registry_url = python_registry_url - self.python_registry_check_url = python_registry_check_url - self.rollout_mode = rollout_mode - - pipeline_name = f"{rollout_mode.value} {connector.technical_name}" - pipeline_name = pipeline_name + " (pre-release)" if pre_release else pipeline_name - - if (use_local_cdk or use_cdk_ref) and not self.pre_release: - raise click.UsageError("Publishing with CDK overrides is only supported for pre-release publishing.") - - super().__init__( - pipeline_name=pipeline_name, - connector=connector, - report_output_prefix=report_output_prefix, - ci_report_bucket=ci_report_bucket, - is_local=is_local, - git_branch=git_branch, - git_revision=git_revision, - diffed_branch=diffed_branch, - git_repo_url=git_repo_url, - gha_workflow_run_url=gha_workflow_run_url, - dagger_logs_url=dagger_logs_url, - pipeline_start_timestamp=pipeline_start_timestamp, - ci_context=ci_context, - slack_webhook=slack_webhook, - ci_gcp_credentials=ci_gcp_credentials, - should_save_report=True, - use_local_cdk=use_local_cdk, - use_cdk_ref=use_cdk_ref, - docker_hub_username=docker_hub_username, - docker_hub_password=docker_hub_password, - s3_build_cache_access_key_id=s3_build_cache_access_key_id, - s3_build_cache_secret_key=s3_build_cache_secret_key, - ci_github_access_token=ci_github_access_token, - ) - - # Reassigning current class required instance attribute - # Which are optional in the super class - # for type checking - self.docker_hub_username: Secret = docker_hub_username - self.docker_hub_password: Secret = docker_hub_password - self.ci_gcp_credentials: Secret = ci_gcp_credentials - - @property - def pre_release_suffix(self) -> str: - return self.git_revision[:7] - - @property - def docker_image_tag(self) -> str: - # get the docker image tag from the parent class - metadata_tag = super().docker_image_tag - if self.pre_release: - return f"{metadata_tag}-preview.{self.pre_release_suffix}" - else: - return metadata_tag - - @property - def should_send_slack_message(self) -> bool: - should_send = super().should_send_slack_message - if not should_send: - return False - if self.pre_release: - return False - return True - - def get_slack_channels(self) -> List[str]: - if self.state in [ContextState.FAILURE, ContextState.ERROR]: - return [PUBLISH_UPDATES_SLACK_CHANNEL, PUBLISH_FAILURE_SLACK_CHANNEL] - else: - return [PUBLISH_UPDATES_SLACK_CHANNEL] - - def create_slack_message(self) -> str: - docker_hub_url = f"https://hub.docker.com/r/{self.connector.metadata['dockerRepository']}/tags" - message = f"*{self.rollout_mode.value} <{docker_hub_url}|{self.docker_image}>*\n" - if self.is_ci: - message += f"🤖 <{self.gha_workflow_run_url}|GitHub Action workflow>\n" - else: - message += "🧑‍💻 Local run\n" - message += f"*Connector:* {self.connector.technical_name}\n" - message += f"*Version:* {self.connector.version}\n" - branch_url = f"{AIRBYTE_GITHUB_REPO_URL_PREFIX}/tree/{self.git_branch}" - message += f"*Branch:* <{branch_url}|{self.git_branch}>\n" - commit_url = f"{AIRBYTE_GITHUB_REPO_URL_PREFIX}/commit/{self.git_revision}" - message += f"*Commit:* <{commit_url}|{self.git_revision[:10]}>\n" - if self.state in [ContextState.INITIALIZED, ContextState.RUNNING]: - message += "🟠" - if self.state is ContextState.SUCCESSFUL: - message += "🟢" - if self.state in [ContextState.FAILURE, ContextState.ERROR]: - message += "🔴" - message += f" {self.state.value['description']}\n" - if self.state is ContextState.SUCCESSFUL: - assert self.report is not None, "Report should be set when state is successful" - message += f"⏲️ Run duration: {format_duration(self.report.run_duration)}\n" - if self.state is ContextState.FAILURE: - message += "\ncc. " - return message diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/pipeline.py deleted file mode 100644 index 85836d67441d..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/publish/pipeline.py +++ /dev/null @@ -1,819 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -import json -import os -import uuid -from datetime import datetime -from pathlib import Path -from typing import Dict, Iterable, List, Tuple - -import anyio -import semver -import yaml -from airbyte_protocol.models.airbyte_protocol import ConnectorSpecification # type: ignore -from auto_merge.consts import AUTO_MERGE_BYPASS_CI_CHECKS_LABEL # type: ignore -from connector_ops.utils import METADATA_FILE_NAME, ConnectorLanguage # type: ignore -from dagger import ( - Container, - Directory, - ExecError, - File, - ImageLayerCompression, - Platform, - QueryError, -) -from pydantic import BaseModel, ValidationError - -from pipelines import consts -from pipelines.airbyte_ci.connectors.build_image import steps -from pipelines.airbyte_ci.connectors.publish.context import PublishConnectorContext, RolloutMode -from pipelines.airbyte_ci.connectors.reports import ConnectorReport -from pipelines.airbyte_ci.metadata.pipeline import MetadataUpload, MetadataValidation -from pipelines.airbyte_ci.steps.bump_version import SetConnectorVersion -from pipelines.airbyte_ci.steps.changelog import AddChangelogEntry -from pipelines.airbyte_ci.steps.pull_request import CreateOrUpdatePullRequest -from pipelines.airbyte_ci.steps.python_registry import ( - PublishToPythonRegistry, - PythonRegistryPublishContext, -) -from pipelines.consts import LOCAL_BUILD_PLATFORM -from pipelines.dagger.actions.remote_storage import upload_to_gcs -from pipelines.dagger.actions.system import docker -from pipelines.helpers.connectors.dagger_fs import dagger_read_file, dagger_write_file -from pipelines.helpers.pip import is_package_published -from pipelines.models.steps import Step, StepModifyingFiles, StepResult, StepStatus - - -class InvalidSpecOutputError(Exception): - pass - - -class CheckConnectorImageDoesNotExist(Step): - context: PublishConnectorContext - title = "Check if the connector docker image does not exist on the registry." - - async def _run(self) -> StepResult: - docker_repository, docker_tag = self.context.docker_image.split(":") - crane_ls = ( - docker.with_crane( - self.context, - ) - .with_env_variable("CACHEBUSTER", str(uuid.uuid4())) - .with_exec(["ls", docker_repository], use_entrypoint=True) - ) - try: - crane_ls_stdout = await crane_ls.stdout() - except ExecError as e: - if "NAME_UNKNOWN" in e.stderr: - return StepResult(step=self, status=StepStatus.SUCCESS, stdout=f"The docker repository {docker_repository} does not exist.") - else: - return StepResult(step=self, status=StepStatus.FAILURE, stderr=e.stderr, stdout=e.stdout) - else: # The docker repo exists and ls was successful - existing_tags = crane_ls_stdout.split("\n") - docker_tag_already_exists = docker_tag in existing_tags - if docker_tag_already_exists: - return StepResult(step=self, status=StepStatus.SKIPPED, stderr=f"{self.context.docker_image} already exists.") - return StepResult(step=self, status=StepStatus.SUCCESS, stdout=f"No manifest found for {self.context.docker_image}.") - - -class CheckPythonRegistryPackageDoesNotExist(Step): - context: PythonRegistryPublishContext - title = "Check if the connector is published on python registry" - - async def _run(self) -> StepResult: - is_published = is_package_published( - self.context.package_metadata.name, self.context.package_metadata.version, self.context.registry_check_url - ) - if is_published: - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stderr=f"{self.context.package_metadata.name} already exists in version {self.context.package_metadata.version}.", - ) - else: - return StepResult( - step=self, - status=StepStatus.SUCCESS, - stdout=f"{self.context.package_metadata.name} does not exist in version {self.context.package_metadata.version}.", - ) - - -class ConnectorDependenciesMetadata(BaseModel): - connector_technical_name: str - connector_repository: str - connector_version: str - connector_definition_id: str - dependencies: List[Dict[str, str]] - generation_time: datetime = datetime.utcnow() - - -class UploadDependenciesToMetadataService(Step): - context: PublishConnectorContext - title = "Upload connector dependencies list to GCS." - key_prefix = "connector_dependencies" - - async def _run(self, built_containers_per_platform: Dict[Platform, Container]) -> StepResult: - assert self.context.connector.language in [ - ConnectorLanguage.PYTHON, - ConnectorLanguage.LOW_CODE, - ], "This step can only run for Python connectors." - built_container = built_containers_per_platform[LOCAL_BUILD_PLATFORM] - pip_freeze_output = await built_container.with_exec(["pip", "freeze"]).stdout() - dependencies = [ - {"package_name": line.split("==")[0], "version": line.split("==")[1]} for line in pip_freeze_output.splitlines() if "==" in line - ] - connector_technical_name = self.context.connector.technical_name - connector_version = self.context.metadata["dockerImageTag"] - dependencies_metadata = ConnectorDependenciesMetadata( - connector_technical_name=connector_technical_name, - connector_repository=self.context.metadata["dockerRepository"], - connector_version=connector_version, - connector_definition_id=self.context.metadata["definitionId"], - dependencies=dependencies, - ).json() - file = ( - (await self.context.get_connector_dir()) - .with_new_file("dependencies.json", contents=dependencies_metadata) - .file("dependencies.json") - ) - key = f"{self.key_prefix}/{connector_technical_name}/{connector_version}/dependencies.json" - exit_code, stdout, stderr = await upload_to_gcs( - self.context.dagger_client, - file, - key, - self.context.metadata_bucket_name, - self.context.metadata_service_gcs_credentials, - flags=['--cache-control="no-cache"'], - ) - if exit_code != 0: - return StepResult(step=self, status=StepStatus.FAILURE, stdout=stdout, stderr=stderr) - return StepResult(step=self, status=StepStatus.SUCCESS, stdout="Uploaded connector dependencies to metadata service bucket.") - - -class PushConnectorImageToRegistry(Step): - context: PublishConnectorContext - title = "Push connector image to registry" - - @property - def latest_docker_image_name(self) -> str: - return f"{self.context.docker_repository}:latest" - - @property - def should_push_latest_tag(self) -> bool: - """ - We don't want to push the latest tag for release candidates or pre-releases. - - Returns: - bool: True if the latest tag should be pushed, False otherwise. - """ - is_release_candidate = "-rc" in self.context.connector.version - is_pre_release = self.context.pre_release - return not (is_release_candidate or is_pre_release) - - async def _run(self, built_containers_per_platform: List[Container], attempts: int = 3) -> StepResult: - try: - image_ref = await built_containers_per_platform[0].publish( - f"docker.io/{self.context.docker_image}", - platform_variants=built_containers_per_platform[1:], - forced_compression=ImageLayerCompression.Gzip, - ) - if self.should_push_latest_tag: - image_ref = await built_containers_per_platform[0].publish( - f"docker.io/{self.latest_docker_image_name}", - platform_variants=built_containers_per_platform[1:], - forced_compression=ImageLayerCompression.Gzip, - ) - return StepResult(step=self, status=StepStatus.SUCCESS, stdout=f"Published {image_ref}") - except QueryError as e: - if attempts > 0: - self.context.logger.error(str(e)) - self.context.logger.warn(f"Failed to publish {self.context.docker_image}. Retrying. {attempts} attempts left.") - await anyio.sleep(5) - return await self._run(built_containers_per_platform, attempts - 1) - return StepResult(step=self, status=StepStatus.FAILURE, stderr=str(e)) - - -class PushVersionImageAsLatest(Step): - context: PublishConnectorContext - title = "Push existing version image as latest" - - @property - def latest_docker_image_name(self) -> str: - return f"{self.context.docker_repository}:latest" - - async def _run(self, attempts: int = 3) -> StepResult: - per_platform_containers = [ - self.context.dagger_client.container(platform=platform).from_(f"docker.io/{self.context.docker_image}") - for platform in consts.BUILD_PLATFORMS - ] - - try: - image_ref = await per_platform_containers[0].publish( - f"docker.io/{self.latest_docker_image_name}", - platform_variants=per_platform_containers[1:], - forced_compression=ImageLayerCompression.Gzip, - ) - return StepResult(step=self, status=StepStatus.SUCCESS, stdout=f"Published {image_ref}") - except QueryError as e: - if attempts > 0: - self.context.logger.error(str(e)) - self.context.logger.warn(f"Failed to publish {self.context.docker_image}. Retrying. {attempts} attempts left.") - await anyio.sleep(5) - return await self._run(attempts - 1) - return StepResult(step=self, status=StepStatus.FAILURE, stderr=str(e)) - - -class PullConnectorImageFromRegistry(Step): - context: PublishConnectorContext - title = "Pull connector image from registry" - - async def check_if_image_only_has_gzip_layers(self) -> bool: - """Check if the image only has gzip layers. - Docker version > 21 can create images that has some layers compressed with zstd. - These layers are not supported by previous docker versions. - We want to make sure that the image we are about to release is compatible with all docker versions. - We use crane to inspect the manifest of the image and check if it only has gzip layers. - """ - has_only_gzip_layers = True - for platform in consts.BUILD_PLATFORMS: - inspect = docker.with_crane(self.context).with_exec( - ["manifest", "--platform", f"{str(platform)}", f"docker.io/{self.context.docker_image}"], use_entrypoint=True - ) - try: - inspect_stdout = await inspect.stdout() - except ExecError as e: - raise Exception(f"Failed to inspect {self.context.docker_image}: {e.stderr}") from e - try: - for layer in json.loads(inspect_stdout)["layers"]: - if not layer["mediaType"].endswith("gzip"): - has_only_gzip_layers = False - break - except (KeyError, json.JSONDecodeError) as e: - raise Exception(f"Failed to parse manifest for {self.context.docker_image}: {inspect_stdout}") from e - return has_only_gzip_layers - - async def _run(self, attempt: int = 3) -> StepResult: - try: - try: - await ( - self.context.dagger_client.container() - .from_(f"docker.io/{self.context.docker_image}") - .with_exec(["spec"], use_entrypoint=True) - ) - except ExecError: - if attempt > 0: - await anyio.sleep(10) - return await self._run(attempt - 1) - else: - return StepResult(step=self, status=StepStatus.FAILURE, stderr=f"Failed to pull {self.context.docker_image}") - if not await self.check_if_image_only_has_gzip_layers(): - return StepResult( - step=self, - status=StepStatus.FAILURE, - stderr=f"Image {self.context.docker_image} does not only have gzip compressed layers. Please rebuild the connector with Docker < 21.", - ) - else: - return StepResult( - step=self, - status=StepStatus.SUCCESS, - stdout=f"Pulled {self.context.docker_image} and validated it has gzip only compressed layers and we can run spec on it.", - ) - except QueryError as e: - if attempt > 0: - await anyio.sleep(10) - return await self._run(attempt - 1) - return StepResult(step=self, status=StepStatus.FAILURE, stderr=str(e)) - - -class UploadSpecToCache(Step): - context: PublishConnectorContext - title = "Upload connector spec to spec cache bucket" - default_spec_file_name = "spec.json" - cloud_spec_file_name = "spec.cloud.json" - - @property - def spec_key_prefix(self) -> str: - return "specs/" + self.context.docker_image.replace(":", "/") - - @property - def cloud_spec_key(self) -> str: - return f"{self.spec_key_prefix}/{self.cloud_spec_file_name}" - - @property - def oss_spec_key(self) -> str: - return f"{self.spec_key_prefix}/{self.default_spec_file_name}" - - def _parse_spec_output(self, spec_output: str) -> str: - parsed_spec_message = None - for line in spec_output.split("\n"): - try: - parsed_json = json.loads(line) - if parsed_json["type"] == "SPEC": - parsed_spec_message = parsed_json - break - except (json.JSONDecodeError, KeyError): - continue - if parsed_spec_message: - parsed_spec = parsed_spec_message["spec"] - try: - ConnectorSpecification.parse_obj(parsed_spec) - return json.dumps(parsed_spec) - except (ValidationError, ValueError) as e: - raise InvalidSpecOutputError(f"The SPEC message did not pass schema validation: {str(e)}.") - raise InvalidSpecOutputError("No spec found in the output of the SPEC command.") - - async def _get_connector_spec(self, connector: Container, deployment_mode: str) -> str: - """ - Get the connector spec by running the `spec` command in the connector container. - - Args: - connector (Container): The connector container. - deployment_mode (str): The deployment mode to run the spec command in. Valid values are "OSS" and "CLOUD". - """ - spec_output = ( - await connector.with_env_variable("DEPLOYMENT_MODE", deployment_mode).with_exec(["spec"], use_entrypoint=True).stdout() - ) - return self._parse_spec_output(spec_output) - - async def _get_spec_as_file(self, spec: str, name: str = "spec_to_cache.json") -> File: - return (await self.context.get_connector_dir()).with_new_file(name, contents=spec).file(name) - - async def _run(self, built_connector: Container) -> StepResult: - try: - oss_spec: str = await self._get_connector_spec(built_connector, "OSS") - cloud_spec: str = await self._get_connector_spec(built_connector, "CLOUD") - except InvalidSpecOutputError as e: - return StepResult(step=self, status=StepStatus.FAILURE, stderr=str(e)) - - specs_to_uploads: List[Tuple[str, File]] = [(self.oss_spec_key, await self._get_spec_as_file(oss_spec))] - - if oss_spec != cloud_spec: - specs_to_uploads.append((self.cloud_spec_key, await self._get_spec_as_file(cloud_spec, "cloud_spec_to_cache.json"))) - - for key, file in specs_to_uploads: - exit_code, stdout, stderr = await upload_to_gcs( - self.context.dagger_client, - file, - key, - self.context.spec_cache_bucket_name, - self.context.spec_cache_gcs_credentials, - flags=['--cache-control="no-cache"'], - ) - if exit_code != 0: - return StepResult(step=self, status=StepStatus.FAILURE, stdout=stdout, stderr=stderr) - return StepResult(step=self, status=StepStatus.SUCCESS, stdout="Uploaded connector spec to spec cache bucket.") - - -class UploadSbom(Step): - context: PublishConnectorContext - title = "Upload SBOM to metadata service bucket" - SBOM_KEY_PREFIX = "sbom" - SYFT_DOCKER_IMAGE = "anchore/syft:v1.6.0" - SBOM_FORMAT = "spdx-json" - IN_CONTAINER_SBOM_PATH = "sbom.json" - SBOM_EXTENSION = "spdx.json" - - def get_syft_container(self) -> Container: - home_dir = os.path.expanduser("~") - config_path = os.path.join(home_dir, ".docker", "config.json") - config_file = self.dagger_client.host().file(config_path) - return ( - self.dagger_client.container() - .from_(self.SYFT_DOCKER_IMAGE) - .with_mounted_file("/config/config.json", config_file) - .with_env_variable("DOCKER_CONFIG", "/config") - # Syft requires access to the docker daemon. We share the host's docker socket with the Syft container. - .with_unix_socket("/var/run/docker.sock", self.dagger_client.host().unix_socket("/var/run/docker.sock")) - ) - - async def _run(self) -> StepResult: - try: - syft_container = self.get_syft_container() - sbom_file = await syft_container.with_exec( - [self.context.docker_image, "-o", f"{self.SBOM_FORMAT}={self.IN_CONTAINER_SBOM_PATH}"], use_entrypoint=True - ).file(self.IN_CONTAINER_SBOM_PATH) - except ExecError as e: - return StepResult(step=self, status=StepStatus.FAILURE, stderr=str(e), exc_info=e) - - # This will lead to a key like: sbom/airbyte/source-faker/0.1.0.json - key = f"{self.SBOM_KEY_PREFIX}/{self.context.docker_image.replace(':', '/')}.{self.SBOM_EXTENSION}" - exit_code, stdout, stderr = await upload_to_gcs( - self.context.dagger_client, - sbom_file, - key, - self.context.metadata_bucket_name, - self.context.metadata_service_gcs_credentials, - flags=['--cache-control="no-cache"', "--content-type=application/json"], - ) - if exit_code != 0: - return StepResult(step=self, status=StepStatus.FAILURE, stdout=stdout, stderr=stderr) - return StepResult(step=self, status=StepStatus.SUCCESS, stdout="Uploaded SBOM to metadata service bucket.") - - -class SetPromotedVersion(SetConnectorVersion): - context: PublishConnectorContext - title = "Promote release candidate" - - @property - def current_semver_version(self) -> semver.Version: - return semver.Version.parse(self.context.connector.version) - - @property - def promoted_semver_version(self) -> semver.Version: - return self.current_semver_version.replace(prerelease=None) - - @property - def promoted_version(self) -> str: - return str(self.promoted_semver_version) - - @property - def current_version_is_rc(self) -> bool: - return bool(self.current_semver_version.prerelease and "rc" in self.current_semver_version.prerelease) - - def __init__(self, context: PublishConnectorContext, connector_directory: Directory) -> None: - self.context = context - super().__init__(context, connector_directory, self.promoted_version) - - async def _run(self) -> StepResult: - if not self.current_version_is_rc: - return StepResult(step=self, status=StepStatus.SKIPPED, stdout="The connector version has no rc suffix.") - return await super()._run() - - -class DisableProgressiveRollout(StepModifyingFiles): - context: PublishConnectorContext - title = "Disable progressive rollout in metadata file" - - async def _run(self) -> StepResult: - raw_metadata = await dagger_read_file(await self.context.get_connector_dir(include=[METADATA_FILE_NAME]), METADATA_FILE_NAME) - current_metadata = yaml.safe_load(raw_metadata) - enable_progressive_rollout = ( - current_metadata.get("data", {}).get("releases", {}).get("rolloutConfiguration", {}).get("enableProgressiveRollout", False) - ) - if not enable_progressive_rollout: - return StepResult(step=self, status=StepStatus.SKIPPED, stdout="Progressive rollout is already disabled.") - # We do an in-place replacement instead of serializing back to yaml to preserve comments and formatting. - new_raw_metadata = raw_metadata.replace("enableProgressiveRollout: true", "enableProgressiveRollout: false") - self.modified_directory = dagger_write_file(self.modified_directory, METADATA_FILE_NAME, new_raw_metadata) - self.modified_files.append(METADATA_FILE_NAME) - return StepResult( - step=self, - status=StepStatus.SUCCESS, - stdout="Set enableProgressiveRollout to false in connector metadata.", - output=self.modified_directory, - ) - - -# Helpers -def create_connector_report(results: List[StepResult], context: PublishConnectorContext) -> ConnectorReport: - """Generate a connector report from results and assign it to the context. - - Args: - results (List[StepResult]): List of step results. - context (PublishConnectorContext): The connector context to assign the report to. - - Returns: - ConnectorReport: The connector report. - """ - report = ConnectorReport(context, results, name="PUBLISH RESULTS") - context.report = report - return report - - -# Pipeline -async def run_connector_publish_pipeline(context: PublishConnectorContext, semaphore: anyio.Semaphore) -> ConnectorReport: - """Run a publish pipeline for a single connector. - - 1. Validate the metadata file. - 2. Check if the connector image already exists. - 3. Build the connector, with platform variants. - 4. Push the connector to DockerHub, with platform variants. - 5. Upload its spec to the spec cache bucket. - 6. Upload its metadata file to the metadata service bucket. - - Returns: - ConnectorReport: The reports holding publish results. - """ - - assert context.rollout_mode == RolloutMode.PUBLISH, "This pipeline can only run in publish mode." - - metadata_upload_step = MetadataUpload( - context=context, - metadata_service_gcs_credentials=context.metadata_service_gcs_credentials, - docker_hub_username=context.docker_hub_username, - docker_hub_password=context.docker_hub_password, - metadata_bucket_name=context.metadata_bucket_name, - pre_release=context.pre_release, - pre_release_tag=context.docker_image_tag, - ) - - upload_spec_to_cache_step = UploadSpecToCache(context) - - upload_sbom_step = UploadSbom(context) - - async with semaphore: - async with context: - results = [] - - # Check if the connector image is already published to the registry. - check_connector_image_results = await CheckConnectorImageDoesNotExist(context).run() - results.append(check_connector_image_results) - - python_registry_steps, terminate_early = await _run_python_registry_publish_pipeline(context) - results.extend(python_registry_steps) - - if terminate_early: - return create_connector_report(results, context) - - # If the connector image already exists, we don't need to build it, but we still need to upload the metadata file. - # We also need to upload the spec to the spec cache bucket. - # For pre-releases, rebuild all the time. - if check_connector_image_results.status is StepStatus.SKIPPED and not context.pre_release: - context.logger.info( - "The connector version is already published. Let's upload metadata.yaml and spec to GCS even if no version bump happened." - ) - already_published_connector = context.dagger_client.container().from_(context.docker_image) - upload_to_spec_cache_results = await upload_spec_to_cache_step.run(already_published_connector) - results.append(upload_to_spec_cache_results) - if upload_to_spec_cache_results.status is not StepStatus.SUCCESS: - return create_connector_report(results, context) - - upload_sbom_results = await upload_sbom_step.run() - results.append(upload_sbom_results) - if upload_sbom_results.status is not StepStatus.SUCCESS: - return create_connector_report(results, context) - - metadata_upload_results = await metadata_upload_step.run() - results.append(metadata_upload_results) - - # Exit early if the connector image already exists - if check_connector_image_results.status is not StepStatus.SUCCESS and not context.pre_release: - return create_connector_report(results, context) - - build_connector_results = await steps.run_connector_build(context) - results.append(build_connector_results) - - # Exit early if the connector image failed to build - if build_connector_results.status is not StepStatus.SUCCESS: - return create_connector_report(results, context) - - if context.connector.language in [ConnectorLanguage.PYTHON, ConnectorLanguage.LOW_CODE]: - upload_dependencies_step = await UploadDependenciesToMetadataService(context).run(build_connector_results.output) - results.append(upload_dependencies_step) - - built_connector_platform_variants = list(build_connector_results.output.values()) - push_connector_image_results = await PushConnectorImageToRegistry(context).run(built_connector_platform_variants) - results.append(push_connector_image_results) - - # Exit early if the connector image failed to push - if push_connector_image_results.status is not StepStatus.SUCCESS: - return create_connector_report(results, context) - - # Make sure the image published is healthy by pulling it and running SPEC on it. - # See https://github.com/airbytehq/airbyte/issues/26085 - pull_connector_image_results = await PullConnectorImageFromRegistry(context).run() - results.append(pull_connector_image_results) - - # Exit early if the connector image failed to pull - if pull_connector_image_results.status is not StepStatus.SUCCESS: - return create_connector_report(results, context) - - upload_to_spec_cache_results = await upload_spec_to_cache_step.run(built_connector_platform_variants[0]) - results.append(upload_to_spec_cache_results) - if upload_to_spec_cache_results.status is not StepStatus.SUCCESS: - return create_connector_report(results, context) - - upload_sbom_results = await upload_sbom_step.run() - results.append(upload_sbom_results) - if upload_sbom_results.status is not StepStatus.SUCCESS: - return create_connector_report(results, context) - - metadata_upload_results = await metadata_upload_step.run() - results.append(metadata_upload_results) - connector_report = create_connector_report(results, context) - return connector_report - - -async def _run_python_registry_publish_pipeline(context: PublishConnectorContext) -> Tuple[List[StepResult], bool]: - """ - Run the python registry publish pipeline for a single connector. - Return the results of the steps and a boolean indicating whether there was an error and the pipeline should be stopped. - """ - results: List[StepResult] = [] - # Try to convert the context to a PythonRegistryPublishContext. If it returns None, it means we don't need to publish to a python registry. - python_registry_context = await PythonRegistryPublishContext.from_publish_connector_context(context) - if not python_registry_context: - return results, False - - if not context.python_registry_token or not context.python_registry_url: - # If the python registry token or url are not set, we can't publish to the python registry - stop the pipeline. - return [ - StepResult( - step=PublishToPythonRegistry(python_registry_context), - status=StepStatus.FAILURE, - stderr="Pypi publishing is enabled, but python registry token or url are not set.", - ) - ], True - - check_python_registry_package_exists_results = await CheckPythonRegistryPackageDoesNotExist(python_registry_context).run() - results.append(check_python_registry_package_exists_results) - if check_python_registry_package_exists_results.status is StepStatus.SKIPPED: - context.logger.info("The connector version is already published on python registry.") - elif check_python_registry_package_exists_results.status is StepStatus.SUCCESS: - context.logger.info("The connector version is not published on python registry. Let's build and publish it.") - publish_to_python_registry_results = await PublishToPythonRegistry(python_registry_context).run() - results.append(publish_to_python_registry_results) - if publish_to_python_registry_results.status is StepStatus.FAILURE: - return results, True - elif check_python_registry_package_exists_results.status is StepStatus.FAILURE: - return results, True - - return results, False - - -def get_rollback_pr_creation_arguments( - modified_files: Iterable[Path], - context: PublishConnectorContext, - step_results: Iterable[StepResult], - release_candidate_version: str, -) -> Tuple[Tuple, Dict]: - return ( - (modified_files,), - { - "branch_id": f"{context.connector.technical_name}/rollback-{release_candidate_version}", - "commit_message": "[auto-publish] " # << We can skip Vercel builds if this is in the commit message - + "; ".join(step_result.step.title for step_result in step_results if step_result.success), - "pr_title": f"revert({context.connector.technical_name}): 🐙 stop progressive rollout for {release_candidate_version}", - "pr_body": f"The release candidate version {release_candidate_version} has been deemed unstable. This PR stops its progressive rollout. This PR will be automatically merged as part of the `auto-merge` workflow. This workflow runs every 2 hours.", - }, - ) - - -async def run_connector_rollback_pipeline(context: PublishConnectorContext, semaphore: anyio.Semaphore) -> ConnectorReport: - """Run a rollback pipeline for a single connector. - - 1. Disable progressive rollout in metadata file. - 2. Open a PR with the updated metadata, set the auto-merge label. - - Returns: - ConnectorReport: The reports holding promote results. - """ - - results = [] - current_version = context.connector.version - all_modified_files = set() - async with semaphore: - async with context: - assert context.rollout_mode == RolloutMode.ROLLBACK, "This pipeline can only run in rollback mode." - original_connector_directory = await context.get_connector_dir() - - # Disable progressive rollout in metadata file - reset_release_candidate = DisableProgressiveRollout(context, original_connector_directory) - reset_release_candidate_results = await reset_release_candidate.run() - results.append(reset_release_candidate_results) - if reset_release_candidate_results.success: - all_modified_files.update(await reset_release_candidate.export_modified_files(context.connector.code_directory)) - - if not all([result.success for result in results]): - context.logger.error("The metadata update failed. Skipping PR creation.") - connector_report = create_connector_report(results, context) - return connector_report - - # Open PR when all previous steps are successful - initial_pr_creation = CreateOrUpdatePullRequest( - context, - # We will merge even if the CI checks fail, due to this label: - labels=[AUTO_MERGE_BYPASS_CI_CHECKS_LABEL, "rollback-rc"], - # Let GitHub auto-merge this if all checks pass before the next run - # of our auto-merge workflow: - github_auto_merge=True, - # Don't skip CI, as it prevents the PR from auto-merging naturally: - skip_ci=False, - ) - pr_creation_args, pr_creation_kwargs = get_rollback_pr_creation_arguments(all_modified_files, context, results, current_version) - initial_pr_creation_result = await initial_pr_creation.run(*pr_creation_args, **pr_creation_kwargs) - results.append(initial_pr_creation_result) - - connector_report = create_connector_report(results, context) - return connector_report - - -def get_promotion_pr_creation_arguments( - modified_files: Iterable[Path], - context: PublishConnectorContext, - step_results: Iterable[StepResult], - release_candidate_version: str, - promoted_version: str, -) -> Tuple[Tuple, Dict]: - return ( - (modified_files,), - { - "branch_id": f"{context.connector.technical_name}/{promoted_version}", - "commit_message": "[auto-publish] " # << We can skip Vercel builds if this is in the commit message - + "; ".join(step_result.step.title for step_result in step_results if step_result.success), - "pr_title": f"release({context.connector.technical_name}): 🐙 promote {promoted_version}", - "pr_body": f"The release candidate version {release_candidate_version} has been deemed stable and is now ready to be promoted to an official release ({promoted_version}). This PR will be automatically merged as part of the `auto-merge` workflow. This workflow runs every 2 hours.", - }, - ) - - -async def run_connector_promote_pipeline(context: PublishConnectorContext, semaphore: anyio.Semaphore) -> ConnectorReport: - """Run a promote pipeline for a single connector. - - 1. Update connector metadata to: - * Remove the RC suffix from the version. - * Disable progressive rollout. - 2. Open a PR with the updated metadata. - 3. Add a changelog entry to the documentation. - 4. Update the PR with the updated changelog, set the auto-merge label. - - Returns: - ConnectorReport: The reports holding promote results. - """ - - results = [] - current_version = context.connector.version - all_modified_files = set() - async with semaphore: - async with context: - assert context.rollout_mode == RolloutMode.PROMOTE, "This pipeline can only run in promote mode." - original_connector_directory = await context.get_connector_dir() - # Remove RC suffix - set_promoted_version = SetPromotedVersion(context, original_connector_directory) - set_promoted_version_results = await set_promoted_version.run() - results.append(set_promoted_version_results) - if set_promoted_version_results.success: - all_modified_files.update(await set_promoted_version.export_modified_files(context.connector.code_directory)) - - # Disable progressive rollout in metadata file - reset_release_candidate = DisableProgressiveRollout(context, set_promoted_version_results.output) - reset_release_candidate_results = await reset_release_candidate.run() - results.append(reset_release_candidate_results) - if reset_release_candidate_results.success: - all_modified_files.update(await reset_release_candidate.export_modified_files(context.connector.code_directory)) - - if not all([result.success for result in results]): - context.logger.error("The metadata update failed. Skipping PR creation.") - connector_report = create_connector_report(results, context) - return connector_report - - # Open PR when all previous steps are successful - promoted_version = set_promoted_version.promoted_version - initial_pr_creation = CreateOrUpdatePullRequest(context, skip_ci=False) - pr_creation_args, pr_creation_kwargs = get_promotion_pr_creation_arguments( - all_modified_files, context, results, current_version, promoted_version - ) - initial_pr_creation_result = await initial_pr_creation.run(*pr_creation_args, **pr_creation_kwargs) - results.append(initial_pr_creation_result) - # Update changelog and update PR - if initial_pr_creation_result.success: - created_pr = initial_pr_creation_result.output - documentation_directory = await context.get_repo_dir( - include=[str(context.connector.local_connector_documentation_directory)] - ).directory(str(context.connector.local_connector_documentation_directory)) - add_changelog_entry = AddChangelogEntry( - context, - documentation_directory, - promoted_version, - f"Promoting release candidate {current_version} to a main version.", - created_pr.number, - ) - add_changelog_entry_result = await add_changelog_entry.run() - results.append(add_changelog_entry_result) - if add_changelog_entry_result.success: - all_modified_files.update( - await add_changelog_entry.export_modified_files(context.connector.local_connector_documentation_directory) - ) - post_changelog_pr_update = CreateOrUpdatePullRequest( - context, - skip_ci=False, # Don't skip CI, as it prevents the PR from auto-merging naturally. - # We will merge even if the CI checks fail, due to the "bypass-ci-checks" label: - labels=[AUTO_MERGE_BYPASS_CI_CHECKS_LABEL, "promoted-rc"], - github_auto_merge=True, # Let GitHub auto-merge this if/when all required checks have passed. - ) - pr_creation_args, pr_creation_kwargs = get_promotion_pr_creation_arguments( - all_modified_files, context, results, current_version, promoted_version - ) - post_changelog_pr_update_result = await post_changelog_pr_update.run(*pr_creation_args, **pr_creation_kwargs) - results.append(post_changelog_pr_update_result) - - connector_report = create_connector_report(results, context) - return connector_report - - -def reorder_contexts(contexts: List[PublishConnectorContext]) -> List[PublishConnectorContext]: - """Reorder contexts so that the ones that are for strict-encrypt/secure connectors come first. - The metadata upload on publish checks if the the connectors referenced in the metadata file are already published to DockerHub. - Non strict-encrypt variant reference the strict-encrypt variant in their metadata file for cloud. - So if we publish the non strict-encrypt variant first, the metadata upload will fail if the strict-encrypt variant is not published yet. - As strict-encrypt variant are often modified in the same PR as the non strict-encrypt variant, we want to publish them first. - """ - - def is_secure_variant(context: PublishConnectorContext) -> bool: - SECURE_VARIANT_KEYS = ["secure", "strict-encrypt"] - return any(key in context.connector.technical_name for key in SECURE_VARIANT_KEYS) - - return sorted(contexts, key=lambda context: (is_secure_variant(context), context.connector.technical_name), reverse=True) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pull_request/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pull_request/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pull_request/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pull_request/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pull_request/commands.py deleted file mode 100644 index 6237ffdc1786..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pull_request/commands.py +++ /dev/null @@ -1,82 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - - -import asyncclick as click - -from pipelines.airbyte_ci.connectors.pull_request.pipeline import run_connector_pull_request_pipeline -from pipelines.cli.dagger_pipeline_command import DaggerPipelineCommand -from pipelines.helpers.connectors.command import run_connector_pipeline - - -@click.command( - cls=DaggerPipelineCommand, - short_help="Create a pull request for changed files in the connector repository.", -) -@click.option( - "-m", - "--message", - help="Commit message and pull request title and changelog (if enabled).", - type=str, - required=True, -) -@click.option( - "-b", - "--branch_id", - help="update a branch named / instead generating one from the message.", - type=str, - required=True, -) -@click.option( - "--report", - is_flag=True, - type=bool, - default=False, - help="Auto open report browser.", -) -@click.option( - "--title", - help="Title of the PR to be created or edited (optional - defaults to message or no change).", - type=str, - required=False, -) -@click.option( - "--body", - help="Body of the PR to be created or edited (optional - defaults to empty or not change).", - type=str, - required=False, -) -@click.option( - "--changelog", - help="Add message to the changelog for this version.", - type=bool, - is_flag=True, - required=False, - default=False, -) -@click.option( - "--bump", - help="Bump the metadata.yaml version. Can be `major`, `minor`, or `patch`.", - type=click.Choice(["patch", "minor", "major"]), - required=False, - default=None, -) -@click.pass_context -async def pull_request( - ctx: click.Context, message: str, branch_id: str, report: bool, title: str, body: str, changelog: bool, bump: str | None -) -> bool: - if not ctx.obj["ci_github_access_token"]: - raise click.ClickException( - "GitHub access token is required to create or simulate a pull request. Set the CI_GITHUB_ACCESS_TOKEN environment variable." - ) - return await run_connector_pipeline( - ctx, - "Create pull request", - report, - run_connector_pull_request_pipeline, - message, - branch_id, - title, - body, - ) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pull_request/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pull_request/pipeline.py deleted file mode 100644 index 7ff2a1eb0ec4..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/pull_request/pipeline.py +++ /dev/null @@ -1,108 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -from pathlib import Path -from typing import TYPE_CHECKING, Set - -from pipelines import main_logger -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.airbyte_ci.connectors.reports import ConnectorReport, Report -from pipelines.airbyte_ci.steps.pull_request import CreateOrUpdatePullRequest -from pipelines.consts import CIContext -from pipelines.helpers.git import get_modified_files -from pipelines.helpers.utils import transform_strs_to_paths - -if TYPE_CHECKING: - from anyio import Semaphore - - -## HELPER FUNCTIONS -async def get_connector_changes(context: ConnectorContext) -> Set[Path]: - logger = main_logger - all_modified_files = set( - transform_strs_to_paths( - await get_modified_files( - context.git_branch, - context.git_revision, - context.diffed_branch, - context.is_local, - CIContext(context.ci_context), - context.git_repo_url, - ) - ) - ) - - directory = context.connector.code_directory - logger.info(f"Filtering to changes in {directory}") - # get a list of files that are a child of this path - connector_files = set([file for file in all_modified_files if directory in file.parents]) - # get doc too - doc_path = context.connector.documentation_file_path - - if doc_path in all_modified_files: - connector_files.add(doc_path) - - return connector_files - - -def replace_placeholder_with_pr_number(context: ConnectorContext, pr_number: int) -> Set[Path]: - current_doc = context.connector.documentation_file_path.read_text() - updated_doc = current_doc.replace("*PR_NUMBER_PLACEHOLDER*", str(pr_number)) - context.connector.documentation_file_path.write_text(updated_doc) - return {context.connector.documentation_file_path} - - -async def run_connector_pull_request_pipeline( - context: ConnectorContext, - semaphore: "Semaphore", - message: str, - branch_id: str, - title: str | None = None, - body: str | None = None, -) -> Report | ConnectorReport | None: - title = title or message - body = body or "" - async with semaphore: - async with context: - step_results = [] - modified_files = await get_connector_changes(context) - - create_or_update_pull_request = CreateOrUpdatePullRequest(context, skip_ci=True) - - if not modified_files: - step_results.append(create_or_update_pull_request.skip("No changes detected in the connector directory.")) - context.report = ConnectorReport(context, step_results, name="PULL REQUEST") - return context.report - - create_or_update_pull_request_result = await create_or_update_pull_request.run( - modified_files, - branch_id, - message, - title, - body, - ) - step_results.append(create_or_update_pull_request_result) - - if not create_or_update_pull_request_result.success: - return ConnectorReport( - context, - step_results, - name="PULL REQUEST", - ) - - created_pr = create_or_update_pull_request_result.output - modified_files.update(replace_placeholder_with_pr_number(context, created_pr.number)) - update_pull_request = CreateOrUpdatePullRequest(context, skip_ci=False) - update_pull_request_result = await update_pull_request.run( - modified_files, - branch_id, - message, - title, - body, - ) - step_results.append(update_pull_request_result) - - context.report = ConnectorReport(context, step_results, name="PULL REQUEST") - return context.report diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/reports.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/reports.py deleted file mode 100644 index 1447a10fcee8..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/reports.py +++ /dev/null @@ -1,195 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -import json -import webbrowser -from dataclasses import dataclass -from pathlib import Path -from types import MappingProxyType -from typing import TYPE_CHECKING, Dict - -from connector_ops.utils import console # type: ignore -from jinja2 import Environment, PackageLoader, select_autoescape -from rich.console import Group -from rich.panel import Panel -from rich.style import Style -from rich.table import Table -from rich.text import Text - -from pipelines.consts import GCS_PUBLIC_DOMAIN -from pipelines.helpers.github import AIRBYTE_GITHUB_REPO_URL_PREFIX, AIRBYTE_GITHUBUSERCONTENT_URL_PREFIX -from pipelines.helpers.utils import format_duration -from pipelines.models.artifacts import Artifact -from pipelines.models.reports import Report -from pipelines.models.steps import StepStatus - -if TYPE_CHECKING: - from typing import List - - from rich.tree import RenderableType - - from pipelines.airbyte_ci.connectors.context import ConnectorContext - - -@dataclass(frozen=True) -class ConnectorReport(Report): - """A dataclass to build connector test reports to share pipelines executions results with the user.""" - - pipeline_context: ConnectorContext - - @property - def report_output_prefix(self) -> str: - return f"{self.pipeline_context.report_output_prefix}/{self.pipeline_context.connector.technical_name}/{self.pipeline_context.connector.version}" - - @property - def html_report_file_name(self) -> str: - return self.filename + ".html" - - def file_remote_storage_key(self, file_name: str) -> str: - return f"{self.report_output_prefix}/{file_name}" - - @property - def html_report_remote_storage_key(self) -> str: - return self.file_remote_storage_key(self.html_report_file_name) - - def file_url(self, file_name: str) -> str: - return f"{GCS_PUBLIC_DOMAIN}/{self.pipeline_context.ci_report_bucket}/{self.file_remote_storage_key(file_name)}" - - @property - def html_report_url(self) -> str: - return self.file_url(self.html_report_file_name) - - def to_json(self) -> str: - """Create a JSON representation of the connector test report. - - Returns: - str: The JSON representation of the report. - """ - assert self.pipeline_context.pipeline_start_timestamp is not None, "The pipeline start timestamp must be set to save reports." - - return json.dumps( - { - "connector_technical_name": self.pipeline_context.connector.technical_name, - "connector_version": self.pipeline_context.connector.version, - "run_timestamp": self.created_at.isoformat(), - "run_duration": self.run_duration.total_seconds(), - "success": self.success, - "failed_steps": [s.step.__class__.__name__ for s in self.failed_steps], - "successful_steps": [s.step.__class__.__name__ for s in self.successful_steps], - "skipped_steps": [s.step.__class__.__name__ for s in self.skipped_steps], - "gha_workflow_run_url": self.pipeline_context.gha_workflow_run_url, - "pipeline_start_timestamp": self.pipeline_context.pipeline_start_timestamp, - "pipeline_end_timestamp": round(self.created_at.timestamp()), - "pipeline_duration": round(self.created_at.timestamp()) - self.pipeline_context.pipeline_start_timestamp, - "git_branch": self.pipeline_context.git_branch, - "git_revision": self.pipeline_context.git_revision, - "ci_context": self.pipeline_context.ci_context, - "cdk_version": self.pipeline_context.cdk_version, - "html_report_url": self.html_report_url, - "dagger_cloud_url": self.pipeline_context.dagger_cloud_url, - } - ) - - def to_html(self) -> str: - env = Environment( - loader=PackageLoader("pipelines.airbyte_ci.connectors.test.steps"), - autoescape=select_autoescape(), - trim_blocks=False, - lstrip_blocks=True, - ) - template = env.get_template("test_report.html.j2") - template.globals["StepStatus"] = StepStatus - template.globals["format_duration"] = format_duration - local_icon_path = Path(f"{self.pipeline_context.connector.code_directory}/icon.svg").resolve() - step_result_to_artifact_links: Dict[str, List[Dict]] = {} - for step_result in self.steps_results: - for artifact in step_result.artifacts: - if artifact.gcs_url: - url = artifact.gcs_url - elif artifact.local_path: - url = artifact.local_path.resolve().as_uri() - else: - continue - step_result_to_artifact_links.setdefault(step_result.step.title, []).append({"name": artifact.name, "url": url}) - - template_context = { - "connector_name": self.pipeline_context.connector.technical_name, - "step_results": self.steps_results, - "run_duration": self.run_duration, - "created_at": self.created_at.isoformat(), - "connector_version": self.pipeline_context.connector.version, - "gha_workflow_run_url": None, - "dagger_logs_url": None, - "git_branch": self.pipeline_context.git_branch, - "git_revision": self.pipeline_context.git_revision, - "commit_url": None, - "icon_url": local_icon_path.as_uri(), - "report": self, - "step_result_to_artifact_links": MappingProxyType(step_result_to_artifact_links), - } - - if self.pipeline_context.is_ci: - template_context["commit_url"] = f"{AIRBYTE_GITHUB_REPO_URL_PREFIX}/commit/{self.pipeline_context.git_revision}" - template_context["gha_workflow_run_url"] = self.pipeline_context.gha_workflow_run_url - template_context["dagger_logs_url"] = self.pipeline_context.dagger_logs_url - template_context["dagger_cloud_url"] = self.pipeline_context.dagger_cloud_url - template_context["icon_url"] = ( - f"{AIRBYTE_GITHUBUSERCONTENT_URL_PREFIX}/{self.pipeline_context.git_revision}/{self.pipeline_context.connector.code_directory}/icon.svg" - ) - return template.render(template_context) - - async def save_html_report(self) -> None: - """Save the report as HTML, upload it to GCS if the pipeline is running in CI""" - - html_report_path = self.report_dir_path / self.html_report_file_name - report_dir = self.pipeline_context.dagger_client.host().directory(str(self.report_dir_path)) - local_html_report_file = report_dir.with_new_file(self.html_report_file_name, self.to_html()).file(self.html_report_file_name) - html_report_artifact = Artifact(name="HTML Report", content_type="text/html", content=local_html_report_file) - await html_report_artifact.save_to_local_path(html_report_path) - absolute_path = html_report_path.absolute() - self.pipeline_context.logger.info(f"Report saved locally at {absolute_path}") - if self.pipeline_context.remote_storage_enabled: - gcs_url = await html_report_artifact.upload_to_gcs( - dagger_client=self.pipeline_context.dagger_client, - bucket=self.pipeline_context.ci_report_bucket, # type: ignore - key=self.html_report_remote_storage_key, - gcs_credentials=self.pipeline_context.ci_gcp_credentials, # type: ignore - ) - self.pipeline_context.logger.info(f"HTML report uploaded to {gcs_url}") - - elif self.pipeline_context.enable_report_auto_open: - self.pipeline_context.logger.info("Opening HTML report in browser.") - webbrowser.open(absolute_path.as_uri()) - - async def save(self) -> None: - await super().save() - await self.save_html_report() - - def print(self) -> None: - """Print the test report to the console in a nice way.""" - connector_name = self.pipeline_context.connector.technical_name - main_panel_title = Text(f"{connector_name.upper()} - {self.name}") - main_panel_title.stylize(Style(color="blue", bold=True)) - duration_subtitle = Text(f"⏲️ Total pipeline duration for {connector_name}: {format_duration(self.run_duration)}") - step_results_table = Table(title="Steps results") - step_results_table.add_column("Step") - step_results_table.add_column("Result") - step_results_table.add_column("Duration") - - for step_result in self.steps_results: - step = Text(step_result.step.title) - step.stylize(step_result.status.get_rich_style()) - result = Text(step_result.status.value) - result.stylize(step_result.status.get_rich_style()) - step_results_table.add_row(step, result, format_duration(step_result.step.run_duration)) - - details_instructions = Text("ℹ️ You can find more details with step executions logs in the saved HTML report.") - to_render: List[RenderableType] = [step_results_table, details_instructions] - - if self.pipeline_context.dagger_cloud_url: - self.pipeline_context.logger.info(f"🔗 View runs for commit in Dagger Cloud: {self.pipeline_context.dagger_cloud_url}") - - main_panel = Panel(Group(*to_render), title=main_panel_title, subtitle=duration_subtitle) - console.print(main_panel) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/commands.py deleted file mode 100644 index 83e26f5888da..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/commands.py +++ /dev/null @@ -1,200 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import shutil -from typing import Dict, List - -import asyncclick as click - -from pipelines import main_logger -from pipelines.airbyte_ci.connectors.consts import CONNECTOR_TEST_STEP_ID -from pipelines.airbyte_ci.connectors.pipeline import run_connectors_pipelines -from pipelines.airbyte_ci.connectors.test.context import ConnectorTestContext -from pipelines.airbyte_ci.connectors.test.pipeline import run_connector_test_pipeline -from pipelines.airbyte_ci.connectors.test.steps.common import LiveTests -from pipelines.cli.click_decorators import click_ci_requirements_option -from pipelines.cli.dagger_pipeline_command import DaggerPipelineCommand -from pipelines.consts import LOCAL_BUILD_PLATFORM, MAIN_CONNECTOR_TESTING_SECRET_STORE_ALIAS, ContextState -from pipelines.hacks import do_regression_test_status_check -from pipelines.helpers.execution import argument_parsing -from pipelines.helpers.execution.run_steps import RunStepOptions -from pipelines.helpers.github import update_global_commit_status_check_for_tests -from pipelines.helpers.utils import fail_if_missing_docker_hub_creds -from pipelines.models.secrets import GSMSecretStore -from pipelines.models.steps import STEP_PARAMS - -GITHUB_GLOBAL_CONTEXT_FOR_TESTS = "Connectors CI tests" -GITHUB_GLOBAL_DESCRIPTION_FOR_TESTS = "Running connectors tests" -REGRESSION_TEST_MANUAL_APPROVAL_CONTEXT = "Regression Test Results Reviewed and Approved" - - -@click.command( - cls=DaggerPipelineCommand, - help="Test all the selected connectors.", - context_settings=dict( - ignore_unknown_options=True, - ), -) -@click_ci_requirements_option() -@click.option( - "--code-tests-only", - is_flag=True, - help=("Only execute code tests. " "Metadata checks, QA, and acceptance tests will be skipped."), - default=False, - type=bool, -) -@click.option( - "--fail-fast", - help="When enabled, tests will fail fast.", - default=False, - type=bool, - is_flag=True, -) -@click.option( - "--concurrent-cat", - help="When enabled, the CAT tests will run concurrently. Be careful about rate limits", - default=False, - type=bool, - is_flag=True, -) -@click.option( - "--skip-step", - "-x", - "skip_steps", - multiple=True, - type=click.Choice([step_id.value for step_id in CONNECTOR_TEST_STEP_ID]), - help="Skip a step by name. Can be used multiple times to skip multiple steps.", -) -@click.option( - "--only-step", - "-k", - "only_steps", - multiple=True, - type=click.Choice([step_id.value for step_id in CONNECTOR_TEST_STEP_ID]), - help="Only run specific step by name. Can be used multiple times to keep multiple steps.", -) -@click.option( - "--global-status-check-context", - "global_status_check_context", - help="The context of the global status check which will be sent to GitHub status API.", - default=GITHUB_GLOBAL_CONTEXT_FOR_TESTS, -) -@click.option( - "--global-status-check-description", - "global_status_check_description", - help="The description of the global status check which will be sent to GitHub status API.", - default=GITHUB_GLOBAL_DESCRIPTION_FOR_TESTS, -) -@click.argument( - "extra_params", nargs=-1, type=click.UNPROCESSED, callback=argument_parsing.build_extra_params_mapping(CONNECTOR_TEST_STEP_ID) -) -@click.pass_context -async def test( - ctx: click.Context, - code_tests_only: bool, - fail_fast: bool, - concurrent_cat: bool, - skip_steps: List[str], - only_steps: List[str], - global_status_check_context: str, - global_status_check_description: str, - extra_params: Dict[CONNECTOR_TEST_STEP_ID, STEP_PARAMS], -) -> bool: - """Runs a test pipeline for the selected connectors. - - Args: - ctx (click.Context): The click context. - """ - ctx.obj["global_status_check_context"] = global_status_check_context - ctx.obj["global_status_check_description"] = global_status_check_description - - if ctx.obj["ci_gcp_credentials"]: - ctx.obj["secret_stores"][MAIN_CONNECTOR_TESTING_SECRET_STORE_ALIAS] = GSMSecretStore(ctx.obj["ci_gcp_credentials"]) - else: - main_logger.warn(f"The credentials to connect to {MAIN_CONNECTOR_TESTING_SECRET_STORE_ALIAS} were are not defined.") - - if only_steps and skip_steps: - raise click.UsageError("Cannot use both --only-step and --skip-step at the same time.") - if not only_steps: - skip_steps = list(skip_steps) - if ctx.obj["is_ci"]: - fail_if_missing_docker_hub_creds(ctx) - - do_regression_test_status_check(ctx, REGRESSION_TEST_MANUAL_APPROVAL_CONTEXT, main_logger) - if ctx.obj["selected_connectors_with_modified_files"]: - update_global_commit_status_check_for_tests(ctx.obj, "pending") - else: - main_logger.warn("No connector were selected for testing.") - update_global_commit_status_check_for_tests(ctx.obj, "success") - return True - - run_step_options = RunStepOptions( - fail_fast=fail_fast, - skip_steps=[CONNECTOR_TEST_STEP_ID(step_id) for step_id in skip_steps], - keep_steps=[CONNECTOR_TEST_STEP_ID(step_id) for step_id in only_steps], - step_params=extra_params, - ) - - connectors_tests_contexts = [ - ConnectorTestContext( - pipeline_name=f"{global_status_check_context} on {connector.technical_name}", - connector=connector, - is_local=ctx.obj["is_local"], - git_branch=ctx.obj["git_branch"], - git_revision=ctx.obj["git_revision"], - diffed_branch=ctx.obj["diffed_branch"], - git_repo_url=ctx.obj["git_repo_url"], - ci_git_user=ctx.obj["ci_git_user"], - ci_github_access_token=ctx.obj["ci_github_access_token"], - ci_report_bucket=ctx.obj["ci_report_bucket_name"], - report_output_prefix=ctx.obj["report_output_prefix"], - gha_workflow_run_url=ctx.obj.get("gha_workflow_run_url"), - dagger_logs_url=ctx.obj.get("dagger_logs_url"), - pipeline_start_timestamp=ctx.obj.get("pipeline_start_timestamp"), - ci_context=ctx.obj.get("ci_context"), - pull_request=ctx.obj.get("pull_request"), - ci_gcp_credentials=ctx.obj["ci_gcp_credentials"], - code_tests_only=code_tests_only, - use_local_cdk=ctx.obj.get("use_local_cdk"), - use_cdk_ref=ctx.obj.get("use_cdk_ref"), - s3_build_cache_access_key_id=ctx.obj.get("s3_build_cache_access_key_id"), - s3_build_cache_secret_key=ctx.obj.get("s3_build_cache_secret_key"), - docker_hub_username=ctx.obj.get("docker_hub_username"), - docker_hub_password=ctx.obj.get("docker_hub_password"), - concurrent_cat=concurrent_cat, - run_step_options=run_step_options, - targeted_platforms=[LOCAL_BUILD_PLATFORM], - secret_stores=ctx.obj["secret_stores"], - enable_report_auto_open=ctx.obj.get("enable_report_auto_open", True), - ) - for connector in ctx.obj["selected_connectors_with_modified_files"] - ] - - try: - await run_connectors_pipelines( - [connector_context for connector_context in connectors_tests_contexts], - run_connector_test_pipeline, - "Test Pipeline", - ctx.obj["concurrency"], - ctx.obj["dagger_logs_path"], - ctx.obj["execute_timeout"], - ) - except Exception as e: - main_logger.error("An error occurred while running the test pipeline", exc_info=e) - update_global_commit_status_check_for_tests(ctx.obj, "failure") - return False - - finally: - if LiveTests.local_tests_artifacts_dir.exists(): - shutil.rmtree(LiveTests.local_tests_artifacts_dir) - main_logger.info(f" Test artifacts cleaned up from {LiveTests.local_tests_artifacts_dir}") - - @ctx.call_on_close - def send_commit_status_check() -> None: - if ctx.obj["is_ci"]: - global_success = all(connector_context.state is ContextState.SUCCESSFUL for connector_context in connectors_tests_contexts) - update_global_commit_status_check_for_tests(ctx.obj, "success" if global_success else "failure") - - # If we reach this point, it means that all the connectors have been tested so the pipeline did its job and can exit with success. - return True diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/context.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/context.py deleted file mode 100644 index 7bdb40270095..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/context.py +++ /dev/null @@ -1,198 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""Module declaring context related classes.""" - -from copy import deepcopy -from logging import Logger -from typing import Any, Dict, List, Optional - -from pydash import find # type: ignore - -from pipelines.airbyte_ci.connectors.consts import CONNECTOR_TEST_STEP_ID -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.helpers.execution.run_steps import RunStepOptions -from pipelines.models.secrets import Secret, SecretNotFoundError, SecretStore - -# These test suite names are declared in metadata.yaml files -TEST_SUITE_NAME_TO_STEP_ID = { - "unitTests": CONNECTOR_TEST_STEP_ID.UNIT, - "integrationTests": CONNECTOR_TEST_STEP_ID.INTEGRATION, - "acceptanceTests": CONNECTOR_TEST_STEP_ID.ACCEPTANCE, - "liveTests": CONNECTOR_TEST_STEP_ID.CONNECTOR_LIVE_TESTS, -} - - -class ConnectorTestContext(ConnectorContext): - def __init__( - self, - *args: Any, - **kwargs: Any, - ) -> None: - super().__init__(*args, **kwargs) - self.run_step_options = self._skip_metadata_disabled_test_suites(self.run_step_options) - self.step_id_to_secrets_mapping = self._get_step_id_to_secret_mapping() - - @property - def test_only_change(self) -> bool: - """Check if the only modified files are in unit_tests or integration_tests directories. - - Returns: - bool: True if all modified files are in unit_tests or integration_tests, False otherwise. - """ - test_directories = ("unit_tests", "integration_tests") - for modified_file in self.modified_files: - try: - rel_path = modified_file.relative_to(self.connector.code_directory) - top_level_dir = rel_path.parts[0] if rel_path.parts else "" - if top_level_dir not in test_directories: - return False - except ValueError: - # File not under connector directory, treat as non-test change - return False - return True - - @staticmethod - def _handle_missing_secret_store( - secret_info: Dict[str, str | Dict[str, str]], raise_on_missing: bool, logger: Optional[Logger] = None - ) -> None: - assert isinstance(secret_info["secretStore"], dict), "The secretStore field must be a dict" - message = f"Secret {secret_info['name']} can't be retrieved as {secret_info['secretStore']['alias']} is not available" - if raise_on_missing: - raise SecretNotFoundError(message) - if logger is not None: - logger.warn(message) - - @staticmethod - def _process_secret( - secret_info: Dict[str, str | Dict[str, str]], - secret_stores: Dict[str, SecretStore], - raise_on_missing: bool, - logger: Optional[Logger] = None, - ) -> Optional[Secret]: - assert isinstance(secret_info["secretStore"], dict), "The secretStore field must be a dict" - secret_store_alias = secret_info["secretStore"]["alias"] - if secret_store_alias not in secret_stores: - ConnectorTestContext._handle_missing_secret_store(secret_info, raise_on_missing, logger) - return None - else: - # All these asserts and casting are there to make MyPy happy - # The dict structure being nested MyPy can't figure if the values are str or dict - assert isinstance(secret_info["name"], str), "The secret name field must be a string" - if file_name := secret_info.get("fileName"): - assert isinstance(secret_info["fileName"], str), "The secret fileName must be a string" - file_name = str(secret_info["fileName"]) - else: - file_name = None - return Secret(secret_info["name"], secret_stores[secret_store_alias], file_name=file_name) - - @staticmethod - def get_secrets_from_connector_test_suites_option( - connector_test_suites_options: List[Dict[str, str | Dict[str, List[Dict[str, str | Dict[str, str]]]]]], - suite_name: str, - secret_stores: Dict[str, SecretStore], - raise_on_missing_secret_store: bool = True, - logger: Logger | None = None, - ) -> List[Secret]: - """Get secrets declared in metadata connectorTestSuitesOptions for a test suite name. - It will use the secret store alias declared in connectorTestSuitesOptions. - If the secret store is not available a warning or and error could be raised according to the raise_on_missing_secret_store parameter value. - We usually want to raise an error when running in CI context and log a warning when running locally, as locally we can fallback on local secrets. - - Args: - connector_test_suites_options (List[Dict[str, str | Dict]]): The connector under test test suite options - suite_name (str): The test suite name - secret_stores (Dict[str, SecretStore]): The available secrets stores - raise_on_missing_secret_store (bool, optional): Raise an error if the secret store declared in the connectorTestSuitesOptions is not available. Defaults to True. - logger (Logger | None, optional): Logger to log a warning if the secret store declared in the connectorTestSuitesOptions is not available. Defaults to None. - - Raises: - SecretNotFoundError: Raised if the secret store declared in the connectorTestSuitesOptions is not available and raise_on_missing_secret_store is truthy. - - Returns: - List[Secret]: List of secrets declared in the connectorTestSuitesOptions for a test suite name. - """ - secrets: List[Secret] = [] - enabled_test_suite = find(connector_test_suites_options, lambda x: x["suite"] == suite_name) - - if enabled_test_suite and "testSecrets" in enabled_test_suite: - for secret_info in enabled_test_suite["testSecrets"]: - if secret := ConnectorTestContext._process_secret(secret_info, secret_stores, raise_on_missing_secret_store, logger): - secrets.append(secret) - return secrets - - def get_connector_secrets_for_test_suite( - self, test_suite_name: str, connector_test_suites_options: List, local_secrets: List[Secret] - ) -> List[Secret]: - """Get secrets to use for a test suite. - Always merge secrets declared in metadata's connectorTestSuiteOptions with secrets declared locally. - - Args: - test_suite_name (str): Name of the test suite to get secrets for - context (ConnectorTestContext): The current connector context - connector_test_suites_options (Dict): The current connector test suite options (from metadata) - local_secrets (List[Secret]): The local connector secrets. - - Returns: - List[Secret]: Secrets to use to run the passed test suite name. - """ - return ( - self.get_secrets_from_connector_test_suites_option( - connector_test_suites_options, - test_suite_name, - self.secret_stores, - raise_on_missing_secret_store=self.is_ci, - logger=self.logger, - ) - + local_secrets - ) - - def _get_step_id_to_secret_mapping(self) -> Dict[CONNECTOR_TEST_STEP_ID, List[Secret]]: - step_id_to_secrets: Dict[CONNECTOR_TEST_STEP_ID, List[Secret]] = { - CONNECTOR_TEST_STEP_ID.UNIT: [], - CONNECTOR_TEST_STEP_ID.INTEGRATION: [], - CONNECTOR_TEST_STEP_ID.ACCEPTANCE: [], - } - local_secrets = self.local_secret_store.get_all_secrets() if self.local_secret_store else [] - connector_test_suites_options = self.metadata.get("connectorTestSuitesOptions", []) - - keep_steps = set(self.run_step_options.keep_steps or []) - skip_steps = set(self.run_step_options.skip_steps or []) - - for test_suite_name, step_id in TEST_SUITE_NAME_TO_STEP_ID.items(): - if step_id in keep_steps or (not keep_steps and step_id not in skip_steps): - step_id_to_secrets[step_id] = self.get_connector_secrets_for_test_suite( - test_suite_name, connector_test_suites_options, local_secrets - ) - return step_id_to_secrets - - def get_secrets_for_step_id(self, step_id: CONNECTOR_TEST_STEP_ID) -> List[Secret]: - return self.step_id_to_secrets_mapping.get(step_id, []) - - def _get_step_id_to_skip_according_to_metadata(self) -> List[CONNECTOR_TEST_STEP_ID]: - """The connector metadata have a connectorTestSuitesOptions field. - It allows connector developers to declare the test suites that are enabled for a connector. - This function retrieved enabled test suites according to this field value and returns the test suites steps that are skipped (because they're not declared in this field.) - The skippable test suites steps are declared in TEST_SUITE_NAME_TO_STEP_ID. - - Returns: - List[CONNECTOR_TEST_STEP_ID]: List of step ids that should be skipped according to connector metadata. - """ - enabled_test_suites = [option["suite"] for option in self.metadata.get("connectorTestSuitesOptions", [])] - return [step_id for test_suite_name, step_id in TEST_SUITE_NAME_TO_STEP_ID.items() if test_suite_name not in enabled_test_suites] - - def _skip_metadata_disabled_test_suites(self, run_step_options: RunStepOptions) -> RunStepOptions: - """Updated the original run_step_options to skip the disabled test suites according to connector metadata. - - Args: - run_step_options (RunStepOptions): Original run step options. - - Returns: - RunStepOptions: Updated run step options. - """ - run_step_options = deepcopy(run_step_options) - # If any `skip_steps` are present, we will run everything except the skipped steps, instead of just `keep_steps`. - if not run_step_options.keep_steps: - run_step_options.skip_steps += self._get_step_id_to_skip_according_to_metadata() - return run_step_options diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/pipeline.py deleted file mode 100644 index 0aad2fa7167f..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/pipeline.py +++ /dev/null @@ -1,77 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -"""This module groups factory like functions to dispatch tests steps according to the connector under test language.""" - -from __future__ import annotations - -from typing import TYPE_CHECKING - -import anyio -from connector_ops.utils import ConnectorLanguage # type: ignore - -from pipelines.airbyte_ci.connectors.consts import CONNECTOR_TEST_STEP_ID -from pipelines.airbyte_ci.connectors.reports import ConnectorReport -from pipelines.airbyte_ci.connectors.test.context import ConnectorTestContext -from pipelines.airbyte_ci.connectors.test.steps import java_connectors, manifest_only_connectors, python_connectors -from pipelines.airbyte_ci.connectors.test.steps.common import VersionIncrementCheck -from pipelines.helpers.execution.run_steps import StepToRun, run_steps - -if TYPE_CHECKING: - from pipelines.helpers.execution.run_steps import STEP_TREE - -LANGUAGE_MAPPING = { - "get_test_steps": { - ConnectorLanguage.PYTHON: python_connectors.get_test_steps, - ConnectorLanguage.LOW_CODE: python_connectors.get_test_steps, - ConnectorLanguage.MANIFEST_ONLY: manifest_only_connectors.get_test_steps, - ConnectorLanguage.JAVA: java_connectors.get_test_steps, - }, -} - - -def get_test_steps(context: ConnectorTestContext) -> STEP_TREE: - """Get all the tests steps according to the connector language. - - Args: - context (ConnectorTestContext): The current connector context. - - Returns: - STEP_TREE: The list of tests steps. - """ - if _get_test_steps := LANGUAGE_MAPPING["get_test_steps"].get(context.connector.language): - return _get_test_steps(context) - else: - context.logger.warning(f"No tests defined for connector language {context.connector.language}!") - return [] - - -async def run_connector_test_pipeline(context: ConnectorTestContext, semaphore: anyio.Semaphore) -> ConnectorReport: - """ - Compute the steps to run for a connector test pipeline. - """ - all_steps_to_run: STEP_TREE = [] - - all_steps_to_run += get_test_steps(context) - - # Skip static analysis steps when only test files are modified - if not context.code_tests_only and not context.test_only_change: - static_analysis_steps_to_run = [ - [ - StepToRun(id=CONNECTOR_TEST_STEP_ID.VERSION_INC_CHECK, step=VersionIncrementCheck(context)), - ] - ] - all_steps_to_run += static_analysis_steps_to_run - - async with semaphore: - async with context: - result_dict = await run_steps( - runnables=all_steps_to_run, - options=context.run_step_options, - ) - - results = list(result_dict.values()) - report = ConnectorReport(context, steps_results=results, name="TEST RESULTS") - context.report = report - - return report diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/common.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/common.py deleted file mode 100644 index 5b9a91bf9d28..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/common.py +++ /dev/null @@ -1,838 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""This module groups steps made to run tests agnostic to a connector language.""" - -import datetime -import json -import os -import time -from abc import ABC, abstractmethod -from enum import Enum -from functools import cached_property -from pathlib import Path -from textwrap import dedent -from typing import Any, Dict, List, Optional, Set - -import dagger -import requests # type: ignore -import semver -import yaml # type: ignore -from dagger import Container, Directory - -# This slugify lib has to be consistent with the slugify lib used in live_tests -# live_test can't resolve the passed connector container otherwise. -from slugify import slugify # type: ignore - -from pipelines import hacks, main_logger -from pipelines.airbyte_ci.connectors.consts import CONNECTOR_TEST_STEP_ID -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.airbyte_ci.steps.docker import SimpleDockerStep -from pipelines.consts import INTERNAL_TOOL_PATHS, CIContext -from pipelines.dagger.actions import secrets -from pipelines.dagger.actions.python.poetry import with_poetry -from pipelines.helpers.github import AIRBYTE_GITHUBUSERCONTENT_URL_PREFIX -from pipelines.helpers.utils import METADATA_FILE_NAME, get_exec_result -from pipelines.models.artifacts import Artifact -from pipelines.models.secrets import Secret -from pipelines.models.steps import STEP_PARAMS, MountPath, Step, StepResult, StepStatus - -GITHUB_URL_PREFIX_FOR_CONNECTORS = f"{AIRBYTE_GITHUBUSERCONTENT_URL_PREFIX}/master/airbyte-integrations/connectors" - - -class VersionCheck(Step, ABC): - """A step to validate the connector version was bumped if files were modified""" - - context: ConnectorContext - - @property - def should_run(self) -> bool: - return True - - @property - def github_master_metadata_url(self) -> str: - return f"{GITHUB_URL_PREFIX_FOR_CONNECTORS}/{self.context.connector.technical_name}/{METADATA_FILE_NAME}" - - @cached_property - def master_metadata(self) -> Optional[dict]: - response = requests.get(self.github_master_metadata_url) - - # New connectors will not have a metadata file in master - if not response.ok: - return None - return yaml.safe_load(response.text) - - @property - def master_connector_version(self) -> semver.Version: - metadata = self.master_metadata - if not metadata: - return semver.Version.parse("0.0.0") - - return semver.Version.parse(str(metadata["data"]["dockerImageTag"])) - - @property - def current_connector_version(self) -> semver.Version: - return semver.Version.parse(str(self.context.metadata["dockerImageTag"])) - - @property - def success_result(self) -> StepResult: - return StepResult(step=self, status=StepStatus.SUCCESS) - - def _get_failure_result(self, failure_message: str) -> StepResult: - return StepResult(step=self, status=StepStatus.FAILURE, stderr=failure_message) - - @abstractmethod - def validate(self) -> StepResult: - raise NotImplementedError() - - async def _run(self) -> StepResult: - if not self.should_run: - return StepResult(step=self, status=StepStatus.SKIPPED, stdout="No modified files required a version bump.") - if self.context.ci_context == CIContext.MASTER: - return StepResult(step=self, status=StepStatus.SKIPPED, stdout="Version check are not running in master context.") - try: - return self.validate() - except (requests.HTTPError, ValueError, TypeError) as e: - return StepResult(step=self, status=StepStatus.FAILURE, stderr=str(e)) - - -class VersionIncrementCheck(VersionCheck): - context: ConnectorContext - title = "Connector version increment check" - - BYPASS_CHECK_FOR = [ - METADATA_FILE_NAME, - "acceptance-test-config.yml", - "README.md", - "bootstrap.md", - ".dockerignore", - "unit_tests", - "integration_tests", - "src/test", - "src/test-integration", - "src/test-performance", - "build.gradle", - "erd", - "build_customization.py", - ] - - @property - def should_run(self) -> bool: - # Skip if connector opts out of version checks - if self.context.metadata and self.context.metadata.get("ab_internal", {}).get("requireVersionIncrementsInPullRequests") is False: - return False - - for filename in self.context.modified_files: - relative_path = str(filename).replace(str(self.context.connector.code_directory) + "/", "") - if not any([relative_path.startswith(to_bypass) for to_bypass in self.BYPASS_CHECK_FOR]): - return True - return False - - def is_version_not_incremented(self) -> bool: - return self.master_connector_version >= self.current_connector_version - - def get_failure_message_for_no_increment(self) -> str: - return ( - f"The dockerImageTag in {METADATA_FILE_NAME} was not incremented. " - f"Master version is {self.master_connector_version}, current version is {self.current_connector_version}" - ) - - def are_both_versions_release_candidates(self) -> bool: - return bool( - self.master_connector_version.prerelease - and self.current_connector_version.prerelease - and "rc" in self.master_connector_version.prerelease - and "rc" in self.current_connector_version.prerelease - ) - - def have_same_major_minor_patch(self) -> bool: - return ( - self.master_connector_version.major == self.current_connector_version.major - and self.master_connector_version.minor == self.current_connector_version.minor - and self.master_connector_version.patch == self.current_connector_version.patch - ) - - @staticmethod - def _get_registry_override_tag(metadata: Optional[dict], channel: str) -> Optional[str]: - """Extract the dockerImageTag from registryOverrides for a given channel. - - Args: - metadata: The metadata dictionary (master or current). - channel: The channel to extract from ("cloud" or "oss"). - - Returns: - The dockerImageTag value if present, None otherwise. - """ - if metadata is None: - return None - try: - return metadata.get("data", {}).get("registryOverrides", {}).get(channel, {}).get("dockerImageTag") - except (TypeError, AttributeError): - return None - - def _has_registry_override_docker_tag_change(self) -> bool: - """Check if registryOverrides.cloud.dockerImageTag or registryOverrides.oss.dockerImageTag has changed. - - Returns: - bool: True if either cloud or oss dockerImageTag has been added, removed, or changed. - """ - master_cloud = self._get_registry_override_tag(self.master_metadata, "cloud") - current_cloud = self._get_registry_override_tag(self.context.metadata, "cloud") - - master_oss = self._get_registry_override_tag(self.master_metadata, "oss") - current_oss = self._get_registry_override_tag(self.context.metadata, "oss") - - return (master_cloud != current_cloud) or (master_oss != current_oss) - - def validate(self) -> StepResult: - if self.is_version_not_incremented(): - # Allow version to stay the same if registryOverrides.cloud.dockerImageTag or - # registryOverrides.oss.dockerImageTag has been added, removed, or changed - if self._has_registry_override_docker_tag_change(): - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stdout=( - f"The current change is modifying the registryOverrides pinned version on Cloud or OSS. Skipping this check " - f"because the defined version {self.current_connector_version} is allowed to be unchanged" - ), - ) - return self._get_failure_result( - ( - f"The dockerImageTag in {METADATA_FILE_NAME} was not incremented. " - f"Master version is {self.master_connector_version}, current version is {self.current_connector_version}" - ) - ) - - if self.are_both_versions_release_candidates(): - if not self.have_same_major_minor_patch(): - return self._get_failure_result( - ( - f"Master and current version are release candidates but they have different major, minor or patch versions. " - f"Release candidates should only differ in the prerelease part. Master version is {self.master_connector_version}, " - f"current version is {self.current_connector_version}" - ) - ) - - return self.success_result - - -class AcceptanceTests(Step): - """A step to run acceptance tests for a connector if it has an acceptance test config file.""" - - context: ConnectorContext - title = "Acceptance tests" - CONTAINER_TEST_INPUT_DIRECTORY = "/test_input" - CONTAINER_SECRETS_DIRECTORY = "/test_input/secrets" - REPORT_LOG_PATH = "/tmp/report_log.jsonl" - skipped_exit_code = 5 - accept_extra_params = True - - @property - def default_params(self) -> STEP_PARAMS: - """Default pytest options. - - Returns: - dict: The default pytest options. - """ - return super().default_params | { - "-ra": [], # Show extra test summary info in the report for all but the passed tests - "--disable-warnings": [], # Disable warnings in the pytest report - "--durations": ["3"], # Show the 3 slowest tests in the report - } - - @property - def base_cat_command(self) -> List[str]: - command = [ - "python", - "-m", - "pytest", - # Write the test report in jsonl format - f"--report-log={self.REPORT_LOG_PATH}", - "-p", # Load the connector_acceptance_test plugin - "connector_acceptance_test.plugin", - "--acceptance-test-config", - self.CONTAINER_TEST_INPUT_DIRECTORY, - ] - - if self.concurrent_test_run: - command += ["--numprocesses=auto"] # Using pytest-xdist to run tests in parallel, auto means using all available cores - return command - - def __init__(self, context: ConnectorContext, secrets: List[Secret], concurrent_test_run: Optional[bool] = False) -> None: - """Create a step to run acceptance tests for a connector if it has an acceptance test config file. - - Args: - context (ConnectorContext): The current test context, providing a connector object, a dagger client and a repository directory. - secrets (List[Secret]): List of secrets to mount to the connector container under test. - concurrent_test_run (Optional[bool], optional): Whether to run acceptance tests in parallel. Defaults to False. - """ - super().__init__(context, secrets) - self.concurrent_test_run = concurrent_test_run - - async def get_cat_command(self, connector_dir: Directory) -> List[str]: - """ - Connectors can optionally setup or teardown resources before and after the acceptance tests are run. - This is done via the acceptance.py file in their integration_tests directory. - We append this module as a plugin the acceptance will use. - """ - cat_command = self.base_cat_command - if "integration_tests" in await connector_dir.entries(): - if "acceptance.py" in await connector_dir.directory("integration_tests").entries(): - cat_command += ["-p", "integration_tests.acceptance"] - return cat_command + self.params_as_cli_options - - async def _run(self, connector_under_test_container: Container) -> StepResult: - """Run the acceptance test suite on a connector dev image. Build the connector acceptance test image if the tag is :dev. - - Args: - connector_under_test_container (Container): The container holding the connector under test image. - - Returns: - StepResult: Failure or success of the acceptances tests with stdout and stderr. - """ - - if not self.context.connector.acceptance_test_config: - return StepResult(step=self, status=StepStatus.SKIPPED) - connector_dir = await self.context.get_connector_dir() - cat_container = await self._build_connector_acceptance_test(connector_under_test_container, connector_dir) - cat_command = await self.get_cat_command(connector_dir) - cat_container = cat_container.with_(hacks.never_fail_exec(cat_command)) - step_result = await self.get_step_result(cat_container) - secret_dir = cat_container.directory(self.CONTAINER_SECRETS_DIRECTORY) - - if secret_files := await secret_dir.entries(): - for file_path in secret_files: - if file_path.startswith("updated_configurations"): - self.context.updated_secrets_dir = secret_dir - break - return step_result - - def get_cache_buster(self) -> str: - """ - This bursts the CAT cached results everyday and on new version or image size change. - It's cool because in case of a partially failing nightly build the connectors that already ran CAT won't re-run CAT. - We keep the guarantee that a CAT runs everyday. - - Returns: - str: A string representing the cachebuster value. - """ - return datetime.datetime.utcnow().strftime("%Y%m%d") + self.context.connector.version - - async def _build_connector_acceptance_test(self, connector_under_test_container: Container, test_input: Directory) -> Container: - """Create a container to run connector acceptance tests. - - Args: - connector_under_test_container (Container): The container holding the connector under test image. - test_input (Directory): The connector under test directory. - Returns: - Container: A container with connector acceptance tests installed. - """ - - if self.context.connector_acceptance_test_image.endswith(":dev"): - cat_container = self.context.connector_acceptance_test_source_dir.docker_build() - else: - cat_container = self.dagger_client.container().from_(self.context.connector_acceptance_test_image) - - connector_container_id = await connector_under_test_container.id() - cat_container = ( - cat_container.with_env_variable("RUN_IN_AIRBYTE_CI", "1") - .with_exec(["mkdir", "/dagger_share"]) - .with_env_variable("CACHEBUSTER", self.get_cache_buster()) - .with_new_file("/tmp/container_id.txt", contents=str(connector_container_id)) - .with_workdir("/test_input") - .with_mounted_directory("/test_input", test_input) - .with_(await secrets.mounted_connector_secrets(self.context, self.CONTAINER_SECRETS_DIRECTORY, self.secrets)) - ) - if "_EXPERIMENTAL_DAGGER_RUNNER_HOST" in os.environ: - self.context.logger.info("Using experimental dagger runner host to run CAT with dagger-in-dagger") - cat_container = cat_container.with_env_variable( - "_EXPERIMENTAL_DAGGER_RUNNER_HOST", "unix:///var/run/buildkit/buildkitd.sock" - ).with_unix_socket( - "/var/run/buildkit/buildkitd.sock", self.context.dagger_client.host().unix_socket("/var/run/buildkit/buildkitd.sock") - ) - - return cat_container.with_unix_socket("/var/run/docker.sock", self.context.dagger_client.host().unix_socket("/var/run/docker.sock")) - - def get_is_hard_failure(self) -> bool: - """When a connector is not certified or the CI context is master, we consider the acceptance tests as hard failures: - The overall status of the pipeline will be FAILURE if the acceptance tests fail. - For marketplace connectors we defer to the IncrementalAcceptanceTests step to determine if the acceptance tests are hard failures: - If a new test is failing compared to the released version of the connector. - - Returns: - bool: Whether a failure of acceptance tests should be considered a hard failures. - """ - return self.context.connector.metadata.get("supportLevel") == "certified" or self.context.ci_context == CIContext.MASTER - - async def get_step_result(self, container: Container) -> StepResult: - """Retrieve stdout, stderr and exit code from the executed CAT container. - Pull the report logs from the container and create an Artifact object from it. - Build and return a step result object from these objects. - - Args: - container (Container): The CAT container to get the results from. - - Returns: - StepResult: The step result object. - """ - exit_code, stdout, stderr = await get_exec_result(container) - report_log_artifact = Artifact( - name="cat_report_log.jsonl", - content_type="text/jsonl", - content=container.file(self.REPORT_LOG_PATH), - to_upload=True, - ) - status = self.get_step_status_from_exit_code(exit_code) - - is_hard_failure = status is StepStatus.FAILURE and self.get_is_hard_failure() - - return StepResult( - step=self, - status=self.get_step_status_from_exit_code(exit_code), - stderr=stderr, - stdout=stdout, - output={"report_log": report_log_artifact}, - artifacts=[report_log_artifact], - consider_in_overall_status=status is StepStatus.SUCCESS or is_hard_failure, - ) - - -class IncrementalAcceptanceTests(Step): - """This step runs the acceptance tests on the released image of the connector and compares the results with the current acceptance tests report log. - It fails if there are new failing tests in the current acceptance tests report log. - """ - - title = "Incremental Acceptance Tests" - context: ConnectorContext - - async def get_failed_pytest_node_ids(self, current_acceptance_tests_report_log: Artifact) -> Set[str]: - """Parse the report log of the acceptance tests and return the pytest node ids of the failed tests. - - Args: - current_acceptance_tests_report_log (Artifact): The report log of the acceptance tests. - - Returns: - List[str]: The pytest node ids of the failed tests. - """ - current_report_lines = (await current_acceptance_tests_report_log.content.contents()).splitlines() - failed_nodes = set() - for line in current_report_lines: - single_test_report = json.loads(line) - if "nodeid" not in single_test_report or "outcome" not in single_test_report: - continue - if single_test_report["outcome"] == "failed": - failed_nodes.add(single_test_report["nodeid"]) - return failed_nodes - - def _get_master_metadata(self) -> Dict[str, Any]: - metadata_response = requests.get(f"{GITHUB_URL_PREFIX_FOR_CONNECTORS}/{self.context.connector.technical_name}/metadata.yaml") - if not metadata_response.ok: - raise FileNotFoundError(f"Could not fetch metadata file for {self.context.connector.technical_name} on master.") - return yaml.safe_load(metadata_response.text) - - async def get_result_log_on_master(self, master_metadata: dict) -> Artifact: - """Runs acceptance test on the released image of the connector and returns the report log. - The released image version is fetched from the master metadata file of the connector. - We're not using the online connector registry here as some connectors might not be released to OSS nor Airbyte Cloud. - Thanks to Dagger caching subsequent runs of this step will be cached if the released image did not change. - - Returns: - Artifact: The report log of the acceptance tests run on the released image. - """ - master_docker_image_tag = master_metadata["data"]["dockerImageTag"] - released_image = f'{master_metadata["data"]["dockerRepository"]}:{master_docker_image_tag}' - released_container = self.dagger_client.container().from_(released_image) - self.logger.info(f"Running acceptance tests on released image: {released_image}") - acceptance_tests_results_on_master = await AcceptanceTests(self.context, self.secrets).run(released_container) - return acceptance_tests_results_on_master.output["report_log"] - - async def _run(self, current_acceptance_tests_result: StepResult) -> StepResult: - """Compare the acceptance tests report log of the current image with the one of the released image. - Fails if there are new failing tests in the current acceptance tests report log. - """ - - if current_acceptance_tests_result.consider_in_overall_status: - return StepResult( - step=self, status=StepStatus.SKIPPED, stdout="Skipping because the current acceptance tests are hard failures." - ) - - current_acceptance_tests_report_log = current_acceptance_tests_result.output["report_log"] - current_failing_nodes = await self.get_failed_pytest_node_ids(current_acceptance_tests_report_log) - if not current_failing_nodes: - return StepResult( - step=self, status=StepStatus.SKIPPED, stdout="No failing acceptance tests were detected on the current version." - ) - try: - master_metadata = self._get_master_metadata() - except FileNotFoundError as exc: - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stdout="The connector does not have a metadata file on master. Skipping incremental acceptance tests.", - exc_info=exc, - ) - - master_result_logs = await self.get_result_log_on_master(master_metadata) - - master_failings = await self.get_failed_pytest_node_ids(master_result_logs) - new_failing_nodes = current_failing_nodes - master_failings - if not new_failing_nodes: - return StepResult( - step=self, - status=StepStatus.SUCCESS, - stdout=dedent( - f""" - No new failing acceptance tests were detected. - Acceptance tests are still failing with {len(current_failing_nodes)} failing tests but the AcceptanceTests step is not a hard failure for this connector. - Please checkout the original acceptance tests failures and assess how critical they are. - """ - ), - ) - else: - return StepResult( - step=self, - status=StepStatus.FAILURE, - stdout=f"{len(new_failing_nodes)} new failing acceptance tests detected:\n-" - + "\n-".join(current_failing_nodes) - + "\nPlease fix the new failing tests before merging this PR." - + f"\nPlease also check the original {len(current_failing_nodes)} acceptance tests failures and assess how critical they are.", - ) - - -class LiveTestSuite(Enum): - ALL = "live" - REGRESSION = "regression" - VALIDATION = "validation" - - -class LiveTests(Step): - """A step to run live tests for a connector.""" - - context: ConnectorContext - skipped_exit_code = 5 - accept_extra_params = True - local_tests_artifacts_dir = Path("/tmp/live_tests_artifacts") - working_directory = "/app" - github_user = "octavia-squidington-iii" - platform_repo_url = "airbytehq/airbyte-platform-internal" - test_suite_to_dir = { - LiveTestSuite.ALL: "src/live_tests", - LiveTestSuite.REGRESSION: "src/live_tests/regression_tests", - LiveTestSuite.VALIDATION: "src/live_tests/validation_tests", - } - - @property - def default_params(self) -> STEP_PARAMS: - """Default pytest options. - - Returns: - dict: The default pytest options. - """ - return super().default_params | { - "-ra": [], # Show extra test summary info in the report for all but the passed tests - "--disable-warnings": [], # Disable warnings in the pytest report - "--durations": ["3"], # Show the 3 slowest tests in the report - } - - @property - def title(self) -> str: - return f"Connector {self.test_suite.title()} Tests" - - def _test_command(self) -> List[str]: - """ - The command used to run the tests - """ - base_command = [ - "poetry", - "run", - "pytest", - self.test_dir, - "--connector-image", - self.connector_image, - ] - return base_command + self._get_command_options() - - def _get_command_options(self) -> List[str]: - command_options = [] - if self.connection_id: - command_options += ["--connection-id", self.connection_id] - if self.control_version: - command_options += ["--control-version", self.control_version] - if self.target_version: - command_options += ["--target-version", self.target_version] - if self.pr_url: - command_options += ["--pr-url", self.pr_url] - if self.run_id: - command_options += ["--run-id", self.run_id] - if self.should_read_with_state: - command_options += ["--should-read-with-state=1"] - if self.disable_proxy: - command_options += ["--disable-proxy=1"] - if self.test_evaluation_mode: - command_options += ["--test-evaluation-mode", self.test_evaluation_mode] - if self.selected_streams: - command_options += ["--stream", self.selected_streams] - command_options += ["--connection-subset", self.connection_subset] - return command_options - - def _run_command_with_proxy(self, command: str) -> List[str]: - """ - This command: - - 1. Starts a Google Cloud SQL proxy running on localhost, which is used by the connection-retriever to connect to postgres. - This is required for secure access to our internal tools. - 2. Gets the PID of the proxy so it can be killed once done. - 3. Runs the command that was passed in as input. - 4. Kills the proxy, and waits for it to exit. - 5. Exits with the command's exit code. - We need to explicitly kill the proxy in order to allow the GitHub Action to exit. - An alternative that we can consider is to run the proxy as a separate service. - - (See https://docs.dagger.io/manuals/developer/python/328492/services/ and https://cloud.google.com/sql/docs/postgres/sql-proxy#cloud-sql-auth-proxy-docker-image) - """ - run_proxy = "./cloud-sql-proxy prod-ab-cloud-proj:us-west3:prod-pgsql-replica --credentials-file /tmp/credentials.json" - run_pytest_with_proxy = dedent( - f""" - {run_proxy} & - proxy_pid=$! - {command} - pytest_exit=$? - kill $proxy_pid - wait $proxy_pid - exit $pytest_exit - """ - ) - return ["bash", "-c", f"'{run_pytest_with_proxy}'"] - - def __init__(self, context: ConnectorContext) -> None: - """Create a step to run live tests for a connector. - - Args: - context (ConnectorContext): The current test context, providing a connector object, a dagger client and a repository directory. - """ - super().__init__(context) - self.connector_image = context.docker_image.split(":")[0] - options = self.context.run_step_options.step_params.get(CONNECTOR_TEST_STEP_ID.CONNECTOR_LIVE_TESTS, {}) - - self.test_suite = self.context.run_step_options.get_item_or_default(options, "test-suite", LiveTestSuite.REGRESSION.value) - self.connection_id = self._get_connection_id(options) - self.pr_url = self._get_pr_url(options) - - self.test_dir = self.test_suite_to_dir[LiveTestSuite(self.test_suite)] - self.control_version = self.context.run_step_options.get_item_or_default(options, "control-version", None) - self.target_version = self.context.run_step_options.get_item_or_default(options, "target-version", "dev") - self.should_read_with_state = "should-read-with-state" in options - self.disable_proxy = "disable-proxy" in options - self.selected_streams = self.context.run_step_options.get_item_or_default(options, "selected-streams", None) - self.test_evaluation_mode = "strict" if self.context.connector.metadata.get("supportLevel") == "certified" else "diagnostic" - self.connection_subset = self.context.run_step_options.get_item_or_default(options, "connection-subset", "sandboxes") - self.run_id = os.getenv("GITHUB_RUN_ID") or str(int(time.time())) - - def _get_connection_id(self, options: Dict[str, List[Any]]) -> Optional[str]: - if self.context.is_pr: - connection_id = self._get_connection_from_test_connections() - self.logger.info( - f"Context is {self.context.ci_context}; got connection_id={connection_id} from metadata.yaml liveTests testConnections." - ) - else: - connection_id = self.context.run_step_options.get_item_or_default(options, "connection-id", None) - self.logger.info(f"Context is {self.context.ci_context}; got connection_id={connection_id} from input options.") - return connection_id - - def _get_pr_url(self, options: Dict[str, List[Any]]) -> Optional[str]: - if self.context.is_pr: - pull_request = self.context.pull_request.url if self.context.pull_request else None - self.logger.info(f"Context is {self.context.ci_context}; got pull_request={pull_request} from context.") - else: - pull_request = self.context.run_step_options.get_item_or_default(options, "pr-url", None) - self.logger.info(f"Context is {self.context.ci_context}; got pull_request={pull_request} from input options.") - return pull_request - - def _validate_job_can_run(self) -> None: - connector_type = self.context.connector.metadata.get("connectorType") - connector_subtype = self.context.connector.metadata.get("connectorSubtype") - assert connector_type == "source", f"Live tests can only run against source connectors, got `connectorType={connector_type}`." - if connector_subtype == "database": - assert ( - self.connection_subset == "sandboxes" - ), f"Live tests for database sources may only be run against sandbox connections, got `connection_subset={self.connection_subset}`." - - assert self.connection_id, "`connection-id` is required to run live tests." - assert self.pr_url, "`pr_url` is required to run live tests." - - if self.context.is_pr: - connection_id_is_valid = False - for test_suite in self.context.connector.metadata.get("connectorTestSuitesOptions", []): - if test_suite["suite"] == "liveTests": - assert self.connection_id in [ - option["id"] for option in test_suite.get("testConnections", []) - ], f"Connection ID {self.connection_id} was not in the list of valid test connections." - connection_id_is_valid = True - break - assert connection_id_is_valid, f"Connection ID {self.connection_id} is not a valid sandbox connection ID." - - def _get_connection_from_test_connections(self) -> Optional[str]: - for test_suite in self.context.connector.metadata.get("connectorTestSuitesOptions", []): - if test_suite["suite"] == "liveTests": - for option in test_suite.get("testConnections", []): - connection_id = option["id"] - connection_name = option["name"] - self.logger.info(f"Using connection name={connection_name}; id={connection_id}") - return connection_id - return None - - async def _run(self, connector_under_test_container: Container) -> StepResult: - """Run the regression test suite. - - Args: - connector_under_test (Container): The container holding the target connector test image. - - Returns: - StepResult: Failure or success of the regression tests with stdout and stderr. - """ - try: - self._validate_job_can_run() - except AssertionError as exc: - self.logger.info(f"Skipping live tests for {self.context.connector.technical_name} due to validation error {str(exc)}.") - return StepResult( - step=self, - status=StepStatus.SKIPPED, - exc_info=exc, - ) - - container = await self._build_test_container(await connector_under_test_container.id()) - command = self._run_command_with_proxy(" ".join(self._test_command())) - main_logger.info(f"Running command {command}") - container = container.with_(hacks.never_fail_exec(command)) - tests_artifacts_dir = str(self.local_tests_artifacts_dir) - path_to_report = f"{tests_artifacts_dir}/session_{self.run_id}/report.html" - - exit_code, stdout, stderr = await get_exec_result(container) - - try: - if ( - f"session_{self.run_id}" not in await container.directory(f"{tests_artifacts_dir}").entries() - or "report.html" not in await container.directory(f"{tests_artifacts_dir}/session_{self.run_id}").entries() - ): - main_logger.exception( - "The report file was not generated, an unhandled error likely happened during regression test execution, please check the step stderr and stdout for more details" - ) - regression_test_report = None - else: - await container.file(path_to_report).export(path_to_report) - with open(path_to_report, "r") as fp: - regression_test_report = fp.read() - except dagger.QueryError as exc: - regression_test_report = None - main_logger.exception( - "The test artifacts directory was not generated, an unhandled error likely happened during setup, please check the step stderr and stdout for more details", - exc_info=exc, - ) - - return StepResult( - step=self, - status=self.get_step_status_from_exit_code(exit_code), - stderr=stderr, - stdout=stdout, - output=container, - report=regression_test_report, - consider_in_overall_status=False if self.context.is_pr else True, - ) - - async def _build_test_container(self, target_container_id: str) -> Container: - """Create a container to run regression tests.""" - container = with_poetry(self.context) - container_requirements = ["apt-get", "install", "-y", "git", "curl", "docker.io"] - if not self.context.is_ci: - # Outside of CI we use ssh to get the connection-retriever package from airbyte-platform-internal - container_requirements += ["openssh-client"] - container = ( - container.with_exec(["apt-get", "update"], use_entrypoint=True) - .with_exec(container_requirements) - .with_exec(["bash", "-c", "curl https://sdk.cloud.google.com | bash"], use_entrypoint=True) - .with_env_variable("PATH", "/root/google-cloud-sdk/bin:$PATH", expand=True) - .with_mounted_directory("/app", self.context.live_tests_dir) - .with_workdir("/app") - # Enable dagger-in-dagger - .with_unix_socket("/var/run/docker.sock", self.dagger_client.host().unix_socket("/var/run/docker.sock")) - .with_env_variable("RUN_IN_AIRBYTE_CI", "1") - .with_file( - "/tmp/record_obfuscator.py", - self.context.get_repo_dir("tools/bin", include=["record_obfuscator.py"]).file("record_obfuscator.py"), - ) - # The connector being tested is already built and is stored in a location accessible to an inner dagger kicked off by - # regression tests. The connector can be found if you know the container ID, so we write the container ID to a file and put - # it in the regression test container. This way regression tests will use the already-built connector instead of trying to - # build their own. - .with_new_file( - f"/tmp/{slugify(self.connector_image + ':' + self.target_version)}_container_id.txt", contents=str(target_container_id) - ) - ) - - if self.context.is_ci: - container = ( - container.with_exec( - [ - "sed", - "-i", - "-E", - rf"s,git@github\.com:{self.platform_repo_url},https://github.com/{self.platform_repo_url}.git,", - "pyproject.toml", - ], - use_entrypoint=True, - ) - .with_exec( - [ - "poetry", - "source", - "add", - "--priority=supplemental", - "airbyte-platform-internal-source", - "https://github.com/airbytehq/airbyte-platform-internal.git", - ], - use_entrypoint=True, - ) - .with_secret_variable( - "CI_GITHUB_ACCESS_TOKEN", - self.context.dagger_client.set_secret( - "CI_GITHUB_ACCESS_TOKEN", self.context.ci_github_access_token.value if self.context.ci_github_access_token else "" - ), - ) - .with_exec( - [ - "/bin/sh", - "-c", - f"poetry config http-basic.airbyte-platform-internal-source {self.github_user} $CI_GITHUB_ACCESS_TOKEN", - ], - use_entrypoint=True, - ) - # Add GCP credentials from the environment and point google to their location (also required for connection-retriever) - .with_new_file("/tmp/credentials.json", contents=os.getenv("GCP_INTEGRATION_TESTER_CREDENTIALS", "")) - .with_env_variable("GOOGLE_APPLICATION_CREDENTIALS", "/tmp/credentials.json") - .with_exec( - [ - "curl", - "-o", - "cloud-sql-proxy", - "https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.11.0/cloud-sql-proxy.linux.amd64", - ], - use_entrypoint=True, - ) - .with_exec(["chmod", "+x", "cloud-sql-proxy"], use_entrypoint=True) - .with_env_variable("CI", "1") - ) - - else: - container = ( - container.with_mounted_file("/root/.ssh/id_rsa", self.dagger_client.host().file(str(Path("~/.ssh/id_rsa").expanduser()))) - .with_mounted_file("/root/.ssh/known_hosts", self.dagger_client.host().file(str(Path("~/.ssh/known_hosts").expanduser()))) - .with_mounted_file( - "/root/.config/gcloud/application_default_credentials.json", - self.dagger_client.host().file(str(Path("~/.config/gcloud/application_default_credentials.json").expanduser())), - ) - ) - - container = container.with_exec(["poetry", "lock"], use_entrypoint=True).with_exec(["poetry", "install"], use_entrypoint=True) - return container diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/java_connectors.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/java_connectors.py deleted file mode 100644 index 5c5ea5dcbe4b..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/java_connectors.py +++ /dev/null @@ -1,142 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""This module groups steps made to run tests for a specific Java connector given a test context.""" - -from __future__ import annotations - -from typing import TYPE_CHECKING - -import anyio -from dagger import File, QueryError - -from pipelines.airbyte_ci.connectors.build_image.steps.common import LoadContainerToLocalDockerHost -from pipelines.airbyte_ci.connectors.build_image.steps.java_connectors import ( - BuildConnectorDistributionTar, - BuildConnectorImages, - dist_tar_directory_path, -) -from pipelines.airbyte_ci.connectors.build_image.steps.normalization import BuildOrPullNormalization -from pipelines.airbyte_ci.connectors.consts import CONNECTOR_TEST_STEP_ID -from pipelines.airbyte_ci.connectors.test.context import ConnectorTestContext -from pipelines.airbyte_ci.connectors.test.steps.common import AcceptanceTests -from pipelines.airbyte_ci.steps.gradle import GradleTask -from pipelines.consts import LOCAL_BUILD_PLATFORM -from pipelines.dagger.actions.system import docker -from pipelines.helpers.execution.run_steps import StepToRun -from pipelines.helpers.utils import export_container_to_tarball -from pipelines.models.steps import STEP_PARAMS, StepResult, StepStatus - -if TYPE_CHECKING: - from typing import Callable, Dict, List, Optional - - from pipelines.helpers.execution.run_steps import RESULTS_DICT, STEP_TREE - - -class IntegrationTests(GradleTask): - """A step to run integrations tests for Java connectors using the integrationTestJava Gradle task.""" - - title = "Java Connector Integration Tests" - gradle_task_name = "integrationTestJava" - mount_connector_secrets = True - bind_to_docker_host = True - with_test_artifacts = True - - @property - def default_params(self) -> STEP_PARAMS: - return super().default_params | { - # Exclude the assemble task to avoid a circular dependency on airbyte-ci. - # The integrationTestJava gradle task depends on assemble, which in turns - # depends on buildConnectorImage to build the connector's docker image. - # At this point, the docker image has already been built. - "-x": ["assemble"], - } - - -class UnitTests(GradleTask): - """A step to run unit tests for Java connectors.""" - - title = "Java Connector Unit Tests" - gradle_task_name = "test" - bind_to_docker_host = True - with_test_artifacts = True - - -def _get_normalization_steps(context: ConnectorTestContext) -> List[StepToRun]: - normalization_image = f"{context.connector.normalization_repository}:dev" - context.logger.info(f"This connector supports normalization: will build {normalization_image}.") - normalization_steps = [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.BUILD_NORMALIZATION, - step=BuildOrPullNormalization(context, normalization_image, LOCAL_BUILD_PLATFORM), - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ) - ] - - return normalization_steps - - -def _get_acceptance_test_steps(context: ConnectorTestContext) -> List[StepToRun]: - """ - Generate the steps to run the acceptance tests for a Java connector. - """ - - # Run tests in parallel - return [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.INTEGRATION, - step=IntegrationTests(context, secrets=context.get_secrets_for_step_id(CONNECTOR_TEST_STEP_ID.INTEGRATION)), - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ), - StepToRun( - id=CONNECTOR_TEST_STEP_ID.ACCEPTANCE, - step=AcceptanceTests( - context, secrets=context.get_secrets_for_step_id(CONNECTOR_TEST_STEP_ID.ACCEPTANCE), concurrent_test_run=False - ), - args=lambda results: {"connector_under_test_container": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ), - ] - - -def get_test_steps(context: ConnectorTestContext) -> STEP_TREE: - """ - Get all the tests steps for a Java connector. - """ - - steps: STEP_TREE = [ - [StepToRun(id=CONNECTOR_TEST_STEP_ID.BUILD_TAR, step=BuildConnectorDistributionTar(context))], - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.UNIT, - step=UnitTests(context, secrets=context.get_secrets_for_step_id(CONNECTOR_TEST_STEP_ID.UNIT)), - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD_TAR], - ) - ], - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.BUILD, - step=BuildConnectorImages(context), - args=lambda results: {"dist_dir": results[CONNECTOR_TEST_STEP_ID.BUILD_TAR].output.directory("build/distributions")}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD_TAR], - ) - ], - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.LOAD_IMAGE_TO_LOCAL_DOCKER_HOST, - step=LoadContainerToLocalDockerHost(context, image_tag="dev"), - args=lambda results: {"containers": results[CONNECTOR_TEST_STEP_ID.BUILD].output}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ), - ], - ] - - if context.connector.supports_normalization: - normalization_steps = _get_normalization_steps(context) - steps.append(normalization_steps) - - acceptance_test_steps = _get_acceptance_test_steps(context) - steps.append(acceptance_test_steps) - - return steps diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/manifest_only_connectors.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/manifest_only_connectors.py deleted file mode 100644 index 5c7aa88ced54..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/manifest_only_connectors.py +++ /dev/null @@ -1,172 +0,0 @@ -# -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. -# - -"""This module groups steps made to run tests for a specific manifest only connector given a test context.""" - -from typing import List, Sequence, Tuple - -from dagger import Container, File - -from pipelines.airbyte_ci.connectors.build_image.steps.manifest_only_connectors import BuildConnectorImages -from pipelines.airbyte_ci.connectors.consts import CONNECTOR_TEST_STEP_ID -from pipelines.airbyte_ci.connectors.test.context import ConnectorTestContext -from pipelines.airbyte_ci.connectors.test.steps.common import AcceptanceTests, IncrementalAcceptanceTests, LiveTests -from pipelines.airbyte_ci.connectors.test.steps.python_connectors import PytestStep -from pipelines.consts import LOCAL_BUILD_PLATFORM -from pipelines.dagger.actions import secrets -from pipelines.helpers.execution.run_steps import STEP_TREE, StepToRun - - -def get_test_steps(context: ConnectorTestContext) -> STEP_TREE: - """ - Get all the tests steps for a Python connector. - """ - - return [ - [StepToRun(id=CONNECTOR_TEST_STEP_ID.BUILD, step=BuildConnectorImages(context))], - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.UNIT, - step=ManifestOnlyConnectorUnitTests(context), - args=lambda results: {"connector_under_test": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ), - StepToRun( - id=CONNECTOR_TEST_STEP_ID.ACCEPTANCE, - step=AcceptanceTests( - context, - concurrent_test_run=context.concurrent_cat, - secrets=context.get_secrets_for_step_id(CONNECTOR_TEST_STEP_ID.ACCEPTANCE), - ), - args=lambda results: {"connector_under_test_container": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ), - StepToRun( - id=CONNECTOR_TEST_STEP_ID.CONNECTOR_LIVE_TESTS, - step=LiveTests(context), - args=lambda results: {"connector_under_test_container": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ), - ], - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.INCREMENTAL_ACCEPTANCE, - step=IncrementalAcceptanceTests(context, secrets=context.get_secrets_for_step_id(CONNECTOR_TEST_STEP_ID.ACCEPTANCE)), - args=lambda results: {"current_acceptance_tests_result": results[CONNECTOR_TEST_STEP_ID.ACCEPTANCE]}, - depends_on=[CONNECTOR_TEST_STEP_ID.ACCEPTANCE], - ) - ], - ] - - -class ManifestOnlyConnectorUnitTests(PytestStep): - """A step to run unit tests for a manifest-only connector""" - - title = "Manifest-only unit tests" - test_directory_name = "unit_tests" - common_test_dependencies = ["freezegun", "pytest", "pytest-mock", "requests-mock"] - - async def install_testing_environment( - self, - built_connector_container: Container, - test_config_file_name: str, - test_config_file: File, - extra_dependencies_names: Sequence[str], - ) -> Container: - """Install the testing environment for manifest-only connectors.""" - - connector_name = self.context.connector.technical_name - # Use a simpler path structure to match what the CDK expects - test_dir = "/tmp/test_environment" - connector_base_path = f"{test_dir}/airbyte-integrations/connectors" - connector_path = f"{connector_base_path}/{connector_name}" - - # Get the proper user from the container - user = await built_connector_container.user() - if not user: - user = "root" - - # Set up base test environment with reset entrypoint - test_environment = built_connector_container.with_entrypoint([]) - - # Create test directories with proper permissions - test_environment = ( - test_environment.with_user("root") # Temporarily switch to root to create directories - .with_exec(["mkdir", "-p", test_dir, connector_base_path, connector_path, f"{connector_path}/{self.test_directory_name}"]) - .with_workdir(test_dir) - ) - - # Mount the connector directory and files - connector_dir = await self.context.get_connector_dir() - - # Check what files are in the connector directory to identify components.py - connector_entries = await connector_dir.entries() - self.logger.info(f"Files in connector directory: {connector_entries}") - - # Mount the entire connector directory to ensure all files (especially components.py) are available - test_environment = test_environment.with_mounted_directory(connector_path, connector_dir) - - # Get and mount the unit_tests directory specifically - unit_tests_dir = connector_dir.directory(self.test_directory_name) - unit_tests_path = f"{connector_path}/{self.test_directory_name}" - - # Mount secrets - secret_mounting_function = await secrets.mounted_connector_secrets(self.context, f"{test_dir}/secrets", self.secrets, owner=user) - - # Apply secrets and set up Python path - test_environment = test_environment.with_(secret_mounting_function).with_env_variable( - "PYTHONPATH", f"{connector_base_path}:{connector_path}:{unit_tests_path}:{test_dir}" - ) - - # Create symlink to source-declarative-manifest - test_environment = test_environment.with_exec(["ln", "-s", "/source-declarative-manifest", connector_path]) - - # Set working directory to unit tests path - test_environment = test_environment.with_workdir(unit_tests_path) - - # Install Poetry - test_environment = test_environment.with_exec(["echo", "=== INSTALLING POETRY ==="]).with_exec(["pip", "install", "poetry"]) - - # Install dependencies directly with Poetry - test_environment = test_environment.with_exec( - ["poetry", "config", "virtualenvs.create", "false"] # Disable virtualenv creation - ).with_exec( - ["poetry", "install", "--no-root"] # Install dependencies without the root package - ) - - # Install common test dependencies. This shouldn't be needed as we're now - # using the connector's pyproject.toml, but it's here to support MO connectors - # that might have dependencies not listed in the pyproject.toml. - if self.common_test_dependencies: - test_environment = test_environment.with_exec(["echo", "=== INSTALLING COMMON TEST DEPENDENCIES ==="]).with_exec( - ["pip", "install"] + self.common_test_dependencies - ) - - # Set ownership of all files to the proper user and switch to that user - test_environment = test_environment.with_exec(["chown", "-R", f"{user}:{user}", test_dir]).with_user(user) - - return test_environment - - async def get_config_file_name_and_file(self) -> Tuple[str, File]: - """ - Get the config file name and file to use for pytest. - For manifest-only connectors, we expect the poetry config to be found - in the unit_tests directory. - """ - connector_name = self.context.connector.technical_name - connector_dir = await self.context.get_connector_dir() - unit_tests_dir = connector_dir.directory(self.test_directory_name) - unit_tests_entries = await unit_tests_dir.entries() - if self.PYPROJECT_FILE_NAME in unit_tests_entries: - config_file_name = self.PYPROJECT_FILE_NAME - test_config = unit_tests_dir.file(self.PYPROJECT_FILE_NAME) - self.logger.info(f"Found {self.PYPROJECT_FILE_NAME} in the unit_tests directory for {connector_name}, using it for testing.") - return config_file_name, test_config - else: - raise FileNotFoundError(f"Could not find {self.PYPROJECT_FILE_NAME} in the unit_tests directory for {connector_name}.") - - def get_pytest_command(self, test_config_file_name: str) -> List[str]: - """Get the pytest command to run.""" - cmd = ["pytest", "-v", ".", "-c", test_config_file_name] + self.params_as_cli_options - return ["poetry", "run"] + cmd diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/python_connectors.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/python_connectors.py deleted file mode 100644 index 5bb2f962f3c0..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/python_connectors.py +++ /dev/null @@ -1,326 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""This module groups steps made to run tests for a specific Python connector given a test context.""" - -from abc import ABC, abstractmethod -from typing import List, Sequence, Tuple - -import dpath.util -from dagger import Container, File - -import pipelines.dagger.actions.python.common -import pipelines.dagger.actions.system.docker -from pipelines import hacks -from pipelines.airbyte_ci.connectors.build_image.steps.python_connectors import BuildConnectorImages -from pipelines.airbyte_ci.connectors.consts import CONNECTOR_TEST_STEP_ID -from pipelines.airbyte_ci.connectors.test.context import ConnectorTestContext -from pipelines.airbyte_ci.connectors.test.steps.common import AcceptanceTests, IncrementalAcceptanceTests, LiveTests -from pipelines.consts import LOCAL_BUILD_PLATFORM -from pipelines.dagger.actions import secrets -from pipelines.dagger.actions.python.poetry import with_poetry -from pipelines.helpers.execution.run_steps import STEP_TREE, StepToRun -from pipelines.helpers.utils import raise_if_not_user -from pipelines.models.steps import STEP_PARAMS, Step, StepResult - -# Pin the PyAirbyte version to avoid updates from breaking CI -PYAIRBYTE_VERSION = "0.35.1" - - -class PytestStep(Step, ABC): - """An abstract class to run pytest tests and evaluate success or failure according to pytest logs.""" - - context: ConnectorTestContext - - PYTEST_INI_FILE_NAME = "pytest.ini" - PYPROJECT_FILE_NAME = "pyproject.toml" - common_test_dependencies: List[str] = [] - - skipped_exit_code = 5 - bind_to_docker_host = False - accept_extra_params = True - - @property - def default_params(self) -> STEP_PARAMS: - """Default pytest options. - - Returns: - dict: The default pytest options. - """ - return super().default_params | { - "-s": [], # Disable capturing stdout/stderr in pytest - } - - @property - @abstractmethod - def test_directory_name(self) -> str: - raise NotImplementedError("test_directory_name must be implemented in the child class.") - - @property - def extra_dependencies_names(self) -> Sequence[str]: - if self.context.connector.is_using_poetry: - return ("dev",) - return ("dev", "tests") - - async def _run(self, connector_under_test: Container) -> StepResult: - """Run all pytest tests declared in the test directory of the connector code. - - Args: - connector_under_test (Container): The connector under test container. - - Returns: - StepResult: Failure or success of the unit tests with stdout and stdout. - """ - if not await self.check_if_tests_are_available(self.test_directory_name): - return self.skip(f"No {self.test_directory_name} directory found in the connector.") - - test_config_file_name, test_config_file = await self.get_config_file_name_and_file() - test_environment = await self.install_testing_environment( - connector_under_test, test_config_file_name, test_config_file, self.extra_dependencies_names - ) - - pytest_command = self.get_pytest_command(test_config_file_name) - - if self.bind_to_docker_host: - test_environment = await pipelines.dagger.actions.system.docker.with_bound_docker_host(self.context, test_environment) - - test_execution = test_environment.with_exec(pytest_command) - - return await self.get_step_result(test_execution) - - def get_pytest_command(self, test_config_file_name: str) -> List[str]: - """Get the pytest command to run. - - Returns: - List[str]: The pytest command to run. - """ - cmd = ["pytest", self.test_directory_name, "-c", test_config_file_name] + self.params_as_cli_options - if self.context.connector.is_using_poetry: - return ["poetry", "run"] + cmd - return cmd - - async def check_if_tests_are_available(self, test_directory_name: str) -> bool: - """Check if the tests are available in the connector directory. - - Returns: - bool: True if the tests are available. - """ - connector_dir = await self.context.get_connector_dir() - connector_dir_entries = await connector_dir.entries() - return test_directory_name in connector_dir_entries - - async def get_config_file_name_and_file(self) -> Tuple[str, File]: - """Get the config file name and file to use for pytest. - - The order of priority is: - - pytest.ini file in the connector directory - - pyproject.toml file in the connector directory - - pyproject.toml file in the repository directory - - Returns: - Tuple[str, File]: The config file name and file to use for pytest. - """ - connector_dir = await self.context.get_connector_dir() - connector_dir_entries = await connector_dir.entries() - if self.PYTEST_INI_FILE_NAME in connector_dir_entries: - config_file_name = self.PYTEST_INI_FILE_NAME - test_config = (await self.context.get_connector_dir(include=[self.PYTEST_INI_FILE_NAME])).file(self.PYTEST_INI_FILE_NAME) - self.logger.info(f"Found {self.PYTEST_INI_FILE_NAME}, using it for testing.") - elif self.PYPROJECT_FILE_NAME in connector_dir_entries: - config_file_name = self.PYPROJECT_FILE_NAME - test_config = (await self.context.get_connector_dir(include=[self.PYPROJECT_FILE_NAME])).file(self.PYPROJECT_FILE_NAME) - self.logger.info(f"Found {self.PYPROJECT_FILE_NAME} at connector level, using it for testing.") - else: - config_file_name = f"global_{self.PYPROJECT_FILE_NAME}" - test_config = (await self.context.get_repo_dir(include=[self.PYPROJECT_FILE_NAME])).file(self.PYPROJECT_FILE_NAME) - self.logger.info(f"Found {self.PYPROJECT_FILE_NAME} at repo level, using it for testing.") - return config_file_name, test_config - - async def install_testing_environment( - self, - built_connector_container: Container, - test_config_file_name: str, - test_config_file: File, - extra_dependencies_names: Sequence[str], - ) -> Container: - """Install the connector with the extra dependencies in /test_environment. - - Args: - extra_dependencies_names (List[str]): Extra dependencies to install. - - Returns: - Container: The container with the test environment installed. - """ - user = await BuildConnectorImages.get_image_user(built_connector_container) - secret_mounting_function = await secrets.mounted_connector_secrets(self.context, "secrets", self.secrets, owner=user) - - container_with_test_deps = ( - # Install the connector python package in /test_environment with the extra dependencies - await pipelines.dagger.actions.python.common.with_python_connector_installed( - self.context, - # Reset the entrypoint to run non airbyte commands - built_connector_container.with_entrypoint([]), - str(self.context.connector.code_directory), - user, - additional_dependency_groups=extra_dependencies_names, - ) - ) - if self.common_test_dependencies: - container_with_test_deps = container_with_test_deps.with_user("root").with_exec( - ["pip", "install"] + self.common_test_dependencies - ) - - container_with_test_deps = ( - container_with_test_deps - # Mount the test config file - .with_mounted_file(test_config_file_name, test_config_file, owner=user) - # Mount the secrets - .with_(secret_mounting_function) - .with_env_variable("PYTHONPATH", ".") - # Make sure all files that were created or mounted under /airbyte are owned by the user - .with_user("root") - .with_exec(["chown", "-R", f"{user}:{user}", "/airbyte"]) - .with_user(user) - ) - - await raise_if_not_user(container_with_test_deps, user) - return container_with_test_deps - - -class UnitTests(PytestStep): - """A step to run the connector unit tests with Pytest.""" - - title = "Unit tests" - test_directory_name = "unit_tests" - - common_test_dependencies = ["pytest-cov==4.1.0"] - MINIMUM_COVERAGE_FOR_CERTIFIED_CONNECTORS = 90 - - @property - def default_params(self) -> STEP_PARAMS: - """Make sure the coverage computation is run for the unit tests. - - Returns: - dict: The default pytest options. - """ - coverage_options = {"--cov": [self.context.connector.technical_name.replace("-", "_")]} - if self.context.connector.support_level == "certified": - coverage_options["--cov-fail-under"] = [str(self.MINIMUM_COVERAGE_FOR_CERTIFIED_CONNECTORS)] - return super().default_params | coverage_options - - -class PyAirbyteValidation(Step): - """Validate the connector can be installed and invoked via Python, using PyAirbyte. - - When this fails, it generally signals that the connector is not installable or not - runnable in a Python environment. The most common reasons for this are: - 1. Conflicting dependencies. - 2. Missing dependency declarations. - 3. Incorrect or invalid CLI entrypoints. - """ - - title = "Python CLI smoke test using PyAirbyte" - - context: ConnectorTestContext - - async def _run(self, connector_under_test: Container) -> StepResult: - """Run all pytest tests declared in the test directory of the connector code. - Args: - connector_under_test (Container): The connector under test container. - Returns: - StepResult: Failure or success of the unit tests with stdout and stdout. - """ - if dpath.util.get(self.context.connector.metadata, "remoteRegistries/pypi/enabled", default=False) is False: - return self.skip("Connector is not flagged for PyPI publish, skipping Python CLI validation.") - - test_environment = await self.install_testing_environment(with_poetry(self.context)) - test_execution = test_environment.with_( - hacks.never_fail_exec( - [ - "pyab", - "validate", - f"--connector={self.context.connector.technical_name}", - "--pip-url='.'", - ] - ) - ) - - return await self.get_step_result(test_execution) - - async def install_testing_environment( - self, - built_connector_container: Container, - ) -> Container: - """Add PyAirbyte and secrets to the test environment.""" - context: ConnectorTestContext = self.context - - container_with_test_deps = await pipelines.dagger.actions.python.common.with_python_package( - self.context, built_connector_container.with_entrypoint([]), str(context.connector.code_directory) - ) - return container_with_test_deps.with_exec(["pip", "install", f"airbyte=={PYAIRBYTE_VERSION}"], use_entrypoint=True) - - -class IntegrationTests(PytestStep): - """A step to run the connector integration tests with Pytest.""" - - title = "Integration tests" - test_directory_name = "integration_tests" - - bind_to_docker_host = True - - -def get_test_steps(context: ConnectorTestContext) -> STEP_TREE: - """ - Get all the tests steps for a Python connector. - """ - - return [ - [StepToRun(id=CONNECTOR_TEST_STEP_ID.BUILD, step=BuildConnectorImages(context))], - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.UNIT, - step=UnitTests(context, secrets=context.get_secrets_for_step_id(CONNECTOR_TEST_STEP_ID.UNIT)), - args=lambda results: {"connector_under_test": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ) - ], - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.INTEGRATION, - step=IntegrationTests(context, secrets=context.get_secrets_for_step_id(CONNECTOR_TEST_STEP_ID.INTEGRATION)), - args=lambda results: {"connector_under_test": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ), - StepToRun( - id=CONNECTOR_TEST_STEP_ID.PYTHON_CLI_VALIDATION, - step=PyAirbyteValidation(context), - args=lambda results: {"connector_under_test": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ), - StepToRun( - id=CONNECTOR_TEST_STEP_ID.ACCEPTANCE, - step=AcceptanceTests( - context, - concurrent_test_run=context.concurrent_cat, - secrets=context.get_secrets_for_step_id(CONNECTOR_TEST_STEP_ID.ACCEPTANCE), - ), - args=lambda results: {"connector_under_test_container": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ), - StepToRun( - id=CONNECTOR_TEST_STEP_ID.CONNECTOR_LIVE_TESTS, - step=LiveTests(context), - args=lambda results: {"connector_under_test_container": results[CONNECTOR_TEST_STEP_ID.BUILD].output[LOCAL_BUILD_PLATFORM]}, - depends_on=[CONNECTOR_TEST_STEP_ID.BUILD], - ), - ], - [ - StepToRun( - id=CONNECTOR_TEST_STEP_ID.INCREMENTAL_ACCEPTANCE, - step=IncrementalAcceptanceTests(context, secrets=context.get_secrets_for_step_id(CONNECTOR_TEST_STEP_ID.ACCEPTANCE)), - args=lambda results: {"current_acceptance_tests_result": results[CONNECTOR_TEST_STEP_ID.ACCEPTANCE]}, - depends_on=[CONNECTOR_TEST_STEP_ID.ACCEPTANCE], - ) - ], - ] diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/templates/test_report.html.j2 b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/templates/test_report.html.j2 deleted file mode 100644 index ea732afba2eb..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/templates/test_report.html.j2 +++ /dev/null @@ -1,201 +0,0 @@ - - - - {{ connector_name }} test report - - - - - - -

{{ connector_name }} test report

-
    -
  • Created at: {{ created_at }} UTC
  • -
  • Run duration: {{ format_duration(run_duration) }}
  • - {% if commit_url %} -
  • Commit: {{ git_revision[:10] }}
  • - {% else %} -
  • Commit: {{ git_revision[:10] }}
  • - {% endif %} -
  • Branch: {{ git_branch }}
  • - {% if gha_workflow_run_url %} -
    -
  • Github Actions logs
  • - {% endif %} - {% if dagger_logs_url %} -
  • Dagger logs
  • - {% endif %} - {% if dagger_cloud_url %} -
  • Dagger Cloud UI
  • - {% endif %} -
-

Summary

- - - - - - - {% for step_result in step_results %} - - - - - - {% endfor %} -
StepStatusDuration
{{ step_result.step.title }}{{ step_result.status }}{{ format_duration(step_result.step.run_duration) }}
-

Step details

- {% for step_result in step_results %} -
- - {% if step_result.status == StepStatus.SUCCESS %} - - {% elif step_result.status == StepStatus.FAILURE %} - {% if not step_result.consider_in_overall_status %} - - {% else %} - - {% endif %} - {% else %} - - {% endif %} -
- {% if step_result_to_artifact_links[step_result.step.title] %} -

Artifacts

-
    - {% for artifact in step_result_to_artifact_links[step_result.step.title] %} -
  • {{ artifact.name }}
  • - {% endfor %} -
- {% endif %} -
- {% if step_result.report %} -
{{ step_result.report }}
- {% else %} - {% if step_result.stdout %} - Standard output(): -
{{ step_result.stdout|e }}
- {% endif %} - {% if step_result.stderr %} - Standard error(): -
{{ step_result.stderr|e }}
- {% endif %} - {% endif %} -
-
-
- {% endfor %} -

These reports are generated from this code, please reach out to the Connector Operations team for support.

- - diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/commands.py deleted file mode 100644 index 03111abf2ef1..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/commands.py +++ /dev/null @@ -1,76 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from typing import List - -import asyncclick as click - -from pipelines.airbyte_ci.connectors.up_to_date.pipeline import run_connector_up_to_date_pipeline -from pipelines.cli.dagger_pipeline_command import DaggerPipelineCommand -from pipelines.helpers.connectors.command import run_connector_pipeline - - -@click.command( - cls=DaggerPipelineCommand, - short_help="Get the selected connectors up to date.", -) -@click.option( - "--dep", - type=str, - multiple=True, - default=[], - help="Give a specific set of `poetry add` dependencies to update. For example: --dep airbyte-cdk==0.80.0 --dep pytest@^6.2", -) -@click.option( - "--create-prs", - is_flag=True, - type=bool, - default=False, - help="Create pull requests for updated connectors", -) -@click.option( - "--auto-merge", - is_flag=True, - type=bool, - default=False, - help="Set the auto-merge label on the create pull requests", -) -@click.option( - "--no-bump", - is_flag=True, - type=bool, - default=False, - help="Don't bump or changelog", -) -@click.option( - "--open-reports", - is_flag=True, - type=bool, - default=False, - help="Auto open reports in browser", -) -@click.pass_context -async def up_to_date( - ctx: click.Context, - dep: List[str], - create_prs: bool, - auto_merge: bool, - no_bump: bool, - open_reports: bool, -) -> bool: - if create_prs and not ctx.obj["ci_github_access_token"]: - raise click.ClickException( - "GitHub access token is required to create or simulate a pull request. Set the CI_GITHUB_ACCESS_TOKEN environment variable." - ) - - return await run_connector_pipeline( - ctx, - "Get Python connector up to date", - open_reports, - run_connector_up_to_date_pipeline, - create_prs, - auto_merge, - dep, - not no_bump, - ) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/pipeline.py deleted file mode 100644 index ec91373fb279..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/pipeline.py +++ /dev/null @@ -1,204 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -from datetime import datetime, timezone -from pathlib import Path -from typing import TYPE_CHECKING - -from jinja2 import Environment, PackageLoader, select_autoescape - -from pipelines import hacks -from pipelines.airbyte_ci.connectors.build_image.steps import run_connector_build -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.airbyte_ci.connectors.reports import ConnectorReport -from pipelines.airbyte_ci.steps.base_image import UpdateBaseImageMetadata -from pipelines.airbyte_ci.steps.bump_version import BumpConnectorVersion -from pipelines.airbyte_ci.steps.changelog import AddChangelogEntry -from pipelines.airbyte_ci.steps.pull_request import CreateOrUpdatePullRequest -from pipelines.consts import LOCAL_BUILD_PLATFORM - -from .steps import DependencyUpdate, GetDependencyUpdates, PoetryUpdate - -if TYPE_CHECKING: - from typing import Dict, Iterable, List, Set, Tuple - - from anyio import Semaphore - from github import PullRequest - - from pipelines.models.steps import StepResult - -UP_TO_DATE_PR_LABEL = "up-to-date" -AUTO_MERGE_PR_LABEL = "auto-merge" -DEFAULT_PR_LABELS = [UP_TO_DATE_PR_LABEL] -BUMP_TYPE = "patch" -CHANGELOG_ENTRY_COMMENT = "Update dependencies" - - -## HELPER FUNCTIONS - - -def get_pr_body(context: ConnectorContext, step_results: Iterable[StepResult], dependency_updates: Iterable[DependencyUpdate]) -> str: - env = Environment( - loader=PackageLoader("pipelines.airbyte_ci.connectors.up_to_date"), - autoescape=select_autoescape(), - trim_blocks=False, - lstrip_blocks=True, - ) - template = env.get_template("up_to_date_pr_body.md.j2") - latest_docker_image = f"{context.connector.metadata['dockerRepository']}:latest" - return template.render( - connector_technical_name=context.connector.technical_name, - step_results=step_results, - dependency_updates=dependency_updates, - connector_latest_docker_image=latest_docker_image, - ) - - -def get_pr_creation_arguments( - modified_files: Iterable[Path], - context: ConnectorContext, - step_results: Iterable[StepResult], - dependency_updates: Iterable[DependencyUpdate], -) -> Tuple[Tuple, Dict]: - return ( - (modified_files,), - { - "branch_id": f"up-to-date/{context.connector.technical_name}", - "commit_message": "[up-to-date]" # << We can skip Vercel builds if this is in the commit message - + "; ".join(step_result.step.title for step_result in step_results if step_result.success), - "pr_title": f"deps({context.connector.technical_name}): 🐙 update dependencies [{datetime.now(timezone.utc).strftime('%Y-%m-%d')}]", - "pr_body": get_pr_body(context, step_results, dependency_updates), - }, - ) - - -## MAIN FUNCTION -async def run_connector_up_to_date_pipeline( - context: ConnectorContext, - semaphore: "Semaphore", - create_pull_request: bool = False, - auto_merge: bool = False, - specific_dependencies: List[str] = [], - bump_connector_version: bool = True, -) -> ConnectorReport: - async with semaphore: - async with context: - step_results: List[StepResult] = [] - all_modified_files: Set[Path] = set() - created_pr: PullRequest.PullRequest | None = None - new_version: str | None = None - - connector_directory = await context.get_connector_dir() - upgrade_base_image_in_metadata = UpdateBaseImageMetadata(context, connector_directory) - upgrade_base_image_in_metadata_result = await upgrade_base_image_in_metadata.run() - step_results.append(upgrade_base_image_in_metadata_result) - if upgrade_base_image_in_metadata_result.success: - connector_directory = upgrade_base_image_in_metadata_result.output["updated_connector_directory"] - exported_modified_files = await upgrade_base_image_in_metadata.export_modified_files(context.connector.code_directory) - context.logger.info(f"Exported files following the base image upgrade: {exported_modified_files}") - all_modified_files.update(exported_modified_files) - - if context.connector.is_using_poetry: - # We run the poetry update step after the base image upgrade because the base image upgrade may change the python environment - poetry_update = PoetryUpdate(context, connector_directory, specific_dependencies=specific_dependencies) - poetry_update_result = await poetry_update.run() - step_results.append(poetry_update_result) - if poetry_update_result.success: - exported_modified_files = await poetry_update.export_modified_files(context.connector.code_directory) - context.logger.info(f"Exported files following the Poetry update: {exported_modified_files}") - all_modified_files.update(exported_modified_files) - connector_directory = poetry_update_result.output - - one_previous_step_is_successful = any(step_result.success for step_result in step_results) - - # NOTE: - # BumpConnectorVersion will already work for manifest-only and Java connectors too - if bump_connector_version and one_previous_step_is_successful: - bump_version = BumpConnectorVersion(context, connector_directory, BUMP_TYPE) - bump_version_result = await bump_version.run() - step_results.append(bump_version_result) - if bump_version_result.success: - new_version = bump_version.new_version - exported_modified_files = await bump_version.export_modified_files(context.connector.code_directory) - context.logger.info(f"Exported files following the version bump: {exported_modified_files}") - all_modified_files.update(exported_modified_files) - - # Only create the PR if the flag is on, and if there's anything to contribute - create_pull_request = create_pull_request and one_previous_step_is_successful and bump_version_result.success - - # We run build and get dependency updates only if we are creating a pull request, - # to fill the PR body with the correct information about what exactly got updated. - if create_pull_request: - # Building connector images is also universal across connector technologies. - build_result = await run_connector_build(context) - step_results.append(build_result) - dependency_updates: List[DependencyUpdate] = [] - - if build_result.success: - built_connector_container = build_result.output[LOCAL_BUILD_PLATFORM] - - # Dependencies here mean Syft deps in the container image itself, not framework-level deps. - get_dependency_updates = GetDependencyUpdates(context) - dependency_updates_result = await get_dependency_updates.run(built_connector_container) - step_results.append(dependency_updates_result) - dependency_updates = dependency_updates_result.output - - # We open a PR even if build is failing. - # This might allow a developer to fix the build in the PR. - initial_labels = DEFAULT_PR_LABELS + ([AUTO_MERGE_PR_LABEL] if auto_merge else []) - initial_pr_creation = CreateOrUpdatePullRequest( - context, - labels=initial_labels, - # Reduce pressure on rate limit, since we need to push a - # a follow-on commit anyway once we have the PR number: - skip_ci=True, - ) - pr_creation_args, pr_creation_kwargs = get_pr_creation_arguments( - all_modified_files, context, step_results, dependency_updates - ) - initial_pr_creation_result = await initial_pr_creation.run(*pr_creation_args, **pr_creation_kwargs) - step_results.append(initial_pr_creation_result) - if initial_pr_creation_result.success: - created_pr = initial_pr_creation_result.output - - if new_version and created_pr: - documentation_directory = await context.get_repo_dir( - include=[str(context.connector.local_connector_documentation_directory)] - ).directory(str(context.connector.local_connector_documentation_directory)) - - changelog_entry_comment = hacks.determine_changelog_entry_comment( - upgrade_base_image_in_metadata_result, CHANGELOG_ENTRY_COMMENT - ) - add_changelog_entry = AddChangelogEntry( - context, documentation_directory, new_version, changelog_entry_comment, created_pr.number - ) - add_changelog_entry_result = await add_changelog_entry.run() - step_results.append(add_changelog_entry_result) - if add_changelog_entry_result.success: - # File path modified by the changelog entry step are relative to the repo root - exported_modified_files = await add_changelog_entry.export_modified_files( - context.connector.local_connector_documentation_directory - ) - context.logger.info(f"Exported files following the changelog entry: {exported_modified_files}") - all_modified_files.update(exported_modified_files) - final_labels = DEFAULT_PR_LABELS + [AUTO_MERGE_PR_LABEL] if auto_merge else DEFAULT_PR_LABELS - post_changelog_pr_update = CreateOrUpdatePullRequest( - context, - labels=final_labels, - # For this 'up-to-date' pipeline, we want GitHub to merge organically - # if/when all required checks pass. Maintainers can also easily disable - # auto-merge if they want to review or update the PR before merging. - github_auto_merge=auto_merge, - skip_ci=False, - ) - pr_creation_args, pr_creation_kwargs = get_pr_creation_arguments( - all_modified_files, context, step_results, dependency_updates - ) - post_changelog_pr_update_result = await post_changelog_pr_update.run(*pr_creation_args, **pr_creation_kwargs) - step_results.append(post_changelog_pr_update_result) - - report = ConnectorReport(context, step_results, name="UP-TO-DATE RESULTS") - context.report = report - return report diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/steps.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/steps.py deleted file mode 100644 index 45bfecc49cfa..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/steps.py +++ /dev/null @@ -1,173 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -import json -import os -import re -from dataclasses import dataclass -from enum import Enum -from pathlib import Path -from typing import TYPE_CHECKING - -import dagger -from connector_ops.utils import POETRY_LOCK_FILE_NAME, PYPROJECT_FILE_NAME # type: ignore -from deepdiff import DeepDiff # type: ignore - -from pipelines.airbyte_ci.connectors.context import ConnectorContext, PipelineContext -from pipelines.consts import LOCAL_BUILD_PLATFORM -from pipelines.models.steps import Step, StepModifyingFiles, StepResult, StepStatus - -if TYPE_CHECKING: - from typing import List - - -class PoetryUpdate(StepModifyingFiles): - context: ConnectorContext - dev: bool - specified_versions: dict[str, str] - title = "Update versions of libraries in poetry" - - def __init__( - self, - context: PipelineContext, - connector_directory: dagger.Directory, - dev: bool = False, - specific_dependencies: List[str] | None = None, - ) -> None: - super().__init__(context, connector_directory) - self.dev = dev - self.specified_versions = self.parse_specific_dependencies(specific_dependencies) if specific_dependencies else {} - - @staticmethod - def parse_specific_dependencies(specific_dependencies: List[str]) -> dict[str, str]: - package_name_pattern = r"^(\w+)[@><=]([^\s]+)$" - versions: dict[str, str] = {} - for dep in specific_dependencies: - match = re.match(package_name_pattern, dep) - if match: - package = match.group(1) - versions[package] = dep - else: - raise ValueError(f"Invalid dependency name: {dep}") - return versions - - async def _run(self) -> StepResult: - connector_directory = self.modified_directory - if PYPROJECT_FILE_NAME not in await connector_directory.entries(): - return StepResult(step=self, status=StepStatus.SKIPPED, stderr=f"Connector does not have a {PYPROJECT_FILE_NAME}") - - base_image_name = self.context.connector.metadata["connectorBuildOptions"]["baseImage"] - base_container = self.dagger_client.container(platform=LOCAL_BUILD_PLATFORM).from_(base_image_name) - connector_container = base_container.with_mounted_directory("/connector", connector_directory).with_workdir("/connector") - original_poetry_lock = await connector_container.file(POETRY_LOCK_FILE_NAME).contents() - original_pyproject_file = await connector_container.file(PYPROJECT_FILE_NAME).contents() - - try: - for package, version in self.specified_versions.items(): - if not self.dev: - self.logger.info(f"Add {package} {version} to main dependencies") - connector_container = await connector_container.with_exec(["poetry", "add", f"{package}{version}"], use_entrypoint=True) - else: - self.logger.info(f"Add {package} {version} to dev dependencies") - connector_container = await connector_container.with_exec( - ["poetry", "add", f"{package}{version}", "--group=dev"], use_entrypoint=True - ) - - connector_container = await connector_container.with_exec(["poetry", "update"], use_entrypoint=True) - self.logger.info(await connector_container.stdout()) - except dagger.ExecError as e: - return StepResult(step=self, status=StepStatus.FAILURE, stderr=str(e)) - - if ( - original_poetry_lock != await connector_container.file(POETRY_LOCK_FILE_NAME).contents() - or original_pyproject_file != await connector_container.file(PYPROJECT_FILE_NAME).contents() - ): - self.modified_directory = await connector_container.directory(".") - self.modified_files = [POETRY_LOCK_FILE_NAME, PYPROJECT_FILE_NAME] - return StepResult(step=self, status=StepStatus.SUCCESS, output=connector_container.directory(".")) - - return StepResult(step=self, status=StepStatus.SKIPPED, stdout="No changes in poetry.lock or pyproject.toml") - - -class DependencyUpdateType(Enum): - ADDED = "added" - REMOVED = "removed" - UPDATED = "updated" - - -@dataclass -class DependencyUpdate: - package_type: str - package_name: str - update_type: DependencyUpdateType - new_version: str | None = None - previous_version: str | None = None - - -class GetDependencyUpdates(Step): - SYFT_DOCKER_IMAGE = "anchore/syft:v1.6.0" - context: ConnectorContext - title: str = "Get dependency updates" - - def get_syft_container(self) -> dagger.Container: - home_dir = os.path.expanduser("~") - config_path = os.path.join(home_dir, ".docker", "config.json") - config_file = self.dagger_client.host().file(config_path) - return ( - self.dagger_client.container() - .from_(self.SYFT_DOCKER_IMAGE) - .with_mounted_file("/config/config.json", config_file) - .with_env_variable("DOCKER_CONFIG", "/config") - # Syft requires access to the docker daemon. We share the host's docker socket with the Syft container. - .with_unix_socket("/var/run/docker.sock", self.dagger_client.host().unix_socket("/var/run/docker.sock")) - ) - - @property - def latest_connector_docker_image_address(self) -> str: - docker_image_name = self.context.connector.metadata["dockerRepository"] - return f"{docker_image_name}:latest" - - async def get_sbom_from_latest_image(self) -> str: - syft_container = self.get_syft_container() - return await syft_container.with_exec([self.latest_connector_docker_image_address, "-o", "syft-json"], use_entrypoint=True).stdout() - - async def get_sbom_from_container(self, container: dagger.Container) -> str: - oci_tarball_path = Path(f"/tmp/{self.context.connector.technical_name}-{self.context.connector.version}.tar") - await container.export(str(oci_tarball_path)) - syft_container = self.get_syft_container() - container_sbom = await ( - syft_container.with_mounted_file("/tmp/oci.tar", self.dagger_client.host().file(str(oci_tarball_path))) - .with_exec(["/tmp/oci.tar", "-o", "syft-json"], use_entrypoint=True) - .stdout() - ) - oci_tarball_path.unlink() - return container_sbom - - def get_dependency_updates(self, raw_latest_sbom: str, raw_current_sbom: str) -> List[DependencyUpdate]: - latest_sbom = json.loads(raw_latest_sbom) - current_sbom = json.loads(raw_current_sbom) - latest_packages = {(dep["type"], dep["name"]): dep["version"] for dep in latest_sbom["artifacts"]} - current_packages = {(dep["type"], dep["name"]): dep["version"] for dep in current_sbom["artifacts"]} - diff = DeepDiff(latest_packages, current_packages) - dependency_updates = [] - diff_type_to_update_type = [ - ("values_changed", DependencyUpdateType.UPDATED), - ("dictionary_item_added", DependencyUpdateType.ADDED), - ("dictionary_item_removed", DependencyUpdateType.REMOVED), - ] - for diff_type, update_type in diff_type_to_update_type: - for change in diff.tree.get(diff_type, []): - package_type, package_name = change.get_root_key() - previous_version, new_version = change.t1, change.t2 - dependency_updates.append( - DependencyUpdate(package_type, package_name, update_type, previous_version=previous_version, new_version=new_version) - ) - return dependency_updates - - async def _run(self, target_connector_container: dagger.Container) -> StepResult: - latest_sbom = await self.get_sbom_from_latest_image() - current_sbom = await self.get_sbom_from_container(target_connector_container) - dependency_updates = self.get_dependency_updates(latest_sbom, current_sbom) - return StepResult(step=self, status=StepStatus.SUCCESS, output=dependency_updates) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/templates/up_to_date_pr_body.md.j2 b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/templates/up_to_date_pr_body.md.j2 deleted file mode 100644 index 6cfe122e6029..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/up_to_date/templates/up_to_date_pr_body.md.j2 +++ /dev/null @@ -1,32 +0,0 @@ -# Update {{ connector_technical_name }} - -This PR was autogenerated by running `airbyte-ci connectors --name={{ connector_technical_name }} up_to_date --pull` - -We've set the `auto-merge` label on it, so it will be automatically merged if the CI pipelines pass. -If you don't want to merge it automatically, please remove the `auto-merge` label. -Please reach out to the Airbyte Connector Tooling team if you have any questions or concerns. - -{% if step_results %} -## Operations -{% for step_result in step_results %} -- {{step_result.step.title}}: {{ step_result.status.value }} -{% endfor %} -{% endif %} - -{% if dependency_updates %} -## Dependency updates - -We use [`syft`](https://github.com/anchore/syft) to generate a SBOM for the latest connector version and the one from the PR. -It allows us to spot the dependencies that have been updated at all levels and for all types of dependencies (system, python, java etc.). -Here are the dependencies that have been updated compared to `{{ connector_latest_docker_image }}`. -Keep in mind that `:latest` does not always match the connector code on the main branch. -It is the latest released connector image when the head commit of this branch was created. - -| Type | Name | State | Previous Version | New Version | -|------|------|-------|-------------|------------------| -{%- for dependency_update in dependency_updates %} -| {{ dependency_update.package_type }} | {{ dependency_update.package_name }} | {{ dependency_update.update_type.value }} | {{ dependency_update.previous_version }} | **{{ dependency_update.new_version }}** | -{%- endfor %} -{% endif %} - - diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/commands.py deleted file mode 100644 index 16519b4e6d6e..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/commands.py +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import asyncclick as click - -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.airbyte_ci.connectors.pipeline import run_connectors_pipelines -from pipelines.airbyte_ci.connectors.upgrade_cdk.pipeline import run_connector_cdk_upgrade_pipeline -from pipelines.cli.dagger_pipeline_command import DaggerPipelineCommand - - -@click.command(cls=DaggerPipelineCommand, short_help="Upgrade CDK version") -@click.argument("target-cdk-version", type=str, default="latest") -@click.pass_context -async def upgrade_cdk( - ctx: click.Context, - target_cdk_version: str, -) -> bool: - """Upgrade CDK version""" - - connectors_contexts = [ - ConnectorContext( - pipeline_name=f"Upgrade CDK version of connector {connector.technical_name}", - connector=connector, - is_local=ctx.obj["is_local"], - git_branch=ctx.obj["git_branch"], - git_revision=ctx.obj["git_revision"], - diffed_branch=ctx.obj["diffed_branch"], - git_repo_url=ctx.obj["git_repo_url"], - ci_report_bucket=ctx.obj["ci_report_bucket_name"], - report_output_prefix=ctx.obj["report_output_prefix"], - gha_workflow_run_url=ctx.obj.get("gha_workflow_run_url"), - dagger_logs_url=ctx.obj.get("dagger_logs_url"), - pipeline_start_timestamp=ctx.obj.get("pipeline_start_timestamp"), - ci_context=ctx.obj.get("ci_context"), - ci_gcp_credentials=ctx.obj["ci_gcp_credentials"], - ci_git_user=ctx.obj["ci_git_user"], - ci_github_access_token=ctx.obj["ci_github_access_token"], - enable_report_auto_open=False, - s3_build_cache_access_key_id=ctx.obj.get("s3_build_cache_access_key_id"), - s3_build_cache_secret_key=ctx.obj.get("s3_build_cache_secret_key"), - ) - for connector in ctx.obj["selected_connectors_with_modified_files"] - ] - - await run_connectors_pipelines( - connectors_contexts, - run_connector_cdk_upgrade_pipeline, - "Upgrade CDK version pipeline", - ctx.obj["concurrency"], - ctx.obj["dagger_logs_path"], - ctx.obj["execute_timeout"], - target_cdk_version, - ) - - return True diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/pipeline.py deleted file mode 100644 index 193ee6885e2c..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/pipeline.py +++ /dev/null @@ -1,177 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -import os -import re -from typing import TYPE_CHECKING - -import toml -from connector_ops.utils import ConnectorLanguage # type: ignore -from dagger import Directory - -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.airbyte_ci.connectors.reports import ConnectorReport -from pipelines.consts import LOCAL_BUILD_PLATFORM -from pipelines.helpers import git -from pipelines.helpers.connectors import cdk_helpers -from pipelines.models.steps import Step, StepResult, StepStatus - -if TYPE_CHECKING: - from typing import Optional - - from anyio import Semaphore - -# GLOBALS - -POETRY_LOCK_FILENAME = "poetry.lock" -PYPROJECT_FILENAME = "pyproject.toml" - - -class SetCDKVersion(Step): - context: ConnectorContext - title = "Set CDK Version" - - def __init__( - self, - context: ConnectorContext, - new_version: str, - ) -> None: - super().__init__(context) - self.new_version = new_version - - async def _run(self) -> StepResult: - context = self.context - - try: - og_connector_dir = await context.get_connector_dir() - if self.context.connector.language in [ConnectorLanguage.PYTHON, ConnectorLanguage.LOW_CODE]: - updated_connector_dir = await self.upgrade_cdk_version_for_python_connector(og_connector_dir) - elif self.context.connector.language is ConnectorLanguage.JAVA: - updated_connector_dir = await self.upgrade_cdk_version_for_java_connector(og_connector_dir) - else: - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stdout=f"The upgrade-cdk command does not support {self.context.connector.language} connectors.", - ) - - if updated_connector_dir is None: - return StepResult( - step=self, - status=StepStatus.FAILURE, - stderr=f"No changes were made to the CDK version for connector {self.context.connector.technical_name}", - ) - diff = og_connector_dir.diff(updated_connector_dir) - exported_successfully = await diff.export(os.path.join(git.get_git_repo_path(), context.connector.code_directory)) - if not exported_successfully: - return StepResult( - step=self, - status=StepStatus.FAILURE, - stdout="Could not export diff to local git repo.", - ) - return StepResult(step=self, status=StepStatus.SUCCESS, stdout=f"Updated CDK version to {self.new_version}", output=diff) - except ValueError as e: - return StepResult( - step=self, - status=StepStatus.FAILURE, - stderr=f"Could not set CDK version: {e}", - exc_info=e, - ) - - async def upgrade_cdk_version_for_java_connector(self, og_connector_dir: Directory) -> Directory: - if "build.gradle" not in await og_connector_dir.entries(): - raise ValueError(f"Java connector {self.context.connector.technical_name} does not have a build.gradle file.") - - build_gradle = og_connector_dir.file("build.gradle") - build_gradle_content = await build_gradle.contents() - - old_cdk_version_required = re.search(r"cdkVersionRequired *= *'(?P[0-9]*\.[0-9]*\.[0-9]*)?'", build_gradle_content) - # If there is no airbyte-cdk dependency, add the version - if old_cdk_version_required is None: - raise ValueError("Could not find airbyte-cdk dependency in build.gradle") - - if self.new_version == "latest": - new_version = await cdk_helpers.get_latest_java_cdk_version(self.context.get_repo_dir()) - else: - new_version = self.new_version - - updated_build_gradle = build_gradle_content.replace(old_cdk_version_required.group("version"), new_version) - - use_local_cdk = re.search(r"useLocalCdk *=.*", updated_build_gradle) - if use_local_cdk is not None: - updated_build_gradle = updated_build_gradle.replace(use_local_cdk.group(), "useLocalCdk = false") - - return og_connector_dir.with_new_file("build.gradle", updated_build_gradle) - - async def upgrade_cdk_version_for_python_connector(self, og_connector_dir: Directory) -> Optional[Directory]: - context = self.context - og_connector_dir = await context.get_connector_dir() - - # Check for existing pyproject file and load contents - pyproject_toml = og_connector_dir.file(PYPROJECT_FILENAME) - if not pyproject_toml: - raise ValueError(f"Could not find 'pyproject.toml' for {context.connector.technical_name}") - pyproject_content = await pyproject_toml.contents() - pyproject_data = toml.loads(pyproject_content) - - # Grab the airbyte-cdk dependency from pyproject - dependencies = pyproject_data.get("tool", {}).get("poetry", {}).get("dependencies", {}) - airbyte_cdk_dependency = dependencies.get("airbyte-cdk") - if not airbyte_cdk_dependency: - raise ValueError("Could not find a valid airbyte-cdk dependency in 'pyproject.toml'") - - # Set the new version. If not explicitly provided, set it to the latest version and allow non-breaking changes - if self.new_version == "latest": - new_version = f"^{cdk_helpers.get_latest_python_cdk_version()}" - else: - new_version = self.new_version - self.logger.info(f"Setting CDK version to {new_version}") - dependencies["airbyte-cdk"] = new_version - - updated_pyproject_toml_content = toml.dumps(pyproject_data) - updated_connector_dir = og_connector_dir.with_new_file(PYPROJECT_FILENAME, updated_pyproject_toml_content) - - # Create a new container to run poetry lock - base_image = self.context.connector.metadata["connectorBuildOptions"]["baseImage"] - base_container = self.dagger_client.container(platform=LOCAL_BUILD_PLATFORM).from_(base_image) - connector_container = base_container.with_mounted_directory("/connector", updated_connector_dir).with_workdir("/connector") - - poetry_lock_file = await connector_container.file(POETRY_LOCK_FILENAME).contents() - updated_container = await connector_container.with_exec(["poetry", "lock"], use_entrypoint=True) - updated_poetry_lock_file = await updated_container.file(POETRY_LOCK_FILENAME).contents() - - if poetry_lock_file != updated_poetry_lock_file: - updated_connector_dir = updated_connector_dir.with_new_file(POETRY_LOCK_FILENAME, updated_poetry_lock_file) - else: - raise ValueError("Lockfile did not change after running poetry lock") - - return updated_connector_dir - - -async def run_connector_cdk_upgrade_pipeline( - context: ConnectorContext, - semaphore: Semaphore, - target_version: str, -) -> ConnectorReport: - """Run a pipeline to upgrade the CDK version for a single connector. - - Args: - context (ConnectorContext): The initialized connector context. - - Returns: - Report: The reports holding the CDK version set results. - """ - async with semaphore: - steps_results = [] - async with context: - set_cdk_version = SetCDKVersion( - context, - target_version, - ) - set_cdk_version_result = await set_cdk_version.run() - steps_results.append(set_cdk_version_result) - report = ConnectorReport(context, steps_results, name="CONNECTOR VERSION CDK UPGRADE RESULTS") - context.report = report - return report diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/metadata/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/metadata/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/metadata/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/metadata/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/metadata/commands.py deleted file mode 100644 index 8796340abffa..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/metadata/commands.py +++ /dev/null @@ -1,16 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import asyncclick as click - -from pipelines.cli.click_decorators import click_ci_requirements_option - -# MAIN GROUP - - -@click.group(help="Commands related to the metadata service.") -@click_ci_requirements_option() -@click.pass_context -def metadata(ctx: click.Context) -> None: - pass diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/metadata/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/metadata/pipeline.py deleted file mode 100644 index 4c6c6b593292..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/metadata/pipeline.py +++ /dev/null @@ -1,160 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import uuid -from typing import Optional - -import dagger - -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.airbyte_ci.steps.docker import SimpleDockerStep -from pipelines.consts import DOCS_DIRECTORY_ROOT_PATH, GIT_DIRECTORY_ROOT_PATH, INTERNAL_TOOL_PATHS -from pipelines.models.secrets import Secret -from pipelines.models.steps import MountPath - -# STEPS - - -class MetadataValidation(SimpleDockerStep): - def __init__(self, context: ConnectorContext) -> None: - super().__init__( - title=f"Validate metadata for {context.connector.technical_name}", - context=context, - paths_to_mount=[ - MountPath(context.connector.code_directory), - MountPath(DOCS_DIRECTORY_ROOT_PATH), - ], - internal_tools=[ - MountPath(INTERNAL_TOOL_PATHS.METADATA_SERVICE.value), - ], - secret_env_variables={"DOCKER_HUB_USERNAME": context.docker_hub_username, "DOCKER_HUB_PASSWORD": context.docker_hub_password} - if context.docker_hub_username and context.docker_hub_password - else None, - command=[ - "metadata_service", - "validate", - str(context.connector.metadata_file_path), - DOCS_DIRECTORY_ROOT_PATH, - ], - ) - - -class MetadataUpload(SimpleDockerStep): - # When the metadata service exits with this code, it means the metadata is valid but the upload was skipped because the metadata is already uploaded - skipped_exit_code = 5 - - def __init__( - self, - context: ConnectorContext, - metadata_bucket_name: str, - metadata_service_gcs_credentials: Secret, - docker_hub_username: Secret, - docker_hub_password: Secret, - pre_release: bool = False, - pre_release_tag: Optional[str] = None, - ) -> None: - title = f"Upload metadata for {context.connector.technical_name} v{context.connector.version}" - command_to_run = [ - "metadata_service", - "upload", - str(context.connector.metadata_file_path), - DOCS_DIRECTORY_ROOT_PATH, - metadata_bucket_name, - ] - - if pre_release and pre_release_tag: - command_to_run += ["--prerelease", pre_release_tag] - - super().__init__( - title=title, - context=context, - paths_to_mount=[ - MountPath(GIT_DIRECTORY_ROOT_PATH), - MountPath(DOCS_DIRECTORY_ROOT_PATH), - MountPath(context.connector.code_directory), - ], - internal_tools=[ - MountPath(INTERNAL_TOOL_PATHS.METADATA_SERVICE.value), - ], - secret_env_variables={ - "DOCKER_HUB_USERNAME": docker_hub_username, - "DOCKER_HUB_PASSWORD": docker_hub_password, - "GCS_CREDENTIALS": metadata_service_gcs_credentials, - }, - env_variables={ - # The cache buster ensures we always run the upload command (in case of remote bucket change) - "CACHEBUSTER": str(uuid.uuid4()), - }, - command=command_to_run, - ) - - -class MetadataRollbackReleaseCandidate(SimpleDockerStep): - def __init__( - self, - context: ConnectorContext, - metadata_bucket_name: str, - metadata_service_gcs_credentials: Secret, - ) -> None: - docker_repository = context.connector.metadata["dockerRepository"] - version = context.connector.metadata["dockerImageTag"] - title = f"Rollback release candidate for {docker_repository} v{version}" - command_to_run = [ - "metadata_service", - "rollback-release-candidate", - docker_repository, - version, - metadata_bucket_name, - ] - - super().__init__( - title=title, - context=context, - internal_tools=[ - MountPath(INTERNAL_TOOL_PATHS.METADATA_SERVICE.value), - ], - secret_env_variables={ - "GCS_CREDENTIALS": metadata_service_gcs_credentials, - }, - env_variables={ - # The cache buster ensures we always run the rollback command (in case of remote bucket change) - "CACHEBUSTER": str(uuid.uuid4()), - }, - command=command_to_run, - ) - - -class MetadataPromoteReleaseCandidate(SimpleDockerStep): - def __init__( - self, - context: ConnectorContext, - metadata_bucket_name: str, - metadata_service_gcs_credentials: Secret, - ) -> None: - docker_repository = context.connector.metadata["dockerRepository"] - version = context.connector.metadata["dockerImageTag"] - title = f"Promote release candidate for {docker_repository} v{version}" - command_to_run = [ - "metadata_service", - "promote-release-candidate", - docker_repository, - version, - metadata_bucket_name, - ] - - super().__init__( - title=title, - context=context, - internal_tools=[ - MountPath(INTERNAL_TOOL_PATHS.METADATA_SERVICE.value), - ], - secret_env_variables={ - "GCS_CREDENTIALS": metadata_service_gcs_credentials, - }, - env_variables={ - # The cache buster ensures we always run the rollback command (in case of remote bucket change) - "CACHEBUSTER": str(uuid.uuid4()), - }, - command=command_to_run, - ) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/commands.py deleted file mode 100644 index e40905692072..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/commands.py +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -""" -Module exposing the format commands. -""" - -from __future__ import annotations - -import asyncclick as click - -from pipelines.cli.click_decorators import click_ignore_unused_kwargs, click_merge_args_into_context_obj -from pipelines.cli.lazy_group import LazyGroup -from pipelines.models.contexts.click_pipeline_context import ClickPipelineContext, pass_pipeline_context - - -@click.group( - name="poetry", - help="Commands related to running poetry commands.", - cls=LazyGroup, - lazy_subcommands={ - "publish": "pipelines.airbyte_ci.poetry.publish.commands.publish", - }, -) -@click.option( - "--package-path", - help="The path to publish", - type=click.STRING, - required=True, -) -@click_merge_args_into_context_obj -@pass_pipeline_context -@click_ignore_unused_kwargs -async def poetry(pipeline_context: ClickPipelineContext) -> None: - pass diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/publish/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/publish/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/publish/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/publish/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/publish/commands.py deleted file mode 100644 index d822ae8e890b..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/poetry/publish/commands.py +++ /dev/null @@ -1,114 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -""" -Module exposing the format commands. -""" - -from __future__ import annotations - -from typing import Optional - -import asyncclick as click -from packaging import version - -from pipelines.airbyte_ci.steps.python_registry import PublishToPythonRegistry -from pipelines.cli.confirm_prompt import confirm -from pipelines.cli.dagger_pipeline_command import DaggerPipelineCommand -from pipelines.cli.secrets import wrap_in_secret -from pipelines.consts import DEFAULT_PYTHON_PACKAGE_REGISTRY_CHECK_URL, DEFAULT_PYTHON_PACKAGE_REGISTRY_URL -from pipelines.models.contexts.click_pipeline_context import ClickPipelineContext, pass_pipeline_context -from pipelines.models.contexts.python_registry_publish import PythonRegistryPublishContext -from pipelines.models.secrets import Secret -from pipelines.models.steps import StepStatus - - -async def _has_metadata_yaml(context: PythonRegistryPublishContext) -> bool: - dir_to_publish = context.get_repo_dir(context.package_path) - return "metadata.yaml" in await dir_to_publish.entries() - - -def _validate_python_version(_ctx: dict, _param: dict, value: Optional[str]) -> Optional[str]: - """ - Check if an given version is valid. - """ - if value is None: - return value - try: - version.Version(value) - return value - except version.InvalidVersion: - raise click.BadParameter(f"Version {value} is not a valid version.") - - -@click.command(cls=DaggerPipelineCommand, name="publish", help="Publish a Python package to a registry.") -@click.option( - "--python-registry-token", - help="Access token", - type=click.STRING, - required=True, - envvar="PYTHON_REGISTRY_TOKEN", - callback=wrap_in_secret, -) -@click.option( - "--python-registry-url", - help="Which registry to publish to. If not set, the default pypi is used. For test pypi, use https://test.pypi.org/legacy/", - type=click.STRING, - default=DEFAULT_PYTHON_PACKAGE_REGISTRY_URL, - envvar="PYTHON_REGISTRY_URL", -) -@click.option( - "--publish-name", - help="The name of the package to publish. If not set, the name will be inferred from the pyproject.toml file of the package.", - type=click.STRING, -) -@click.option( - "--publish-version", - help="The version of the package to publish. If not set, the version will be inferred from the pyproject.toml file of the package.", - type=click.STRING, - callback=_validate_python_version, -) -@pass_pipeline_context -@click.pass_context -async def publish( - ctx: click.Context, - click_pipeline_context: ClickPipelineContext, - python_registry_token: Secret, - python_registry_url: str, - publish_name: Optional[str], - publish_version: Optional[str], -) -> bool: - context = PythonRegistryPublishContext( - is_local=ctx.obj["is_local"], - git_branch=ctx.obj["git_branch"], - git_revision=ctx.obj["git_revision"], - diffed_branch=ctx.obj["diffed_branch"], - git_repo_url=ctx.obj["git_repo_url"], - ci_report_bucket=ctx.obj["ci_report_bucket_name"], - report_output_prefix=ctx.obj["report_output_prefix"], - gha_workflow_run_url=ctx.obj.get("gha_workflow_run_url"), - dagger_logs_url=ctx.obj.get("dagger_logs_url"), - pipeline_start_timestamp=ctx.obj.get("pipeline_start_timestamp"), - ci_context=ctx.obj.get("ci_context"), - ci_gcp_credentials=ctx.obj["ci_gcp_credentials"], - python_registry_token=python_registry_token, - registry=python_registry_url, - registry_check_url=DEFAULT_PYTHON_PACKAGE_REGISTRY_CHECK_URL, - package_path=ctx.obj["package_path"], - package_name=publish_name, - version=publish_version, - ) - - dagger_client = await click_pipeline_context.get_dagger_client() - context.dagger_client = dagger_client - - if await _has_metadata_yaml(context): - confirm( - "It looks like you are trying to publish a connector. In most cases, the `connectors` command group should be used instead. Do you want to continue?", - abort=True, - ) - - publish_result = await PublishToPythonRegistry(context).run() - - return publish_result.status is StepStatus.SUCCESS diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/base_image.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/base_image.py deleted file mode 100644 index 34d04d231f77..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/base_image.py +++ /dev/null @@ -1,158 +0,0 @@ -# Copyright (c) 2025 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -from typing import TYPE_CHECKING, List, Optional - -import dagger -import semver -import yaml -from connector_ops.utils import METADATA_FILE_NAME, ConnectorLanguage # type: ignore - -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.dagger.actions.system.docker import with_crane -from pipelines.helpers.connectors.dagger_fs import dagger_read_file, dagger_write_file -from pipelines.models.steps import StepModifyingFiles, StepResult, StepStatus - -if TYPE_CHECKING: - import dagger - - -class NoBaseImageAddressInMetadataError(Exception): - pass - - -class UpdateBaseImageMetadata(StepModifyingFiles): - BASE_IMAGE_LIST_CACHE_TTL_SECONDS = 60 * 60 * 24 # 1 day - - context: ConnectorContext - - title = "Upgrade the base image to the latest version in metadata.yaml" - - def __init__( - self, - context: ConnectorContext, - connector_directory: dagger.Directory, - set_if_not_exists: bool = False, - ) -> None: - super().__init__(context, connector_directory) - self.set_if_not_exists = set_if_not_exists - self.modified_files = [] - self.connector_directory = connector_directory - - def _get_repository_for_language(self, language: ConnectorLanguage) -> str: - """Map connector language to DockerHub repository.""" - if language in [ConnectorLanguage.PYTHON, ConnectorLanguage.LOW_CODE]: - return "airbyte/python-connector-base" - elif language is ConnectorLanguage.MANIFEST_ONLY: - return "airbyte/source-declarative-manifest" - elif language is ConnectorLanguage.JAVA: - return "airbyte/java-connector-base" - else: - raise NotImplementedError(f"Registry for language {language} is not implemented yet.") - - def _parse_latest_stable_tag(self, tags: List[str]) -> Optional[str]: - """Parse tags to find latest stable (non-prerelease) version.""" - valid_versions = [] - for tag in tags: - try: - version = semver.VersionInfo.parse(tag) - if not version.prerelease: # Exclude pre-release versions - valid_versions.append(version) - except ValueError: - continue # Skip non-semver tags - - if valid_versions: - return str(max(valid_versions)) - return None - - async def get_latest_base_image_address(self) -> Optional[str]: - try: - if not (self.context.docker_hub_username and self.context.docker_hub_password): - raise ValueError("Docker Hub credentials are required to get the latest base image address") - - repository = self._get_repository_for_language(self.context.connector.language) - crane_container = with_crane(self.context) - - # List all tags - tags_output = await crane_container.with_exec(["crane", "ls", f"docker.io/{repository}"]).stdout() - tags = [tag.strip() for tag in tags_output.strip().split("\n") if tag.strip()] - - latest_tag = self._parse_latest_stable_tag(tags) - if latest_tag: - # Get the digest for the specific tag to ensure immutable reference - digest_output = await crane_container.with_exec(["crane", "digest", f"docker.io/{repository}:{latest_tag}"]).stdout() - digest = digest_output.strip() - return f"docker.io/{repository}:{latest_tag}@{digest}" - return None - except NotImplementedError: - return None - - @staticmethod - async def update_base_image_in_metadata( - connector_directory: dagger.Directory, latest_base_image_version_address: str, set_if_not_exists: bool = False - ) -> dagger.Directory: - raw_metadata = await dagger_read_file(connector_directory, METADATA_FILE_NAME) - current_metadata = yaml.safe_load(raw_metadata) - - current_base_image_version_address = current_metadata.get("data").get("connectorBuildOptions", {}).get("baseImage") - if not current_base_image_version_address: - if set_if_not_exists: - current_metadata["data"]["connectorBuildOptions"] = {"baseImage": latest_base_image_version_address} - new_raw_metadata = yaml.dump(current_metadata) - else: - raise NoBaseImageAddressInMetadataError("No base image address found in metadata file") - else: - new_raw_metadata = raw_metadata.replace(current_base_image_version_address, latest_base_image_version_address) - updated_connector_dir = dagger_write_file(connector_directory, METADATA_FILE_NAME, new_raw_metadata) - return updated_connector_dir - - async def _run(self) -> StepResult: - latest_base_image_address = await self.get_latest_base_image_address() - updated_base_image_address = None - if latest_base_image_address is None: - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stdout="Could not find a base image for this connector language.", - ) - - current_base_image_address = self.context.connector.metadata.get("connectorBuildOptions", {}).get("baseImage") - - if not self.set_if_not_exists and current_base_image_address is None: - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stdout="This connector does not have a base image set in metadata.yaml.", - ) - - if current_base_image_address == latest_base_image_address: - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stdout=f"Base image is already up to date: {latest_base_image_address}", - ) - - original_connector_directory = self.connector_directory or await self.context.get_connector_dir() - try: - updated_connector_directory = await self.update_base_image_in_metadata( - original_connector_directory, latest_base_image_address, self.set_if_not_exists - ) - updated_base_image_address = latest_base_image_address - except NoBaseImageAddressInMetadataError: - return StepResult( - step=self, - status=StepStatus.FAILURE, - stderr="No base image address found in metadata file", - ) - self.modified_files.append(METADATA_FILE_NAME) - - return StepResult( - step=self, - status=StepStatus.SUCCESS, - stdout=f"Updated base image to {latest_base_image_address} in {METADATA_FILE_NAME}", - output={ - "updated_connector_directory": updated_connector_directory, - "updated_base_image_address": updated_base_image_address, - }, - ) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/bump_version.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/bump_version.py deleted file mode 100644 index e26c10c292c1..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/bump_version.py +++ /dev/null @@ -1,151 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -from typing import TYPE_CHECKING, Any, Mapping - -import dagger -import semver -import yaml # type: ignore -from connector_ops.utils import METADATA_FILE_NAME, PYPROJECT_FILE_NAME # type: ignore - -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.dagger.actions.python.poetry import with_poetry -from pipelines.helpers.connectors.dagger_fs import dagger_read_file, dagger_write_file -from pipelines.models.steps import StepModifyingFiles, StepResult, StepStatus - -BUMP_VERSION_METHOD_MAPPING: Mapping[str, Any] = { - "patch": semver.Version.bump_patch, - "minor": semver.Version.bump_minor, - "major": semver.Version.bump_major, - "rc": semver.Version.bump_prerelease, -} - -if TYPE_CHECKING: - pass - - -class ConnectorVersionNotFoundError(Exception): - pass - - -class PoetryVersionBumpError(Exception): - pass - - -class SetConnectorVersion(StepModifyingFiles): - context: ConnectorContext - - @property - def title(self) -> str: - return f"Set connector version to {self.new_version}" - - def __init__( - self, - context: ConnectorContext, - connector_directory: dagger.Directory, - new_version: str, - ) -> None: - super().__init__(context, connector_directory) - self.new_version = new_version - - @staticmethod - async def _set_version_in_metadata(new_version: str, connector_directory: dagger.Directory) -> dagger.Directory: - raw_metadata = await dagger_read_file(connector_directory, METADATA_FILE_NAME) - current_metadata = yaml.safe_load(raw_metadata) - - try: - current_version = current_metadata["data"]["dockerImageTag"] - except KeyError: - raise ConnectorVersionNotFoundError("dockerImageTag not found in metadata file") - - # We use replace here instead of mutating the deserialized yaml to avoid messing up with the comments in the metadata file. - new_raw_metadata = raw_metadata.replace("dockerImageTag: " + current_version, "dockerImageTag: " + new_version) - updated_connector_dir = dagger_write_file(connector_directory, METADATA_FILE_NAME, new_raw_metadata) - - return updated_connector_dir - - @staticmethod - async def _set_version_in_poetry_package( - container_with_poetry: dagger.Container, connector_directory: dagger.Directory, new_version: str - ) -> dagger.Directory: - try: - connector_directory_with_updated_pyproject = await ( - container_with_poetry.with_directory("/connector", connector_directory) - .with_workdir("/connector") - .with_exec(["poetry", "version", new_version], use_entrypoint=True) - .directory("/connector") - ) - except dagger.ExecError as e: - raise PoetryVersionBumpError(f"Failed to bump version in pyproject.toml: {e}") - return connector_directory_with_updated_pyproject - - async def _run(self) -> StepResult: - original_connector_directory = self.modified_directory - try: - self.modified_directory = await self._set_version_in_metadata(self.new_version, original_connector_directory) - self.modified_files.append(METADATA_FILE_NAME) - except (FileNotFoundError, ConnectorVersionNotFoundError) as e: - return StepResult( - step=self, - status=StepStatus.FAILURE, - stderr="Connector does not have a metadata file or the version is not set in the metadata file", - exc_info=e, - ) - - if self.context.connector.pyproject_file_path.is_file(): - try: - poetry_container = with_poetry(self.context) - self.modified_directory = await self._set_version_in_poetry_package( - poetry_container, self.modified_directory, self.new_version - ) - self.modified_files.append(PYPROJECT_FILE_NAME) - except PoetryVersionBumpError as e: - return StepResult( - step=self, - status=StepStatus.FAILURE, - stderr="Failed to bump version in pyproject.toml", - exc_info=e, - ) - - return StepResult( - step=self, - status=StepStatus.SUCCESS, - stdout=f"Updated connector to {self.new_version}", - output=self.modified_directory, - ) - - -class BumpConnectorVersion(SetConnectorVersion): - def __init__(self, context: ConnectorContext, connector_directory: dagger.Directory, bump_type: str, rc: bool = False) -> None: - self.bump_type = bump_type - new_version = self.get_bumped_version(context.connector.version, bump_type, rc) - super().__init__( - context, - connector_directory, - new_version, - ) - - @property - def title(self) -> str: - return f"{self.bump_type.upper()} bump {self.context.connector.technical_name} version to {self.new_version}" - - @staticmethod - def get_bumped_version(version: str | None, bump_type: str, rc: bool) -> str: - if version is None: - raise ValueError("Version is not set") - current_version = semver.VersionInfo.parse(version) - if bump_type in BUMP_VERSION_METHOD_MAPPING: - new_version = BUMP_VERSION_METHOD_MAPPING[bump_type](current_version) - if rc: - new_version = new_version.bump_prerelease() - elif bump_type.startswith("version:"): - version_str = bump_type.split("version:", 1)[1] - if semver.VersionInfo.is_valid(version_str): - return version_str - else: - raise ValueError(f"Invalid version: {version_str}") - else: - raise ValueError(f"Unknown bump type: {bump_type}") - return str(new_version) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/changelog.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/changelog.py deleted file mode 100644 index 3170d082b333..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/changelog.py +++ /dev/null @@ -1,70 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from __future__ import annotations - -import datetime - -import semver -from dagger import Directory - -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.helpers.changelog import Changelog -from pipelines.helpers.connectors.dagger_fs import dagger_read_file, dagger_write_file -from pipelines.models.steps import StepModifyingFiles, StepResult, StepStatus - - -class AddChangelogEntry(StepModifyingFiles): - context: ConnectorContext - - title = "Add changelog entry" - - def __init__( - self, - context: ConnectorContext, - documentation_directory: Directory, - new_version: str, - comment: str, - pull_request_number: str | int | None, - ) -> None: - super().__init__(context, documentation_directory) - self.new_version = semver.VersionInfo.parse(new_version) - self.comment = comment - self.pull_request_number = pull_request_number or "*PR_NUMBER_PLACEHOLDER*" - - async def _run(self, pull_request_number: int | str | None = None) -> StepResult: - if pull_request_number is None: - # this allows passing it dynamically from a result of another action (like creating a pull request) - pull_request_number = self.pull_request_number - - try: - original_markdown = await dagger_read_file(self.modified_directory, self.context.connector.documentation_file_name) - except FileNotFoundError: - return StepResult( - step=self, - status=StepStatus.SKIPPED, - stderr="Connector does not have a documentation file.", - ) - - try: - changelog = Changelog(original_markdown) - changelog.add_entry(self.new_version, datetime.date.today(), pull_request_number, self.comment) - updated_doc = changelog.to_markdown() - except Exception as e: - return StepResult( - step=self, - status=StepStatus.FAILURE, - stderr=f"Could not add changelog entry: {e}", - output=self.modified_directory, - exc_info=e, - ) - - self.modified_directory = dagger_write_file(self.modified_directory, self.context.connector.documentation_file_name, updated_doc) - self.modified_files.append(self.context.connector.documentation_file_name) - return StepResult( - step=self, - status=StepStatus.SUCCESS, - stdout=f"Added changelog entry to {self.context.connector.documentation_file_name}", - output=self.modified_directory, - ) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/docker.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/docker.py deleted file mode 100644 index 1e974fc46deb..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/docker.py +++ /dev/null @@ -1,112 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from pathlib import Path -from typing import Dict, List, Optional - -import dagger - -from pipelines.dagger.actions.python.pipx import with_installed_pipx_package -from pipelines.dagger.containers.python import with_python_base -from pipelines.models.contexts.pipeline_context import PipelineContext -from pipelines.models.secrets import Secret -from pipelines.models.steps import MountPath, Step, StepResult - - -class SimpleDockerStep(Step): - def __init__( - self, - title: str, - context: PipelineContext, - paths_to_mount: Optional[List[MountPath]] = None, - internal_tools: Optional[List[MountPath]] = None, - secret_env_variables: Optional[Dict[str, Secret]] = None, - env_variables: dict[str, str] = {}, - working_directory: str = "/", - command: Optional[List[str]] = None, - ) -> None: - """A simple step that runs a given command in a container. - - Args: - title (str): name of the step - context (PipelineContext): context of the step - paths_to_mount (List[MountPath], optional): directory paths to mount. Defaults to []. - internal_tools (List[MountPath], optional): internal tools to install. Defaults to []. - secret_env_variables (List[Tuple[str, Secret]], optional): secrets to add to container as environment variables, a tuple of env var name > Secret object . Defaults to []. - env_variables (dict[str, str], optional): env variables to set in container. Defaults to {}. - working_directory (str, optional): working directory to run the command in. Defaults to "/". - command (Optional[List[str]], optional): The default command to run. Defaults to None. - """ - self._title = title - super().__init__(context) - - self.paths_to_mount = paths_to_mount if paths_to_mount else [] - self.working_directory = working_directory - self.internal_tools = internal_tools if internal_tools else [] - self.secret_env_variables = secret_env_variables if secret_env_variables else {} - self.env_variables = env_variables - self.command = command - - @property - def title(self) -> str: - return self._title - - def _mount_paths(self, container: dagger.Container) -> dagger.Container: - for path_to_mount in self.paths_to_mount: - if path_to_mount.optional and not path_to_mount.get_path().exists(): - continue - - if path_to_mount.get_path().is_symlink(): - container = self._mount_path(container, path_to_mount.get_path().readlink()) - - container = self._mount_path(container, path_to_mount.get_path()) - return container - - def _mount_path(self, container: dagger.Container, path: Path) -> dagger.Container: - path_string = str(path) - destination_path = f"/{path_string}" - if path.is_file(): - file_to_load = self.context.get_repo_file(path_string) - container = container.with_mounted_file(destination_path, file_to_load) - else: - dir_to_load = self.context.get_repo_dir(path_string) - container = container.with_mounted_directory(destination_path, dir_to_load) - return container - - async def _install_internal_tools(self, container: dagger.Container) -> dagger.Container: - for internal_tool in self.internal_tools: - container = await with_installed_pipx_package(self.context, container, str(internal_tool)) - return container - - def _set_workdir(self, container: dagger.Container) -> dagger.Container: - return container.with_workdir(self.working_directory) - - def _set_env_variables(self, container: dagger.Container) -> dagger.Container: - for key, value in self.env_variables.items(): - container = container.with_env_variable(key, value) - return container - - def _set_secret_env_variables(self, container: dagger.Container) -> dagger.Container: - for env_var_name, secret in self.secret_env_variables.items(): - container = container.with_secret_variable(env_var_name, secret.as_dagger_secret(self.context.dagger_client)) - return container - - async def init_container(self) -> dagger.Container: - # TODO (ben): Replace with python base container when available - container = with_python_base(self.context) - - container = self._mount_paths(container) - container = self._set_env_variables(container) - container = self._set_secret_env_variables(container) - container = await self._install_internal_tools(container) - container = self._set_workdir(container) - - return container - - async def _run(self, command: Optional[List[str]] = None) -> StepResult: - command_to_run = command or self.command - if not command_to_run: - raise ValueError(f"No command given to the {self.title} step") - - container_to_run = await self.init_container() - return await self.get_step_result(container_to_run.with_exec(command_to_run)) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/gradle.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/gradle.py deleted file mode 100644 index 32aa13463907..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/gradle.py +++ /dev/null @@ -1,323 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -import os -import select -import shutil -import signal -import subprocess -from abc import ABC -from contextlib import contextmanager -from datetime import datetime -from pathlib import Path -from typing import Any, ClassVar, Dict, Generator, List, Optional, Tuple, cast - -from dagger import Container, ExecError - -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.helpers.utils import dagger_directory_as_zip_file -from pipelines.models.artifacts import Artifact -from pipelines.models.secrets import Secret -from pipelines.models.steps import Step, StepResult, StepStatus - - -class InvalidGradleEnvironment(Exception): - pass - - -class GradleTimeoutError(Exception): - """Raised when a Gradle operation times out.""" - - pass - - -class GradleExecutionError(Exception): - """Raised when a Gradle execution fails due to an unexpected error.""" - - pass - - -class GradleTask(Step, ABC): - """ - A step to run a Gradle task. - - Attributes: - title (str): The step title. - gradle_task_name (str): The Gradle task name to run. - bind_to_docker_host (bool): Whether to install the docker client and bind it to the host. - mount_connector_secrets (bool): Whether to mount connector secrets. - """ - - context: ConnectorContext - - STATIC_GRADLE_OPTIONS = ("--build-cache", "--scan", "--no-watch-fs") - gradle_task_name: ClassVar[str] - - with_test_artifacts: ClassVar[bool] = False - accept_extra_params = True - - GRADLE_TIMEOUT = 3600 * 2 # 2 hour timeout by default - - @property - def gradle_task_options(self) -> Tuple[str, ...]: - if self.context.s3_build_cache_access_key_id and self.context.s3_build_cache_secret_key: - return self.STATIC_GRADLE_OPTIONS + (f"-Ds3BuildCachePrefix={self.context.connector.technical_name}",) - return self.STATIC_GRADLE_OPTIONS - - def _get_gradle_command(self, task: str, *args: Any, task_options: Optional[List[str]] = None) -> str: - task_options = task_options or [] - return f"./gradlew {' '.join(self.gradle_task_options + args)} {task} {' '.join(task_options)}" - - def check_system_requirements(self) -> None: - """ - Check if the system has all the required commands in the path. - This could be improved to check for more specific versions of the commands. - """ - required_commands_in_path = ["docker", "gradle", "jq", "xargs", "java"] - for command in required_commands_in_path: - if not shutil.which(command): - raise ValueError(f"Command {command} is not in the path") - - @property - def gradle_command(self) -> str: - connector_gradle_task = f":airbyte-integrations:connectors:{self.context.connector.technical_name}:{self.gradle_task_name}" - return self._get_gradle_command(connector_gradle_task, task_options=self.params_as_cli_options) - - def timeout_handler(self, signum: int, frame: Any) -> None: - raise GradleTimeoutError(f"Gradle operation timed out after {self.GRADLE_TIMEOUT} seconds") - - @contextmanager - def gradle_environment(self) -> Generator[None, None, None]: - """ - Context manager to set the gradle environment with timeout: - - Check if the system has all the required commands in the path. - - Set the S3 build cache environment variables if available. - - Enforces a timeout for gradle operations - - ... Add whatever setup/teardown logic needed to run a gradle task. - - Raises: - InvalidGradleEnvironment: If the gradle environment is not properly set up - GradleTimeoutError: If the gradle operation exceeds the timeout - """ - - def set_env_vars() -> Dict[str, str]: - # Set the RUN_IN_AIRBYTE_CI environment variable to True to tell gradle to use the docker image that was previously built in the airbyte-ci pipeline - env_vars = {"RUN_IN_AIRBYTE_CI": "True"} - - # Set the S3 build cache environment variables if available. - if self.context.s3_build_cache_access_key_id and self.context.s3_build_cache_secret_key: - env_vars["S3_BUILD_CACHE_ACCESS_KEY_ID"] = self.context.s3_build_cache_access_key_id.value - env_vars["S3_BUILD_CACHE_SECRET_KEY"] = self.context.s3_build_cache_secret_key.value - - for key, value in env_vars.items(): - os.environ[key] = value - return env_vars - - def unset_env_vars(env_vars: Dict[str, str]) -> None: - for key in env_vars.keys(): - del os.environ[key] - - def write_secrets(secrets: List[Secret]) -> List[Path]: - secrets_paths = [] - secrets_dir = f"{self.context.connector.code_directory}/secrets" - for secret in secrets: - secret_path = Path(f"{secrets_dir}/{secret.file_name}") - secret_path.parent.mkdir(parents=True, exist_ok=True) - secret_path.write_text(secret.value) - secrets_paths.append(secret_path) - return secrets_paths - - def remove_secrets(secrets_paths: List[Path]) -> None: - for secret_path in secrets_paths: - secret_path.unlink() - - # Set the timeout handler for gradle operations - original_timeout_handler = signal.signal(signal.SIGALRM, self.timeout_handler) - - try: - # Check if the system has all the required commands in the path. - self.check_system_requirements() - # Set env vars and write secrets - will be undone in the finally block - env_vars = set_env_vars() - secret_paths = write_secrets(self.secrets) - - # Set the timeout for gradle operations via SIGALRM - self.logger.info(f"Setting gradle timeout to {self.GRADLE_TIMEOUT} seconds") - signal.alarm(self.GRADLE_TIMEOUT) - - yield None - except GradleTimeoutError: - raise - except InvalidGradleEnvironment: - raise - except Exception as e: - # Wrap any other unexpected exceptions in GradleExecutionError - raise GradleExecutionError(f"Unexpected error during gradle execution: {str(e)}") from e - finally: - signal.alarm(0) # Disable the alarm - signal.signal(signal.SIGALRM, original_timeout_handler) # Restore original handler - unset_env_vars(env_vars) - # Remove secrets from the secrets folders only in CI - if self.context.is_ci: - remove_secrets(secret_paths) - - def _run_gradle_in_subprocess(self) -> Tuple[str, str, int]: - """ - Run a gradle command in a subprocess and stream output in real-time using non-blocking reads. - """ - try: - self.context.logger.info(f"Running gradle command: {self.gradle_command}") - process = subprocess.Popen( - self.gradle_command, - shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True, - universal_newlines=True, - ) - - # Store complete output for return value - full_stdout = [] - full_stderr = [] - - # Get file objects for stdout and stderr - stdout = process.stdout - stderr = process.stderr - - # While the process is running and we have pipes to read from - while process.poll() is None or (stdout or stderr): - # Wait for data on either pipe (timeout of 0.1 seconds) - readable, _, _ = select.select( - [stdout, stderr] if stdout and stderr else [stdout] if stdout else [stderr] if stderr else [], [], [], 0.1 - ) - - for stream in readable: - data = stream.readline() - if data: - if stream == stdout: - self.logger.info(data.rstrip()) - full_stdout.append(data) - else: - self.logger.error(data.rstrip()) - full_stderr.append(data) - else: - if stream == stdout: - stdout = None - else: - stderr = None - - returncode = process.wait() - final_stdout = "".join(full_stdout) - final_stderr = "".join(full_stderr) - - if returncode != 0: - final_stderr = f"Error while running gradle command: {self.gradle_command}\n{final_stderr}" - - return final_stdout, final_stderr, returncode - - finally: - # Ensure process is terminated if something goes wrong - if "process" in locals(): - self.logger.info("Terminating gradle process") - process.terminate() - process.wait(timeout=20) # Give it 20 seconds to terminate gracefully - try: - self.logger.info("Force killing gradle process") - process.kill() - except ProcessLookupError: - pass - - async def _run(self, *args: Any, **kwargs: Any) -> StepResult: - try: - with self.gradle_environment(): - stdout, stderr, returncode = self._run_gradle_in_subprocess() - artifacts = [] - if self.with_test_artifacts: - if test_logs := await self._collect_test_logs(): - artifacts.append(test_logs) - if test_results := await self._collect_test_results(): - artifacts.append(test_results) - step_result = StepResult( - step=self, - status=StepStatus.SUCCESS if returncode == 0 else StepStatus.FAILURE, - stdout=stdout, - stderr=stderr, - output=self.context.dagger_client.host().directory(str(self.context.connector.code_directory)), - artifacts=artifacts, - ) - return step_result - except (GradleTimeoutError, InvalidGradleEnvironment) as e: - return StepResult( - step=self, - status=StepStatus.FAILURE, - stderr=str(e), - ) - - async def _collect_test_logs(self) -> Optional[Artifact]: - """ - Exports the java docs to the host filesystem as a zip file. - The docs are expected to be in build/test-logs, and will end up test-artifact directory by default - One can change the destination directory by setting the outputs - """ - test_logs_dir_name_in_container = "test-logs" - test_logs_dir_name_in_zip = f"test-logs-{datetime.fromtimestamp(cast(float, self.context.pipeline_start_timestamp)).isoformat()}-{self.context.git_branch}-{self.gradle_task_name}".replace( - "/", "_" - ) - if ( - test_logs_dir_name_in_container - not in await self.dagger_client.host().directory(f"{self.context.connector.code_directory}/build").entries() - ): - self.context.logger.warn(f"No {test_logs_dir_name_in_container} found directory in the build folder") - return None - try: - zip_file = await dagger_directory_as_zip_file( - self.dagger_client, - await self.dagger_client.host().directory( - f"{self.context.connector.code_directory}/build/{test_logs_dir_name_in_container}" - ), - test_logs_dir_name_in_zip, - ) - return Artifact( - name=f"{test_logs_dir_name_in_zip}.zip", - content=zip_file, - content_type="application/zip", - to_upload=True, - ) - except ExecError as e: - self.context.logger.error(str(e)) - return None - - async def _collect_test_results(self) -> Optional[Artifact]: - """ - Exports the junit test results into the host filesystem as a zip file. - The docs in the container are expected to be in build/test-results, and will end up test-artifact directory by default - Only the XML files generated by junit are downloaded into the host filesystem - One can change the destination directory by setting the outputs - """ - test_results_dir_name_in_container = "test-results" - test_results_dir_name_in_zip = f"test-results-{datetime.fromtimestamp(cast(float, self.context.pipeline_start_timestamp)).isoformat()}-{self.context.git_branch}-{self.gradle_task_name}".replace( - "/", "_" - ) - if ( - test_results_dir_name_in_container - not in await self.dagger_client.host().directory(f"{self.context.connector.code_directory}/build").entries() - ): - self.context.logger.warn(f"No {test_results_dir_name_in_container} found directory in the build folder") - return None - try: - zip_file = await dagger_directory_as_zip_file( - self.dagger_client, - await self.dagger_client.host().directory( - f"{self.context.connector.code_directory}/build/{test_results_dir_name_in_container}" - ), - test_results_dir_name_in_zip, - ) - return Artifact( - name=f"{test_results_dir_name_in_zip}.zip", - content=zip_file, - content_type="application/zip", - to_upload=True, - ) - except ExecError as e: - self.context.logger.error(str(e)) - return None diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/no_op.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/no_op.py deleted file mode 100644 index 86b9712713a3..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/no_op.py +++ /dev/null @@ -1,22 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from typing import Any - -from pipelines.models.contexts.pipeline_context import PipelineContext -from pipelines.models.steps import Step, StepResult, StepStatus - - -class NoOpStep(Step): - """A step that does nothing.""" - - title = "No Op" - should_log = False - - def __init__(self, context: PipelineContext, step_status: StepStatus) -> None: - super().__init__(context) - self.step_status = step_status - - async def _run(self, *args: Any, **kwargs: Any) -> StepResult: - return StepResult(step=self, status=self.step_status) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/poetry.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/poetry.py deleted file mode 100644 index ebca7a7d612a..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/poetry.py +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from typing import List - -from pipelines.dagger.actions.python.poetry import with_poetry_module -from pipelines.models.contexts.pipeline_context import PipelineContext -from pipelines.models.steps import Step, StepResult - - -class PoetryRunStep(Step): - def __init__(self, context: PipelineContext, title: str, parent_dir_path: str, module_path: str, poetry_run_args: List[str]) -> None: - """A simple step that runs a given command inside a poetry project. - - Args: - context (PipelineContext): context of the step - title (str): name of the step - parent_dir_path (str): The path to the parent directory of the poetry project - module_path (str): The path to the poetry project - poetry_run_args (List[str]): The arguments to pass to the poetry run command - """ - self._title = title - super().__init__(context) - - parent_dir = self.context.get_repo_dir(parent_dir_path) - module_path = module_path - self.poetry_run_args = poetry_run_args - self.poetry_run_container = with_poetry_module(self.context, parent_dir, module_path).with_entrypoint(["poetry", "run"]) - - @property - def title(self) -> str: - return self._title - - async def _run(self) -> StepResult: - poetry_run_exec = self.poetry_run_container.with_exec(self.poetry_run_args, use_entrypoint=True) - return await self.get_step_result(poetry_run_exec) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/pull_request.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/pull_request.py deleted file mode 100644 index 962d4018ed73..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/pull_request.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -from typing import TYPE_CHECKING - -from pipelines.airbyte_ci.connectors.context import ConnectorContext, PipelineContext -from pipelines.helpers import github -from pipelines.models.steps import Step, StepResult, StepStatus - -if TYPE_CHECKING: - from pathlib import Path - from typing import Iterable, Optional - - -class CreateOrUpdatePullRequest(Step): - context: ConnectorContext - pull: bool - - title = "Create or update pull request on Airbyte repository" - - def __init__( - self, - context: PipelineContext, - skip_ci: bool, - labels: Optional[Iterable[str]] = None, - github_auto_merge: bool = False, - ) -> None: - super().__init__(context) - self.skip_ci = skip_ci - self.labels = labels or [] - self.github_auto_merge = github_auto_merge - - async def _run( - self, - modified_repo_files: Iterable[Path], - branch_id: str, - commit_message: str, - pr_title: str, - pr_body: str, - ) -> StepResult: - if self.context.ci_github_access_token is None: - return StepResult(step=self, status=StepStatus.FAILURE, stderr="No github access token provided") - - try: - pr = github.create_or_update_github_pull_request( - modified_repo_files, - self.context.ci_github_access_token.value, - branch_id, - commit_message, - pr_title, - pr_body, - logger=self.logger, - skip_ci=self.skip_ci, - labels=self.labels, - github_auto_merge=self.github_auto_merge, - ) - except Exception as e: - return StepResult(step=self, status=StepStatus.FAILURE, stderr=str(e), exc_info=e) - - return StepResult(step=self, status=StepStatus.SUCCESS, output=pr) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/python_registry.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/python_registry.py deleted file mode 100644 index de1829584c1e..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/steps/python_registry.py +++ /dev/null @@ -1,171 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import configparser -import io -import uuid -from enum import Enum, auto -from typing import Dict, Optional - -import tomli_w -import tomllib -from dagger import Container, Directory - -from pipelines.consts import PYPROJECT_TOML_FILE_PATH, SETUP_PY_FILE_PATH -from pipelines.dagger.actions.python.poetry import with_poetry -from pipelines.helpers.utils import sh_dash_c -from pipelines.models.contexts.python_registry_publish import PythonPackageMetadata, PythonRegistryPublishContext -from pipelines.models.steps import Step, StepResult - - -class PackageType(Enum): - POETRY = auto() - PIP = auto() - - -class PublishToPythonRegistry(Step): - context: PythonRegistryPublishContext - title = "Publish package to python registry" - max_retries = 3 - - def _get_base_container(self) -> Container: - return with_poetry(self.context) - - async def _get_package_metadata_from_pyproject_toml(self, package_dir_to_publish: Directory) -> Optional[PythonPackageMetadata]: - pyproject_toml = package_dir_to_publish.file(PYPROJECT_TOML_FILE_PATH) - pyproject_toml_content = await pyproject_toml.contents() - contents = tomllib.loads(pyproject_toml_content) - try: - return PythonPackageMetadata(contents["tool"]["poetry"]["name"], contents["tool"]["poetry"]["version"]) - except KeyError: - return None - - async def _get_package_type(self, package_dir_to_publish: Directory) -> Optional[PackageType]: - files = await package_dir_to_publish.entries() - has_pyproject_toml = PYPROJECT_TOML_FILE_PATH in files - has_setup_py = SETUP_PY_FILE_PATH in files - if has_pyproject_toml: - return PackageType.POETRY - elif has_setup_py: - return PackageType.PIP - else: - return None - - async def _run(self) -> StepResult: - package_dir_to_publish = await self.context.get_repo_dir(self.context.package_path) - package_type = await self._get_package_type(package_dir_to_publish) - - if not package_type: - return self.skip("Connector does not have a pyproject.toml file or setup.py file, skipping.") - - result = await self._ensure_package_name_and_version(package_dir_to_publish, package_type) - if result: - return result - - self.logger.info( - f"Uploading package {self.context.package_metadata.name} version {self.context.package_metadata.version} to {self.context.registry}..." - ) - - return await self._publish(package_dir_to_publish, package_type) - - async def _ensure_package_name_and_version(self, package_dir_to_publish: Directory, package_type: PackageType) -> Optional[StepResult]: - """ - Try to infer package name and version from the pyproject.toml file. If it is not present, we need to have the package name and version set. - Setup.py packages need to set package name and version as parameter. - - Returns None if package name and version are set, otherwise a StepResult with a skip message. - """ - if self.context.package_metadata.name and self.context.package_metadata.version: - return None - - if package_type is not PackageType.POETRY: - return self.skip("Connector does not have a pyproject.toml file and version and package name is not set otherwise, skipping.") - - inferred_package_metadata = await self._get_package_metadata_from_pyproject_toml(package_dir_to_publish) - - if not inferred_package_metadata: - return self.skip( - "Connector does not have a pyproject.toml file which specifies package name and version and they are not set otherwise, skipping." - ) - - if not self.context.package_metadata.name: - self.context.package_metadata.name = inferred_package_metadata.name - if not self.context.package_metadata.version: - self.context.package_metadata.version = inferred_package_metadata.version - - return None - - async def _publish(self, package_dir_to_publish: Directory, package_type: PackageType) -> StepResult: - if package_type is PackageType.PIP: - return await self._pip_publish(package_dir_to_publish) - else: - return await self._poetry_publish(package_dir_to_publish) - - async def _poetry_publish(self, package_dir_to_publish: Directory) -> StepResult: - pyproject_toml = package_dir_to_publish.file(PYPROJECT_TOML_FILE_PATH) - pyproject_toml_content = await pyproject_toml.contents() - contents = tomllib.loads(pyproject_toml_content) - # make sure package name and version are set to the configured one - contents["tool"]["poetry"]["name"] = self.context.package_metadata.name - contents["tool"]["poetry"]["version"] = self.context.package_metadata.version - # enforce consistent author - contents["tool"]["poetry"]["authors"] = ["Airbyte "] - poetry_publish = ( - self._get_base_container() - .with_secret_variable("PYTHON_REGISTRY_TOKEN", self.context.python_registry_token.as_dagger_secret(self.dagger_client)) - .with_directory("package", package_dir_to_publish) - .with_workdir("package") - .with_new_file(PYPROJECT_TOML_FILE_PATH, contents=tomli_w.dumps(contents)) - # Make sure these steps are always executed and not cached as they are triggering a side-effect (calling the registry) - # Env var setting needs to be in this block as well to make sure a change of the env var will be propagated correctly - .with_env_variable("CACHEBUSTER", str(uuid.uuid4())) - .with_exec(["poetry", "config", "repositories.mypypi", self.context.registry], use_entrypoint=True) - .with_exec(sh_dash_c(["poetry config pypi-token.mypypi $PYTHON_REGISTRY_TOKEN"])) - # Default timeout is set to 15 seconds - # We sometime face 443 HTTP read timeout responses from PyPi - # Setting it to 60 seconds to avoid transient publish failures - .with_env_variable("POETRY_REQUESTS_TIMEOUT", "60") - .with_exec(sh_dash_c(["poetry publish --build --repository mypypi -vvv --no-interaction"])) - ) - - return await self.get_step_result(poetry_publish) - - async def _pip_publish(self, package_dir_to_publish: Directory) -> StepResult: - files = await package_dir_to_publish.entries() - metadata: Dict[str, str] = { - "name": str(self.context.package_metadata.name), - "version": str(self.context.package_metadata.version), - # Enforce consistent author - "author": "Airbyte", - "author_email": "contact@airbyte.io", - } - if "README.md" in files: - metadata["long_description"] = await package_dir_to_publish.file("README.md").contents() - metadata["long_description_content_type"] = "text/markdown" - - config = configparser.ConfigParser() - config["metadata"] = metadata - - setup_cfg_io = io.StringIO() - config.write(setup_cfg_io) - setup_cfg = setup_cfg_io.getvalue() - - twine_upload = ( - self._get_base_container() - .with_exec(sh_dash_c(["apt-get update", "apt-get install -y twine"])) - .with_directory("package", package_dir_to_publish) - .with_workdir("package") - .with_exec(["sed", "-i", "/name=/d; /author=/d; /author_email=/d; /version=/d", SETUP_PY_FILE_PATH], use_entrypoint=True) - .with_new_file("setup.cfg", contents=setup_cfg) - .with_exec(["pip", "install", "--upgrade", "setuptools", "wheel"], use_entrypoint=True) - .with_exec(["python", SETUP_PY_FILE_PATH, "sdist", "bdist_wheel"], use_entrypoint=True) - # Make sure these steps are always executed and not cached as they are triggering a side-effect (calling the registry) - # Env var setting needs to be in this block as well to make sure a change of the env var will be propagated correctly - .with_env_variable("CACHEBUSTER", str(uuid.uuid4())) - .with_secret_variable("TWINE_USERNAME", self.context.dagger_client.set_secret("pypi_username", "__token__")) - .with_secret_variable("TWINE_PASSWORD", self.context.python_registry_token.as_dagger_secret(self.dagger_client)) - .with_exec(["twine", "upload", "--verbose", "--repository-url", self.context.registry, "dist/*"], use_entrypoint=True) - ) - - return await self.get_step_result(twine_upload) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/__init__.py deleted file mode 100644 index 2418143507dc..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from pathlib import Path - -INTERNAL_POETRY_PACKAGES = [ - "airbyte-ci/connectors/auto_merge", - "airbyte-ci/connectors/pipelines", - "airbyte-ci/connectors/connectors_insights", - "airbyte-ci/connectors/connector_ops", - "airbyte-ci/connectors/ci_credentials", - "airbyte-ci/connectors/erd", - "airbyte-ci/connectors/live-tests", - "airbyte-ci/connectors/metadata_service/lib", - "airbyte-integrations/bases/connector-acceptance-test", -] - -INTERNAL_POETRY_PACKAGES_PATH = [Path(package) for package in INTERNAL_POETRY_PACKAGES] diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/commands.py deleted file mode 100644 index 15ec6831423b..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/commands.py +++ /dev/null @@ -1,131 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -from typing import TYPE_CHECKING - -import asyncclick as click -import asyncer - -from pipelines.airbyte_ci.test import INTERNAL_POETRY_PACKAGES, INTERNAL_POETRY_PACKAGES_PATH, pipeline -from pipelines.cli.click_decorators import click_ci_requirements_option, click_ignore_unused_kwargs, click_merge_args_into_context_obj -from pipelines.helpers.git import get_modified_files -from pipelines.helpers.utils import transform_strs_to_paths -from pipelines.models.contexts.click_pipeline_context import ClickPipelineContext, pass_pipeline_context -from pipelines.models.steps import StepStatus - -if TYPE_CHECKING: - from pathlib import Path - from typing import List, Set, Tuple - - -async def find_modified_internal_packages(pipeline_context: ClickPipelineContext) -> Set[Path]: - """Finds the modified internal packages according to the modified files on the branch/commit. - - Args: - pipeline_context (ClickPipelineContext): The context object. - - Returns: - Set[Path]: The set of modified internal packages. - """ - modified_files = transform_strs_to_paths( - await get_modified_files( - pipeline_context.params["git_branch"], - pipeline_context.params["git_revision"], - pipeline_context.params["diffed_branch"], - pipeline_context.params["is_local"], - pipeline_context.params["ci_context"], - git_repo_url=pipeline_context.params["git_repo_url"], - ) - ) - modified_packages = set() - for modified_file in modified_files: - for internal_package in INTERNAL_POETRY_PACKAGES_PATH: - if modified_file.is_relative_to(internal_package): - modified_packages.add(internal_package) - return modified_packages - - -async def get_packages_to_run(pipeline_context: ClickPipelineContext) -> Set[Path]: - """Gets the packages to run the poe tasks on. - - Args: - pipeline_context (ClickPipelineContext): The context object. - - Raises: - click.ClickException: If no packages are specified to run the poe tasks on. - - Returns: - Set[Path]: The set of packages to run the poe tasks on. - """ - if not pipeline_context.params["poetry_package_paths"] and not pipeline_context.params["modified"]: - raise click.ClickException("You must specify at least one package to test.") - - poetry_package_paths = set() - if pipeline_context.params["modified"]: - poetry_package_paths = await find_modified_internal_packages(pipeline_context) - - return poetry_package_paths.union(set(pipeline_context.params["poetry_package_paths"])) - - -def crash_on_any_failure(poetry_package_poe_tasks_results: List[Tuple[Path, asyncer.SoonValue]]) -> None: - """Fail the command if any of the poe tasks failed. - - Args: - poetry_package_poe_tasks_results (List[Tuple[Path, asyncer.SoonValue]]): The results of the poe tasks. - - Raises: - click.ClickException: If any of the poe tasks failed. - """ - failed_packages = set() - for poetry_package_paths, package_result in poetry_package_poe_tasks_results: - poe_command_results = package_result.value - if any([result.status is StepStatus.FAILURE for result in poe_command_results]): - failed_packages.add(poetry_package_paths) - if failed_packages: - raise click.ClickException( - f"The following packages failed to run poe tasks: {', '.join([str(package_path) for package_path in failed_packages])}" - ) - return None - - -@click.command() -@click.option("--modified", default=False, is_flag=True, help="Run on modified internal packages.") -@click.option( - "--poetry-package-path", - "-p", - "poetry_package_paths", - help="The path to the poetry package to test.", - type=click.Choice(INTERNAL_POETRY_PACKAGES), - multiple=True, -) -@click_ci_requirements_option() -@click_merge_args_into_context_obj -@pass_pipeline_context -@click_ignore_unused_kwargs -# TODO this command should be renamed ci and go under the poetry command group -# e.g. airbyte-ci poetry ci --poetry-package-path airbyte-ci/connectors/pipelines -async def test(pipeline_context: ClickPipelineContext) -> None: - """Runs the tests for the given airbyte-ci package - - Args: - pipeline_context (ClickPipelineContext): The context object. - """ - poetry_package_paths = await get_packages_to_run(pipeline_context) - click.echo(f"Running poe tasks of the following packages: {', '.join([str(package_path) for package_path in poetry_package_paths])}") - dagger_client = await pipeline_context.get_dagger_client() - - poetry_package_poe_tasks_results: List[Tuple[Path, asyncer.SoonValue]] = [] - async with asyncer.create_task_group() as poetry_packages_task_group: - for poetry_package_path in poetry_package_paths: - poetry_package_poe_tasks_results.append( - ( - poetry_package_path, - poetry_packages_task_group.soonify(pipeline.run_poe_tasks_for_package)( - dagger_client, poetry_package_path, pipeline_context.params - ), - ) - ) - - crash_on_any_failure(poetry_package_poe_tasks_results) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/models.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/models.py deleted file mode 100644 index e5b2aae93c6a..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/models.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -import os -from typing import Dict, List, Set - -from pydantic import BaseModel, Field, validator - - -class AirbyteCiPackageConfiguration(BaseModel): - poe_tasks: Set[str] = Field(..., description="List of unique poe tasks to run") - required_environment_variables: Set[str] = Field( - set(), description="List of unique required environment variables to pass to the container running the poe task" - ) - poetry_extras: Set[str] = Field(set(), description="List of unique poetry extras to install") - optional_poetry_groups: Set[str] = Field(set(), description="List of unique poetry groups to install") - side_car_docker_engine: bool = Field( - False, description="Flag indicating the use of a sidecar Docker engine during the poe task executions" - ) - mount_docker_socket: bool = Field( - False, - description="Flag indicating the mount of the host docker socket to the container running the poe task, useful when the package under test is using dagger", - ) - python_versions: List[str] = Field(description="List of unique python versions to run the poe tasks on") - - @validator("required_environment_variables") - def check_required_environment_variables_are_set(cls, value: Set) -> Set: - for required_env_var in value: - if required_env_var not in os.environ: - raise ValueError(f"Environment variable {required_env_var} is not set.") - return value - - -def deserialize_airbyte_ci_config(pyproject_toml: Dict) -> AirbyteCiPackageConfiguration: - try: - airbyte_ci_config = pyproject_toml["tool"]["airbyte_ci"] - except KeyError: - raise ValueError("Missing tool.airbyte_ci configuration in pyproject.toml") - return AirbyteCiPackageConfiguration.parse_obj(airbyte_ci_config) diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/pipeline.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/pipeline.py deleted file mode 100644 index ef0a14199396..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/test/pipeline.py +++ /dev/null @@ -1,355 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -import logging -import os -from typing import TYPE_CHECKING - -import asyncer -import dagger -import toml - -from pipelines.airbyte_ci.test.models import deserialize_airbyte_ci_config -from pipelines.consts import DOCKER_HOST_NAME, DOCKER_HOST_PORT, DOCKER_VERSION, POETRY_CACHE_VOLUME_NAME, PYPROJECT_TOML_FILE_PATH -from pipelines.dagger.actions.system import docker -from pipelines.helpers.github import update_commit_status_check -from pipelines.helpers.utils import sh_dash_c -from pipelines.models.steps import PoeTaskResult, StepStatus - -if TYPE_CHECKING: - from logging import Logger - from pathlib import Path - from typing import Dict, List - - from pipelines.airbyte_ci.test.models import AirbyteCiPackageConfiguration - -# The following directories are always mounted because a lot of tests rely on them -DIRECTORIES_TO_ALWAYS_MOUNT = [ - ".git", # This is needed as some package tests rely on being in a git repo - ".github", - "docs", - "airbyte-integrations", - "airbyte-ci", - "airbyte-cdk", - PYPROJECT_TOML_FILE_PATH, - "LICENSE_SHORT", - "poetry.lock", - "spotless-maven-pom.xml", - "tools/gradle/codestyle/java-google-style.xml", -] - -DEFAULT_EXCLUDE = ["**/__pycache__", "**/.pytest_cache", "**/.venv", "**.log", "**/.gradle"] - -DEFAULT_CONTAINER_IMAGE = "python:{version}" - -VERSION_CONTAINER_IMAGES = { - "3.10": DEFAULT_CONTAINER_IMAGE.format(version="3.10.12"), - "3.11": DEFAULT_CONTAINER_IMAGE.format(version="3.11.9"), -} - - -async def get_filtered_airbyte_repo_dir(dagger_client: dagger.Client, poetry_package_path: Path) -> dagger.Directory: - """Get a filtered airbyte repo directory with the directories to always mount and the poetry package path. - - Args: - dagger_client (dagger.Client): Dagger client. - poetry_package_path (Path): Path to the poetry package in the airbyte repo. - - Returns: - dagger.Directory: The filtered airbyte repo directory. - """ - directories_to_mount = list(set([str(poetry_package_path), *DIRECTORIES_TO_ALWAYS_MOUNT])) - return dagger_client.host().directory( - ".", - exclude=DEFAULT_EXCLUDE, - include=directories_to_mount, - ) - - -async def get_poetry_package_dir(airbyte_repo_dir: dagger.Directory, poetry_package_path: Path) -> dagger.Directory: - """Get the poetry package directory from the airbyte repo directory. - - Args: - airbyte_repo_dir (dagger.Directory): The airbyte repo directory. - poetry_package_path (Path): Path to the poetry package in the airbyte repo. - - Raises: - FileNotFoundError: If the pyproject.toml file is not found in the poetry package directory. - FileNotFoundError: If the poetry package directory is not found in the airbyte repo directory. - - Returns: - dagger.Directory: The poetry package directory. - """ - try: - package_directory = await airbyte_repo_dir.directory(str(poetry_package_path)) - if PYPROJECT_TOML_FILE_PATH not in await package_directory.entries(): - raise FileNotFoundError(f"Could not find pyproject.toml in {poetry_package_path}, are you sure this is a poetry package?") - except dagger.DaggerError: - raise FileNotFoundError(f"Could not find {poetry_package_path} in the repository, are you sure this path is correct?") - return package_directory - - -async def get_airbyte_ci_package_config(poetry_package_dir: dagger.Directory) -> AirbyteCiPackageConfiguration: - """Get the airbyte ci package configuration from the pyproject.toml file in the poetry package directory. - - Args: - poetry_package_dir (dagger.Directory): The poetry package directory. - - Returns: - AirbyteCiPackageConfiguration: The airbyte ci package configuration. - """ - raw_pyproject_toml = await poetry_package_dir.file(PYPROJECT_TOML_FILE_PATH).contents() - pyproject_toml = toml.loads(raw_pyproject_toml) - return deserialize_airbyte_ci_config(pyproject_toml) - - -def get_poetry_base_container(dagger_client: dagger.Client, python_version: str) -> dagger.Container: - """Get a base container with system dependencies to run poe tasks of poetry package: - - git: required for packages using GitPython - - poetry - - poethepoet - - docker: required for packages using docker in their tests - - Args: - dagger_client (dagger.Client): The dagger client. - - Returns: - dagger.Container: The base container. - """ - poetry_cache_volume: dagger.CacheVolume = dagger_client.cache_volume(POETRY_CACHE_VOLUME_NAME) - poetry_cache_path = "/root/.cache/poetry" - container_image = VERSION_CONTAINER_IMAGES.get(python_version, DEFAULT_CONTAINER_IMAGE.format(version=python_version)) - return ( - dagger_client.container() - .from_(container_image) - .with_env_variable("PIPX_BIN_DIR", "/usr/local/bin") - .with_env_variable("POETRY_CACHE_DIR", poetry_cache_path) - .with_mounted_cache(poetry_cache_path, poetry_cache_volume) - .with_exec( - sh_dash_c( - [ - "apt-get update", - "apt-get install -y bash git curl", - "pip install pipx", - "pipx ensurepath", - "pipx install poetry", - "pipx install poethepoet", - ] - ) - ) - .with_env_variable("VERSION", DOCKER_VERSION) - .with_exec(sh_dash_c(["curl -fsSL https://get.docker.com | sh"])) - ) - - -def prepare_container_for_poe_tasks( - dagger_client: dagger.Client, - airbyte_repo_dir: dagger.Directory, - airbyte_ci_package_config: AirbyteCiPackageConfiguration, - poetry_package_path: Path, - pipeline_context_params: Dict, - python_version: str, -) -> dagger.Container: - """Prepare a container to run poe tasks for a poetry package. - - Args: - dagger_client (dagger.Client): The dagger client. - airbyte_repo_dir (dagger.Directory): The airbyte repo directory. - airbyte_ci_package_config (AirbyteCiPackageConfiguration): The airbyte ci package configuration. - poetry_package_path (Path): The path to the poetry package in the airbyte repo. - pipeline_context_params (Dict): The pipeline context parameters. - - Returns: - dagger.Container: The container to run poe tasks for the poetry package. - """ - - # BE CAREFUL ABOUT THE ORDER OF THESE INSTRUCTIONS - # PLEASE REMIND THAT DAGGER OPERATION ARE CACHED LIKE IN DOCKERFILE: - # ANY CHANGE IN THE INPUTS OF AN OPERATION WILL INVALIDATE THE DOWNSTREAM OPERATIONS CACHE - - # Start from the base container - container = get_poetry_base_container(dagger_client, python_version) - - # Set the CI environment variable - is_ci = pipeline_context_params["is_ci"] - if is_ci: - container = container.with_env_variable("CI", "true") - - # Bind to dockerd service if needed - if airbyte_ci_package_config.side_car_docker_engine: - dockerd_service = docker.with_global_dockerd_service(dagger_client) - container = ( - container.with_env_variable("DOCKER_HOST", f"tcp://{DOCKER_HOST_NAME}:{DOCKER_HOST_PORT}") - .with_env_variable("DOCKER_HOST_NAME", DOCKER_HOST_NAME) - .with_service_binding(DOCKER_HOST_NAME, dockerd_service) - ) - - # Mount the docker socket if needed - if airbyte_ci_package_config.mount_docker_socket: - container = container.with_unix_socket("/var/run/docker.sock", dagger_client.host().unix_socket("/var/run/docker.sock")) - - # Set the required environment variables according to the package configuration - for required_env_var in airbyte_ci_package_config.required_environment_variables: - # We consider any environment variable as a secret for safety reasons - secret_env_var = dagger_client.set_secret(required_env_var, os.environ[required_env_var]) - container = container.with_secret_variable(required_env_var, secret_env_var) - - # Mount the airbyte repo directory - container = container.with_mounted_directory("/airbyte", airbyte_repo_dir) - - # Set working directory to the poetry package directory - container = container.with_workdir(f"/airbyte/{poetry_package_path}") - - # If a package from `airbyte-platform-internal` is required, modify the entry in pyproject.toml to use https instead of ssh, - # when run in Github Actions - # This is currently required for getting the connection-retriever package, for regression tests. - if is_ci: - container = ( - container.with_exec( - [ - "sed", - "-i", - "-E", - r"s,git@github\.com:airbytehq/airbyte-platform-internal,https://github.com/airbytehq/airbyte-platform-internal.git,", - "pyproject.toml", - ], - use_entrypoint=True, - ) - .with_exec( - [ - "poetry", - "source", - "add", - "--priority=supplemental", - "airbyte-platform-internal-source", - "https://github.com/airbytehq/airbyte-platform-internal.git", - ], - use_entrypoint=True, - ) - .with_secret_variable( - "CI_GITHUB_ACCESS_TOKEN", - dagger_client.set_secret("CI_GITHUB_ACCESS_TOKEN", pipeline_context_params["ci_github_access_token"].value), - ) - .with_exec( - [ - "/bin/sh", - "-c", - "poetry config http-basic.airbyte-platform-internal-source octavia-squidington-iii $CI_GITHUB_ACCESS_TOKEN", - ], - use_entrypoint=True, - ) - .with_exec(["poetry", "lock"], use_entrypoint=True) - ) - - # Install the poetry package - container = container.with_exec( - ["poetry", "install"] - + [f"--with={group}" for group in airbyte_ci_package_config.optional_poetry_groups] - + [f"--extras={extra}" for extra in airbyte_ci_package_config.poetry_extras] - ) - return container - - -async def run_poe_task(container: dagger.Container, poe_task: str) -> PoeTaskResult: - """Run the poe task in the container and return a PoeTaskResult. - - Args: - container (dagger.Container): The container to run the poe task in. - poe_task (str): The poe task to run. - - Returns: - PoeTaskResult: The result of the command execution. - """ - try: - executed_container = await container.with_exec(["poe", poe_task], use_entrypoint=True) - return PoeTaskResult( - task_name=poe_task, - status=StepStatus.SUCCESS, - stdout=await executed_container.stdout(), - stderr=await executed_container.stderr(), - ) - except dagger.ExecError as e: - return PoeTaskResult(task_name=poe_task, status=StepStatus.FAILURE, exc_info=e) - - -async def run_and_log_poe_task_results( - pipeline_context_params: Dict, package_name: str, container: dagger.Container, poe_task: str, logger: Logger -) -> PoeTaskResult: - """Run the poe task in the container and log the result. - - Args: - pipeline_context_params (Dict): The pipeline context parameters. - package_name (str): The name of the package to run the poe task for. - container (dagger.Container): The container to run the poe task in. - poe_task (str): The poe task to run. - logger (Logger): The logger to log the result. - - Returns: - PoeTaskResult: The result of the command execution. - """ - - commit_status_check_params = { - "sha": pipeline_context_params["git_revision"], - "description": f"{poe_task} execution for {package_name}", - "context": f"{package_name} - {poe_task}", - "target_url": f"{pipeline_context_params['gha_workflow_run_url']}", - "should_send": pipeline_context_params["is_ci"], - "logger": logger, - } - - logger.info(f"Running poe task: {poe_task}") - # Send pending status check - update_commit_status_check(**{**commit_status_check_params, "state": "pending"}) - result = await run_poe_task(container, poe_task) - result.log(logger) - # Send the final status check - update_commit_status_check(**{**commit_status_check_params, "state": result.status.get_github_state()}) - - return result - - -async def run_poe_tasks_for_package( - dagger_client: dagger.Client, poetry_package_path: Path, pipeline_context_params: Dict -) -> List[PoeTaskResult]: - """Concurrently Run the poe tasks declared in pyproject.toml for a poetry package. - - Args: - dagger_client (dagger.Client): The dagger client. - poetry_package_path (Path): The path to the poetry package in the airbyte repo. - pipeline_context_params (Dict): The pipeline context parameters. - Returns: - List[PoeTaskResult]: The results of the poe tasks. - """ - dagger_client = dagger_client - airbyte_repo_dir = await get_filtered_airbyte_repo_dir(dagger_client, poetry_package_path) - package_dir = await get_poetry_package_dir(airbyte_repo_dir, poetry_package_path) - package_config = await get_airbyte_ci_package_config(package_dir) - - logger = logging.getLogger(str(poetry_package_path)) - - if not package_config.poe_tasks: - logger.warning("No poe tasks to run.") - return [] - - logger.info(f"Python versions: {package_config.python_versions}") - - poe_task_results: List[asyncer.SoonValue] = [] - return_results = [] - - for python_version in package_config.python_versions: - container = prepare_container_for_poe_tasks( - dagger_client, airbyte_repo_dir, package_config, poetry_package_path, pipeline_context_params, python_version - ) - - async with asyncer.create_task_group() as poe_tasks_task_group: - for task in package_config.poe_tasks: - poe_task_results.append( - poe_tasks_task_group.soonify(run_and_log_poe_task_results)( - pipeline_context_params, str(poetry_package_path), container, task, logger.getChild(f"@{python_version}") - ) - ) - - return_results.extend([result.value for result in poe_task_results]) - - return return_results diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/update/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/update/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/update/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/update/commands.py b/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/update/commands.py deleted file mode 100644 index 690c5ae56f94..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/update/commands.py +++ /dev/null @@ -1,24 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import logging - -import asyncclick as click - -from pipelines.cli.auto_update import is_dev_command -from pipelines.external_scripts.airbyte_ci_dev_install import main as install_airbyte_ci_dev_pipx -from pipelines.external_scripts.airbyte_ci_install import main as install_airbyte_ci_binary - - -@click.command() -@click.option("--version", default="latest", type=str, help="The version to update to.") -async def update(version: str) -> None: - """Updates airbyte-ci to the latest version.""" - is_dev = is_dev_command() - if is_dev: - logging.info("Updating to the latest development version of airbyte-ci...") - install_airbyte_ci_dev_pipx() - else: - logging.info("Updating to the latest version of airbyte-ci...") - install_airbyte_ci_binary(version) diff --git a/airbyte-ci/connectors/pipelines/pipelines/cli/airbyte_ci.py b/airbyte-ci/connectors/pipelines/pipelines/cli/airbyte_ci.py deleted file mode 100644 index ca06ffeab448..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/cli/airbyte_ci.py +++ /dev/null @@ -1,218 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""This module is the CLI entrypoint to the airbyte-ci commands.""" - -from __future__ import annotations - -# HACK! IMPORTANT! This import and function call must be the first import in this file -# This is needed to ensure that the working directory is the root of the airbyte repo -# ruff: noqa: E402 -from pipelines.cli.ensure_repo_root import set_working_directory_to_root - -set_working_directory_to_root() - -import logging -import multiprocessing -import os -import sys -from typing import Optional - -import asyncclick as click -import docker # type: ignore -from github import PullRequest - -from pipelines import main_logger -from pipelines.cli.auto_update import __installed_version__, check_for_upgrade, pre_confirm_auto_update_flag -from pipelines.cli.click_decorators import ( - CI_REQUIREMENTS_OPTION_NAME, - click_append_to_context_object, - click_ci_requirements_option, - click_ignore_unused_kwargs, - click_merge_args_into_context_obj, -) -from pipelines.cli.confirm_prompt import pre_confirm_all_flag -from pipelines.cli.lazy_group import LazyGroup -from pipelines.cli.secrets import wrap_gcp_credentials_in_secret, wrap_in_secret -from pipelines.cli.telemetry import click_track_command -from pipelines.consts import DAGGER_WRAP_ENV_VAR_NAME, LOCAL_BUILD_PLATFORM, CIContext -from pipelines.dagger.actions.connector.hooks import get_dagger_sdk_version -from pipelines.helpers import github -from pipelines.helpers.git import get_current_git_branch, get_current_git_revision -from pipelines.helpers.github import AIRBYTE_GITHUB_REPO_URL, AIRBYTE_GITHUB_REPO_URL_PREFIX -from pipelines.helpers.utils import get_current_epoch_time -from pipelines.models.secrets import InMemorySecretStore - - -def log_context_info(ctx: click.Context) -> None: - main_logger.info(f"Running airbyte-ci version {__installed_version__}") - main_logger.info(f"Running dagger version {get_dagger_sdk_version()}") - main_logger.info("Running airbyte-ci in CI mode.") - main_logger.info(f"CI Context: {ctx.obj['ci_context']}") - main_logger.info(f"CI Report Bucket Name: {ctx.obj['ci_report_bucket_name']}") - main_logger.info(f"Git Repo URL: {ctx.obj['git_repo_url']}") - main_logger.info(f"Git Branch: {ctx.obj['git_branch']}") - main_logger.info(f"Git Revision: {ctx.obj['git_revision']}") - main_logger.info(f"GitHub Workflow Run ID: {ctx.obj['gha_workflow_run_id']}") - main_logger.info(f"GitHub Workflow Run URL: {ctx.obj['gha_workflow_run_url']}") - main_logger.info(f"Pull Request Number: {ctx.obj['pull_request_number']}") - main_logger.info(f"Pipeline Start Timestamp: {ctx.obj['pipeline_start_timestamp']}") - main_logger.info(f"Local build platform: {LOCAL_BUILD_PLATFORM}") - - -def _get_gha_workflow_run_url(ctx: click.Context) -> Optional[str]: - gha_workflow_run_id = ctx.obj["gha_workflow_run_id"] - if not gha_workflow_run_id: - return None - - return f"{AIRBYTE_GITHUB_REPO_URL_PREFIX}/actions/runs/{gha_workflow_run_id}" - - -def _get_pull_request(ctx: click.Context) -> Optional[PullRequest.PullRequest]: - pull_request_number = ctx.obj["pull_request_number"] - ci_github_access_token = ctx.obj["ci_github_access_token"] - - can_get_pull_request = pull_request_number and ci_github_access_token - if not can_get_pull_request: - return None - return github.get_pull_request(pull_request_number, ci_github_access_token) - - -def check_local_docker_configuration() -> None: - try: - docker_client = docker.from_env() - except Exception as e: - raise click.UsageError(f"Could not connect to docker daemon: {e}") - daemon_info = docker_client.info() - docker_cpus_count = daemon_info["NCPU"] - local_cpus_count = multiprocessing.cpu_count() - if docker_cpus_count < local_cpus_count: - logging.warning( - f"Your docker daemon is configured with less CPUs than your local machine ({docker_cpus_count} vs. {local_cpus_count}). This may slow down the airbyte-ci execution. Please consider increasing the number of CPUs allocated to your docker daemon in the Resource Allocation settings of Docker." - ) - - -def is_dagger_run_enabled_by_default() -> bool: - if CI_REQUIREMENTS_OPTION_NAME in sys.argv: - return False - - dagger_run_by_default = [ - ["connectors", "test"], - ["connectors", "build"], - ["test"], - ["metadata_service"], - ] - - for command_tokens in dagger_run_by_default: - if all(token in sys.argv for token in command_tokens): - return True - - return False - - -def check_dagger_wrap() -> bool: - """ - Check if the command is already wrapped by dagger run. - This is useful to avoid infinite recursion when calling dagger run from dagger run. - """ - return os.getenv(DAGGER_WRAP_ENV_VAR_NAME) == "true" - - -def is_current_process_wrapped_by_dagger_run() -> bool: - """ - Check if the current process is wrapped by dagger run. - """ - called_with_dagger_run = check_dagger_wrap() - main_logger.info(f"Called with dagger run: {called_with_dagger_run}") - return called_with_dagger_run - - -# COMMANDS - - -@click.group( - cls=LazyGroup, - help="Airbyte CI top-level command group.", - lazy_subcommands={ - "connectors": "pipelines.airbyte_ci.connectors.commands.connectors", - "poetry": "pipelines.airbyte_ci.poetry.commands.poetry", - "metadata": "pipelines.airbyte_ci.metadata.commands.metadata", - "test": "pipelines.airbyte_ci.test.commands.test", - "update": "pipelines.airbyte_ci.update.commands.update", - }, -) -@click.version_option(__installed_version__) -@pre_confirm_all_flag -@pre_confirm_auto_update_flag -@click.option("--enable-dagger-run/--disable-dagger-run", default=is_dagger_run_enabled_by_default) -@click.option("--enable-update-check/--disable-update-check", default=True) -@click.option("--enable-auto-update/--disable-auto-update", default=True) -@click.option("--is-local/--is-ci", default=True) -@click.option("--git-repo-url", default=AIRBYTE_GITHUB_REPO_URL, envvar="CI_GIT_REPO_URL") -@click.option("--git-branch", default=get_current_git_branch, envvar="CI_GIT_BRANCH") -@click.option("--git-revision", default=get_current_git_revision, envvar="CI_GIT_REVISION") -@click.option( - "--diffed-branch", - help="Branch to which the git diff will happen to detect new or modified connectors", - default="master", - type=str, -) -@click.option("--gha-workflow-run-id", help="[CI Only] The run id of the GitHub action workflow", default=None, type=str) -@click.option("--ci-context", default=CIContext.MANUAL, envvar="CI_CONTEXT", type=click.Choice([c for c in CIContext])) -@click.option("--pipeline-start-timestamp", default=get_current_epoch_time, envvar="CI_PIPELINE_START_TIMESTAMP", type=int) -@click.option("--pull-request-number", envvar="PULL_REQUEST_NUMBER", type=int) -@click.option("--ci-git-user", default="octavia-squidington-iii", envvar="CI_GIT_USER", type=str) -@click.option("--ci-github-access-token", envvar="CI_GITHUB_ACCESS_TOKEN", type=str, callback=wrap_in_secret) -@click.option("--ci-report-bucket-name", envvar="CI_REPORT_BUCKET_NAME", type=str) -@click.option("--ci-artifact-bucket-name", envvar="CI_ARTIFACT_BUCKET_NAME", type=str) -@click.option( - "--ci-gcp-credentials", - help="The service account to use during CI.", - type=click.STRING, - required=False, # Not required for pre-release or local pipelines - envvar="GCP_GSM_CREDENTIALS", - callback=wrap_gcp_credentials_in_secret, -) -@click.option("--ci-job-key", envvar="CI_JOB_KEY", type=str) -@click.option("--s3-build-cache-access-key-id", envvar="S3_BUILD_CACHE_ACCESS_KEY_ID", type=str, callback=wrap_in_secret) -@click.option("--s3-build-cache-secret-key", envvar="S3_BUILD_CACHE_SECRET_KEY", type=str, callback=wrap_in_secret) -@click.option("--show-dagger-logs/--hide-dagger-logs", default=False, type=bool) -@click_ci_requirements_option() -@click_track_command -@click_merge_args_into_context_obj -@click_append_to_context_object("is_ci", lambda ctx: not ctx.obj["is_local"]) -@click_append_to_context_object("gha_workflow_run_url", _get_gha_workflow_run_url) -@click_append_to_context_object("pull_request", _get_pull_request) -@click.pass_context -@click_ignore_unused_kwargs -async def airbyte_ci(ctx: click.Context) -> None: # noqa D103 - # Check that the command being run is not upgrade - is_update_command = ctx.invoked_subcommand == "update" - if ctx.obj["enable_update_check"] and ctx.obj["is_local"] and not is_update_command: - check_for_upgrade( - require_update=ctx.obj["is_local"], - enable_auto_update=ctx.obj["is_local"] and ctx.obj["enable_auto_update"], - ) - - if ctx.obj["enable_dagger_run"] and not is_current_process_wrapped_by_dagger_run(): - main_logger.debug("Re-Running airbyte-ci with dagger run.") - from pipelines.cli.dagger_run import call_current_command_with_dagger_run - - call_current_command_with_dagger_run() - return - - if ctx.obj["is_local"]: - # This check is meaningful only when running locally - # In our CI the docker host used by the Dagger Engine is different from the one used by the runner. - check_local_docker_configuration() - - if not ctx.obj["is_local"]: - log_context_info(ctx) - - if not ctx.obj.get("secret_stores", {}).get("in_memory"): - ctx.obj["secret_stores"] = {"in_memory": InMemorySecretStore()} - - -if __name__ == "__main__": - airbyte_ci() diff --git a/airbyte-ci/connectors/pipelines/pipelines/cli/auto_update.py b/airbyte-ci/connectors/pipelines/pipelines/cli/auto_update.py deleted file mode 100644 index 6f7c16bae0ca..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/cli/auto_update.py +++ /dev/null @@ -1,145 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -# HELPERS -from __future__ import annotations - -import importlib -import logging -import os -import sys -from typing import TYPE_CHECKING - -import asyncclick as click -import requests - -from pipelines import main_logger -from pipelines.cli.confirm_prompt import confirm -from pipelines.consts import LOCAL_PIPELINE_PACKAGE_PATH -from pipelines.external_scripts.airbyte_ci_install import RELEASE_URL, get_airbyte_os_name - -if TYPE_CHECKING: - from typing import Callable - -__installed_version__ = importlib.metadata.version("pipelines") - -PROD_COMMAND = "airbyte-ci" -DEV_COMMAND = "airbyte-ci-dev" -AUTO_UPDATE_AGREE_KEY = "yes_auto_update" - - -def pre_confirm_auto_update_flag(f: Callable) -> Callable: - """Decorator to add a --yes-auto-update flag to a command.""" - return click.option( - "--yes-auto-update/--no-auto-update", - AUTO_UPDATE_AGREE_KEY, - is_flag=True, - default=True, - help="Skip prompts and automatically upgrade pipelines", - )(f) - - -def _is_version_available(version: str, is_dev: bool) -> bool: - """ - Check if an given version is available. - """ - - # Given that they can install from source, we don't need to check for upgrades - if is_dev: - return True - - os_name = get_airbyte_os_name() - url = f"{RELEASE_URL}/{os_name}/{version}/airbyte-ci" - - # Just check if the URL exists, but dont download it - return requests.head(url).ok - - -def _get_latest_version() -> str: - """ - Get the version of the latest release, which is just in the pyproject.toml file of the pipelines package - as this is an internal tool, we don't need to check for the latest version on PyPI - """ - path_to_pyproject_toml = LOCAL_PIPELINE_PACKAGE_PATH + "pyproject.toml" - with open(path_to_pyproject_toml, "r") as f: - for line in f.readlines(): - if "version" in line: - return line.split("=")[1].strip().replace('"', "") - raise Exception("Could not find version in pyproject.toml. Please ensure you are running from the root of the airbyte repo.") - - -def is_dev_command() -> bool: - """ - Check if the current command is the dev version of the command - """ - current_command = " ".join(sys.argv) - return DEV_COMMAND in current_command - - -def check_for_upgrade( - require_update: bool = True, - enable_auto_update: bool = True, -) -> None: - """Check if the installed version of pipelines is up to date.""" - current_command = " ".join(sys.argv) - latest_version = _get_latest_version() - is_out_of_date = latest_version > __installed_version__ - if not is_out_of_date: - main_logger.info(f"airbyte-ci is up to date. Installed version: {__installed_version__}. Latest version: {latest_version}") - return - - is_dev_version = is_dev_command() - upgrade_available = _is_version_available(latest_version, is_dev_version) - if not upgrade_available: - main_logger.warning( - f"airbyte-ci is out of date, but no upgrade is available yet. This likely means that a release is still being built. Installed version: {__installed_version__}. Latest version: {latest_version}" - ) - return - - parent_command = DEV_COMMAND if is_dev_version else PROD_COMMAND - upgrade_command = f"{parent_command} update" - - # Tack on the specific version if it is not the latest version and it is not the dev version - # This is because the dev version always corresponds to the version in the local repository - if not is_dev_version: - upgrade_command = f"{upgrade_command} --version {latest_version}" - - upgrade_error_message = f""" - 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨 - - This version of `airbyte-ci` does not match that of your local airbyte repository. - - Installed Version: {__installed_version__}. - Local Repository Version: {latest_version} - - Please upgrade your local airbyte repository to the latest version using the following command: - $ {upgrade_command} - - Alternatively you can skip this with the `--disable-update-check` flag. - - 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨 - """ - logging.warning(upgrade_error_message) - - # Ask the user if they want to upgrade - if enable_auto_update and confirm( - "Do you want to automatically upgrade?", default=True, additional_pre_confirm_key=AUTO_UPDATE_AGREE_KEY - ): - # if the current command contains `airbyte-ci-dev` is the dev version of the command - logging.info(f"[{'DEV' if is_dev_version else 'BINARY'}] Upgrading pipelines...") - - upgrade_exit_code = os.system(upgrade_command) - if upgrade_exit_code != 0: - raise Exception(f"Failed to upgrade pipelines. Exit code: {upgrade_exit_code}") - - logging.info(f"Re-running command: {current_command}") - - # Re-run the command - command_exit_code = os.system(current_command) - sys.exit(command_exit_code) - - if require_update: - raise Exception(upgrade_error_message) - - return diff --git a/airbyte-ci/connectors/pipelines/pipelines/cli/click_decorators.py b/airbyte-ci/connectors/pipelines/pipelines/cli/click_decorators.py deleted file mode 100644 index 7ede57342b7b..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/cli/click_decorators.py +++ /dev/null @@ -1,153 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import functools -import inspect -from functools import wraps -from typing import Any, Callable, Type, TypeVar - -import asyncclick as click - -from pipelines.models.ci_requirements import CIRequirements - -_AnyCallable = Callable[..., Any] -FC = TypeVar("FC", bound="_AnyCallable | click.core.Command") -CI_REQUIREMENTS_OPTION_NAME = "--ci-requirements" - - -def _contains_var_kwarg(f: Callable) -> bool: - return any(param.kind is inspect.Parameter.VAR_KEYWORD for param in inspect.signature(f).parameters.values()) - - -def _is_kwarg_of(key: str, f: Callable) -> bool: - param = inspect.signature(f).parameters.get(key) - if not param: - return False - - return bool(param) and (param.kind is inspect.Parameter.KEYWORD_ONLY or param.kind is inspect.Parameter.POSITIONAL_OR_KEYWORD) - - -def click_ignore_unused_kwargs(f: Callable) -> Callable: - """Make function ignore unmatched kwargs. - - If the function already has the catch all **kwargs, do nothing. - - Useful in the case that the argument is meant to be passed to a child command - and is not used by the parent command - """ - if _contains_var_kwarg(f): - return f - - @functools.wraps(f) - def inner(*args: Any, **kwargs: Any) -> Callable: - filtered_kwargs = {key: value for key, value in kwargs.items() if _is_kwarg_of(key, f)} - return f(*args, **filtered_kwargs) - - return inner - - -def click_merge_args_into_context_obj(f: Callable) -> Callable: - """ - Decorator to pass click context and args to children commands. - """ - - def wrapper(*args: Any, **kwargs: Any) -> Callable: - ctx = click.get_current_context() - ctx.ensure_object(dict) - click_obj = ctx.obj - click_params = ctx.params - command_name = ctx.command.name - - # Error if click_obj and click_params have the same key - intersection = set(click_obj.keys()) & set(click_params.keys()) - if intersection: - raise ValueError(f"Your command '{command_name}' has defined options/arguments with the same key as its parent: {intersection}") - - ctx.obj = {**click_obj, **click_params} - return f(*args, **kwargs) - - return wrapper - - -def click_append_to_context_object(key: str, value: Callable) -> Callable: - """ - Decorator to append a value to the click context object. - """ - - def decorator(f: Callable) -> Callable: - async def wrapper(*args: Any, **kwargs: Any) -> Any: # noqa: ANN401 - ctx = click.get_current_context() - ctx.ensure_object(dict) - - # if async, get the value, cannot use await - if inspect.iscoroutinefunction(value): - ctx.obj[key] = await value(ctx) - elif callable(value): - ctx.obj[key] = value(ctx) - else: - ctx.obj[key] = value - return await f(*args, **kwargs) - - return wrapper - - return decorator - - -class LazyPassDecorator: - """ - Used to create a decorator that will pass an instance of the given class to the decorated function. - """ - - def __init__(self, cls: Type[Any], *args: Any, **kwargs: Any) -> None: - """ - Initialize the decorator with the given source class - """ - self.cls = cls - self.args = args - self.kwargs = kwargs - - def __call__(self, f: Callable[..., Any]) -> Callable[..., Any]: - """ - Create a decorator that will pass an instance of the given class to the decorated function. - """ - - @wraps(f) - def decorated_function(*args: Any, **kwargs: Any) -> Any: # noqa: ANN401 - # Check if the kwargs already contain the arguments being passed by the decorator - decorator_kwargs = {k: v for k, v in self.kwargs.items() if k not in kwargs} - # Create an instance of the class - instance = self.cls(*self.args, **decorator_kwargs) - # If function has **kwargs, we can put the instance there - if "kwargs" in kwargs: - kwargs["kwargs"] = instance - # Otherwise, add it to positional arguments - else: - args = (*args, instance) - return f(*args, **kwargs) - - return decorated_function - - -def click_ci_requirements_option() -> Callable[[FC], FC]: - """Add a --ci-requirements option to the command. - - Returns: - Callable[[FC], FC]: The decorated command. - """ - - def callback(ctx: click.Context, param: click.Parameter, value: bool) -> None: - if value: - ci_requirements = CIRequirements() - click.echo(ci_requirements.to_json()) - ctx.exit() - - return click.decorators.option( - CI_REQUIREMENTS_OPTION_NAME, - is_flag=True, - expose_value=False, - is_eager=True, - flag_value=True, - help="Show the CI requirements and exit. It used to make airbyte-ci client define the CI runners it will run on.", - callback=callback, - ) diff --git a/airbyte-ci/connectors/pipelines/pipelines/cli/confirm_prompt.py b/airbyte-ci/connectors/pipelines/pipelines/cli/confirm_prompt.py deleted file mode 100644 index b7504cb452f1..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/cli/confirm_prompt.py +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from __future__ import annotations - -from typing import TYPE_CHECKING - -import asyncclick as click - -if TYPE_CHECKING: - from typing import Any, Callable - -PRE_CONFIRM_ALL_KEY = "yes" - - -def pre_confirm_all_flag(f: Callable) -> Callable: - """Decorator to add a --yes flag to a command.""" - return click.option("-y", "--yes", PRE_CONFIRM_ALL_KEY, is_flag=True, default=False, help="Skip prompts and use default values")(f) - - -def confirm(*args: Any, **kwargs: Any) -> bool: - """Confirm a prompt with the user, with support for a --yes flag.""" - additional_pre_confirm_key = kwargs.pop("additional_pre_confirm_key", None) - ctx = click.get_current_context() - if ctx.obj.get(PRE_CONFIRM_ALL_KEY, False): - return True - - if additional_pre_confirm_key: - if ctx.obj.get(additional_pre_confirm_key, False): - return True - - return click.confirm(*args, **kwargs) diff --git a/airbyte-ci/connectors/pipelines/pipelines/cli/dagger_pipeline_command.py b/airbyte-ci/connectors/pipelines/pipelines/cli/dagger_pipeline_command.py deleted file mode 100644 index 9120bf59921e..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/cli/dagger_pipeline_command.py +++ /dev/null @@ -1,108 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""This module groups util function used in pipelines.""" - -from __future__ import annotations - -import sys -from pathlib import Path - -import asyncclick as click -from dagger import DaggerError - -from pipelines import consts, main_logger -from pipelines.consts import GCS_PUBLIC_DOMAIN, STATIC_REPORT_PREFIX -from pipelines.helpers import sentry_utils -from pipelines.helpers.gcs import upload_to_gcs -from pipelines.helpers.utils import slugify - - -class DaggerPipelineCommand(click.Command): - @sentry_utils.with_command_context - async def invoke(self, ctx: click.Context) -> None: - """Wrap parent invoke in a try catch suited to handle pipeline failures. - Args: - ctx (click.Context): The invocation context. - Raises: - e: Raise whatever exception that was caught. - """ - command_name = self.name - main_logger.info(f"Running Dagger Command {command_name}...") - main_logger.info( - "If you're running this command for the first time the Dagger engine image will be pulled, it can take a short minute..." - ) - ctx.obj["report_output_prefix"] = self.render_report_output_prefix(ctx) - dagger_logs_gcs_key = f"{ctx.obj['report_output_prefix']}/dagger-logs.txt" - try: - if not ctx.obj["show_dagger_logs"]: - dagger_log_dir = Path(f"{consts.LOCAL_REPORTS_PATH_ROOT}/{ctx.obj['report_output_prefix']}") - dagger_log_path = Path(f"{dagger_log_dir}/dagger.log").resolve() - ctx.obj["dagger_logs_path"] = dagger_log_path - main_logger.info(f"Saving dagger logs to: {dagger_log_path}") - if ctx.obj["is_ci"]: - ctx.obj["dagger_logs_url"] = f"{GCS_PUBLIC_DOMAIN}/{ctx.obj['ci_report_bucket_name']}/{dagger_logs_gcs_key}" - else: - ctx.obj["dagger_logs_url"] = None - else: - ctx.obj["dagger_logs_path"] = None - pipeline_success = await super().invoke(ctx) - if not pipeline_success: - raise DaggerError(f"Dagger Command {command_name} failed.") - except DaggerError as e: - main_logger.error(f"Dagger Command {command_name} failed", exc_info=e) - sys.exit(1) - finally: - if ctx.obj.get("dagger_logs_path"): - main_logger.info(f"Dagger logs saved to {ctx.obj['dagger_logs_path']}") - if ctx.obj["is_ci"] and ctx.obj["ci_gcp_credentials"] and ctx.obj["ci_report_bucket_name"]: - gcs_uri, public_url = upload_to_gcs( - ctx.obj["dagger_logs_path"], - ctx.obj["ci_report_bucket_name"], - dagger_logs_gcs_key, - ctx.obj["ci_gcp_credentials"].value, - ) - main_logger.info(f"Dagger logs saved to {gcs_uri}. Public URL: {public_url}") - - @staticmethod - def render_report_output_prefix(ctx: click.Context) -> str: - """Render the report output prefix for any command in the Connector CLI. - - The goal is to standardize the output of all logs and reports generated by the CLI - related to a specific command, and to a specific CI context. - - Note: We cannot hoist this higher in the command hierarchy because only one level of - subcommands are available at the time the context is created. - """ - - git_branch = ctx.obj["git_branch"] - git_revision = ctx.obj["git_revision"] - pipeline_start_timestamp = ctx.obj["pipeline_start_timestamp"] - ci_context = ctx.obj["ci_context"] - ci_job_key = ctx.obj["ci_job_key"] if ctx.obj.get("ci_job_key") else ci_context - - sanitized_branch = slugify(git_branch.replace("/", "_")) - - # get the command name for the current context, if a group then prepend the parent command name - if ctx.command_path: - cmd_components = ctx.command_path.split(" ") - cmd_components[0] = STATIC_REPORT_PREFIX - cmd = "/".join(cmd_components) - else: - cmd = None - - path_values = [ - cmd, - ci_job_key, - sanitized_branch, - pipeline_start_timestamp, - git_revision, - ] - - # check all values are defined - if None in path_values: - raise ValueError(f"Missing value required to render the report output prefix: {path_values}") - - # join all values with a slash, and convert all values to string - return "/".join(map(str, path_values)) diff --git a/airbyte-ci/connectors/pipelines/pipelines/cli/dagger_run.py b/airbyte-ci/connectors/pipelines/pipelines/cli/dagger_run.py deleted file mode 100644 index d06921be5743..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/cli/dagger_run.py +++ /dev/null @@ -1,127 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""This module execute the airbyte-ci-internal CLI wrapped in a dagger run command to use the Dagger Terminal UI.""" - -import logging -import os -import re -import subprocess -import sys -from pathlib import Path -from typing import Optional - -import pkg_resources # type: ignore -import requests # type: ignore - -from pipelines.consts import DAGGER_WRAP_ENV_VAR_NAME - -LOGGER = logging.getLogger(__name__) -BIN_DIR = Path.home() / "bin" -BIN_DIR.mkdir(exist_ok=True) -DAGGER_TELEMETRY_TOKEN_ENV_VAR_NAME_VALUE = ( - # The _EXPERIMENTAL_DAGGER_CLOUD_TOKEN is used for telemetry only at the moment. - # It will eventually be renamed to a more specific name in future Dagger versions. - "_EXPERIMENTAL_DAGGER_CLOUD_TOKEN", - "p.eyJ1IjogIjFiZjEwMmRjLWYyZmQtNDVhNi1iNzM1LTgxNzI1NGFkZDU2ZiIsICJpZCI6ICJlNjk3YzZiYy0yMDhiLTRlMTktODBjZC0yNjIyNGI3ZDBjMDEifQ.hT6eMOYt3KZgNoVGNYI3_v4CC-s19z8uQsBkGrBhU3k", -) - -ARGS_DISABLING_TUI = ["--no-tui", "--version", "publish", "upgrade-base-image", "--help", "format", "bump-version"] - - -def get_dagger_path() -> Optional[str]: - try: - return ( - subprocess.run(["which", "dagger"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.decode("utf-8").strip() - ) - except subprocess.CalledProcessError: - if Path(BIN_DIR / "dagger").exists(): - return str(Path(BIN_DIR / "dagger")) - return None - - -def get_current_dagger_sdk_version() -> str: - version = pkg_resources.get_distribution("dagger-io").version - return version - - -def install_dagger_cli(dagger_version: str) -> None: - install_script_path = "/tmp/install_dagger.sh" - with open(install_script_path, "w") as f: - response = requests.get("https://dl.dagger.io/dagger/install.sh") - response.raise_for_status() - f.write(response.text) - subprocess.run(["chmod", "+x", install_script_path], check=True) - os.environ["BIN_DIR"] = str(BIN_DIR) - os.environ["DAGGER_VERSION"] = dagger_version - subprocess.run([install_script_path], check=True) - - -def get_dagger_cli_version(dagger_path: Optional[str]) -> Optional[str]: - if not dagger_path: - return None - version_output = ( - subprocess.run([dagger_path, "version"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.decode("utf-8").strip() - ) - version_pattern = r"v(\d+\.\d+\.\d+)" - - match = re.search(version_pattern, version_output) - - if match: - version = match.group(1) - return version - else: - raise Exception("Could not find dagger version in output: " + version_output) - - -def check_dagger_cli_install() -> str: - """ - If the dagger CLI is not installed, install it. - """ - - expected_dagger_cli_version = get_current_dagger_sdk_version() - dagger_path = get_dagger_path() - if dagger_path is None: - LOGGER.info(f"The Dagger CLI is not installed. Installing {expected_dagger_cli_version}...") - install_dagger_cli(expected_dagger_cli_version) - dagger_path = get_dagger_path() - assert dagger_path is not None, "Dagger CLI installation failed, dagger not found in path" - - cli_version = get_dagger_cli_version(dagger_path) - if cli_version != expected_dagger_cli_version: - LOGGER.warning( - f"The Dagger CLI version '{cli_version}' does not match the expected version '{expected_dagger_cli_version}'. Installing Dagger CLI '{expected_dagger_cli_version}'..." - ) - install_dagger_cli(expected_dagger_cli_version) - return check_dagger_cli_install() - return dagger_path - - -def mark_dagger_wrap() -> None: - """ - Mark that the dagger wrap has been applied. - """ - os.environ[DAGGER_WRAP_ENV_VAR_NAME] = "true" - - -def call_current_command_with_dagger_run() -> None: - mark_dagger_wrap() - # We're enabling telemetry only for local runs. - # CI runs already have telemetry as DAGGER_CLOUD_TOKEN env var is set on the CI. - if (os.environ.get("AIRBYTE_ROLE") == "airbyter") and not os.environ.get("CI"): - os.environ[DAGGER_TELEMETRY_TOKEN_ENV_VAR_NAME_VALUE[0]] = DAGGER_TELEMETRY_TOKEN_ENV_VAR_NAME_VALUE[1] - - exit_code = 0 - dagger_path = check_dagger_cli_install() - command = [dagger_path, "--silent", "run"] + sys.argv - try: - try: - LOGGER.info(f"Running command: {command}") - subprocess.run(command, check=True) - except KeyboardInterrupt: - LOGGER.info("Keyboard interrupt detected. Exiting...") - exit_code = 1 - except subprocess.CalledProcessError as e: - exit_code = e.returncode - sys.exit(exit_code) diff --git a/airbyte-ci/connectors/pipelines/pipelines/cli/ensure_repo_root.py b/airbyte-ci/connectors/pipelines/pipelines/cli/ensure_repo_root.py deleted file mode 100644 index 5970979d9d71..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/cli/ensure_repo_root.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -import logging -import os -from pathlib import Path - -import git - - -def _validate_airbyte_repo(repo: git.Repo) -> bool: - """Check if any of the remotes are the airbyte repo.""" - expected_repo_name = "airbytehq/airbyte" - for remote in repo.remotes: - if expected_repo_name in remote.url: - return True - - warning_message = f""" - ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ - - It looks like you are not running this command from the airbyte repo ({expected_repo_name}). - - If this command is run from outside the airbyte repo, it will not work properly. - - Please run this command your local airbyte project. - - ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ - """ - - logging.warning(warning_message) - - return False - - -def get_airbyte_repo() -> git.Repo: - """Get the airbyte repo.""" - repo = git.Repo(search_parent_directories=True) - _validate_airbyte_repo(repo) - return repo - - -def get_airbyte_repo_path_with_fallback() -> Path: - """Get the path to the airbyte repo.""" - try: - repo_path = get_airbyte_repo().working_tree_dir - if repo_path is not None: - return Path(str(get_airbyte_repo().working_tree_dir)) - except git.exc.InvalidGitRepositoryError: - pass - logging.warning("Could not find the airbyte repo, falling back to the current working directory.") - path = Path.cwd() - logging.warning(f"Using {path} as the airbyte repo path.") - return path - - -def set_working_directory_to_root() -> None: - """Set the working directory to the root of the airbyte repo.""" - working_dir = get_airbyte_repo_path_with_fallback() - logging.info(f"Setting working directory to {working_dir}") - os.chdir(working_dir) diff --git a/airbyte-ci/connectors/pipelines/pipelines/cli/lazy_group.py b/airbyte-ci/connectors/pipelines/pipelines/cli/lazy_group.py deleted file mode 100644 index def24edb1b6d..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/cli/lazy_group.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -# Source: https://click.palletsprojects.com/en/8.1.x/complex/ - -import importlib -from typing import Any, Dict, List, Optional - -import asyncclick as click - - -class LazyGroup(click.Group): - """ - A click Group that can lazily load subcommands. - """ - - def __init__(self, *args: Any, lazy_subcommands: Optional[Dict[str, str]] = None, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) - # lazy_subcommands is a map of the form: - # - # {command-name} -> {module-name}.{command-object-name} - # - self.lazy_subcommands = lazy_subcommands or {} - - def list_commands(self, ctx: click.Context) -> List[str]: - base = super().list_commands(ctx) - lazy = sorted(self.lazy_subcommands.keys()) - return base + lazy - - def get_command(self, ctx: click.Context, cmd_name: str) -> Optional[click.Command]: - if cmd_name in self.lazy_subcommands: - return self._lazy_load(cmd_name) - return super().get_command(ctx, cmd_name) - - def _lazy_load(self, cmd_name: str) -> click.Command: - # lazily loading a command, first get the module name and attribute name - import_path = self.lazy_subcommands[cmd_name] - modname, cmd_object_name = import_path.rsplit(".", 1) - # do the import - mod = importlib.import_module(modname) - # get the Command object from that module - cmd_object = getattr(mod, cmd_object_name) - # check the result to make debugging easier - if not isinstance(cmd_object, click.Command): - print(f"{cmd_object} is of instance {type(cmd_object)}") - raise ValueError(f"Lazy loading of {import_path} failed by returning " "a non-command object") - return cmd_object diff --git a/airbyte-ci/connectors/pipelines/pipelines/cli/secrets.py b/airbyte-ci/connectors/pipelines/pipelines/cli/secrets.py deleted file mode 100644 index a477e89d2a71..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/cli/secrets.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from typing import Any, Optional - -import asyncclick as click - -from pipelines.helpers.gcs import sanitize_gcp_credentials -from pipelines.models.secrets import InMemorySecretStore, Secret - - -def wrap_in_secret(ctx: click.Context, param: click.Option, value: Any) -> Optional[Secret]: # noqa - # Validate callback usage - if value is None: - return None - assert param.name is not None - if not isinstance(value, str): - raise click.BadParameter(f"{param.name} value is not a string, only strings can be wrapped in a secret.") - - # Make sure the context object is set or set it with an empty dict - ctx.ensure_object(dict) - - # Instantiate a global in memory secret store in the context object if it's not yet set - if "secret_stores" not in ctx.obj: - ctx.obj["secret_stores"] = {} - if "in_memory" not in ctx.obj["secret_stores"]: - ctx.obj["secret_stores"]["in_memory"] = InMemorySecretStore() - - # Add the CLI option value to the in memory secret store and wrap it in a Secret - ctx.obj["secret_stores"]["in_memory"].add_secret(param.name, value) - return Secret(param.name, ctx.obj["secret_stores"]["in_memory"]) - - -def wrap_gcp_credentials_in_secret(ctx: click.Context, param: click.Option, value: Any) -> Optional[Secret]: # noqa - # Validate callback usage - if value is None: - return None - if not isinstance(value, str): - raise click.BadParameter(f"{param.name} value is not a string, only strings can be wrapped in a secret.") - - value = sanitize_gcp_credentials(value) - return wrap_in_secret(ctx, param, value) diff --git a/airbyte-ci/connectors/pipelines/pipelines/cli/telemetry.py b/airbyte-ci/connectors/pipelines/pipelines/cli/telemetry.py deleted file mode 100644 index 8ecb606973a1..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/cli/telemetry.py +++ /dev/null @@ -1,74 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -import getpass -import hashlib -import os -import platform -import sys -from typing import TYPE_CHECKING - -import segment.analytics as analytics # type: ignore -from asyncclick import get_current_context - -DISABLE_TELEMETRY = os.environ.get("AIRBYTE_CI_DISABLE_TELEMETRY", "false").lower() == "true" - -if TYPE_CHECKING: - from typing import Any, Callable, Dict, Tuple - - from asyncclick import Command - -analytics.write_key = "G6G7whgro81g9xM00kN2buclGKvcOjFd" -analytics.send = not DISABLE_TELEMETRY -analytics.debug = False - - -def _is_airbyte_user() -> bool: - """Returns True if the user is airbyter, False otherwise.""" - return os.getenv("AIRBYTE_ROLE") == "airbyter" - - -def _get_anonymous_system_id() -> str: - """Returns a unique anonymous hashid of the current system info.""" - # Collect machine-specific information - machine_info = platform.node() - username = getpass.getuser() - - unique_system_info = f"{machine_info}-{username}" - - # Generate a unique hash - unique_id = hashlib.sha256(unique_system_info.encode()).hexdigest() - - return unique_id - - -def click_track_command(f: Callable) -> Callable: - """ - Decorator to track CLI commands with segment.io - """ - - def wrapper(*args: Tuple, **kwargs: Dict[str, Any]) -> Command: - ctx = get_current_context() - - top_level_command = ctx.command_path - full_cmd = " ".join(sys.argv) - - # remove anything prior to the command name f.__name__ - # to avoid logging inline secrets - sanitized_cmd = full_cmd[full_cmd.find(top_level_command) :] - sys_id = _get_anonymous_system_id() - sys_user_name = f"anonymous:{sys_id}" - airbyter = _is_airbyte_user() - - is_local = kwargs.get("is_local", False) - user_id = "local-user" if is_local else "ci-user" - event = f"airbyte-ci:{f.__name__}" - - # IMPORTANT! do not log kwargs as they may contain secrets - analytics.track(user_id, event, {"username": sys_user_name, "command": sanitized_cmd, "airbyter": airbyter}) - - return f(*args, **kwargs) - - return wrapper diff --git a/airbyte-ci/connectors/pipelines/pipelines/consts.py b/airbyte-ci/connectors/pipelines/pipelines/consts.py deleted file mode 100644 index 8846d2d1f927..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/consts.py +++ /dev/null @@ -1,101 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import os -import platform -from enum import Enum - -from dagger import Platform - -PYPROJECT_TOML_FILE_PATH = "pyproject.toml" -MANIFEST_FILE_PATH = "manifest.yaml" -COMPONENTS_FILE_PATH = "components.py" -LICENSE_SHORT_FILE_PATH = "LICENSE_SHORT" -CONNECTOR_TESTING_REQUIREMENTS = [ - "pip==21.3.1", - "mccabe==0.6.1", - "pytest==6.2.5", - "coverage[toml]==6.3.1", - "pytest-custom_exit_code", -] - -BUILD_PLATFORMS = (Platform("linux/amd64"), Platform("linux/arm64")) - -PLATFORM_MACHINE_TO_DAGGER_PLATFORM = { - "x86_64": Platform("linux/amd64"), - "arm64": Platform("linux/arm64"), - "aarch64": Platform("linux/amd64"), - "amd64": Platform("linux/amd64"), -} -LOCAL_MACHINE_TYPE = platform.machine() -LOCAL_BUILD_PLATFORM = PLATFORM_MACHINE_TO_DAGGER_PLATFORM[LOCAL_MACHINE_TYPE] -AMAZONCORRETTO_IMAGE = "amazoncorretto:21-al2023" -NODE_IMAGE = "node:18.18.0-slim" -MAVEN_IMAGE = "maven:3.9.6-amazoncorretto-21-al2023" -DOCKER_VERSION = "24" -DOCKER_DIND_IMAGE = f"docker:{DOCKER_VERSION}-dind" -DOCKER_CLI_IMAGE = f"docker:{DOCKER_VERSION}-cli" -DOCKER_REGISTRY_MIRROR_URL = os.getenv("DOCKER_REGISTRY_MIRROR_URL") -DOCKER_REGISTRY_ADDRESS = "docker.io" -DOCKER_VAR_LIB_VOLUME_NAME = "docker-cache-2" -GIT_IMAGE = "alpine/git:latest" -GIT_DIRECTORY_ROOT_PATH = ".git" -GRADLE_CACHE_PATH = "/root/.gradle/caches" -GRADLE_BUILD_CACHE_PATH = f"{GRADLE_CACHE_PATH}/build-cache-1" -GRADLE_READ_ONLY_DEPENDENCY_CACHE_PATH = "/root/gradle_dependency_cache" -LOCAL_REPORTS_PATH_ROOT = "airbyte-ci/connectors/pipelines/pipeline_reports/" -LOCAL_PIPELINE_PACKAGE_PATH = "airbyte-ci/connectors/pipelines/" -DOCS_DIRECTORY_ROOT_PATH = "docs/" -GCS_PUBLIC_DOMAIN = "https://storage.cloud.google.com" -DOCKER_HOST_NAME = "global-docker-host" -DOCKER_HOST_PORT = 2375 -DOCKER_TMP_VOLUME_NAME = "shared-tmp" -STATIC_REPORT_PREFIX = "airbyte-ci" -PIP_CACHE_VOLUME_NAME = "pip_cache" -PIP_CACHE_PATH = "/root/.cache/pip" -POETRY_CACHE_VOLUME_NAME = "poetry_cache" -POETRY_CACHE_PATH = "/root/.cache/pypoetry" -STORAGE_DRIVER = "fuse-overlayfs" -SETUP_PY_FILE_PATH = "setup.py" -DEFAULT_PYTHON_PACKAGE_REGISTRY_URL = "https://upload.pypi.org/legacy/" -DEFAULT_PYTHON_PACKAGE_REGISTRY_CHECK_URL = "https://pypi.org/pypi" -MAIN_CONNECTOR_TESTING_SECRET_STORE_ALIAS = "airbyte-connector-testing-secret-store" -AIRBYTE_SUBMODULE_DIR_NAME = "airbyte-submodule" -MANUAL_PIPELINE_STATUS_CHECK_OVERRIDE_PREFIXES = ["Regression Tests"] - -PUBLISH_UPDATES_SLACK_CHANNEL = "#connector-publish-updates" -PUBLISH_FAILURE_SLACK_CHANNEL = "#connector-publish-failures" -# TODO this should be passed via an env var or a CLI input -PATH_TO_LOCAL_CDK = "../airbyte-python-cdk" - - -class CIContext(str, Enum): - """An enum for Ci context values which can be ["manual", "pull_request", "nightly_builds"].""" - - MANUAL = "manual" - PULL_REQUEST = "pull_request" - MASTER = "master" - - def __str__(self) -> str: - return self.value - - -class ContextState(Enum): - """Enum to characterize the current context state, values are used for external representation on GitHub commit checks.""" - - INITIALIZED = {"github_state": "pending", "description": "Pipelines are being initialized..."} - RUNNING = {"github_state": "pending", "description": "Pipelines are running..."} - ERROR = {"github_state": "error", "description": "Something went wrong while running the Pipelines."} - SUCCESSFUL = {"github_state": "success", "description": "All Pipelines ran successfully."} - FAILURE = {"github_state": "failure", "description": "Pipeline failed."} - - -class INTERNAL_TOOL_PATHS(str, Enum): - CI_CREDENTIALS = "airbyte-ci/connectors/ci_credentials" - CONNECTOR_OPS = "airbyte-ci/connectors/connector_ops" - # CONNECTORS_QA has been removed - now using airbyte-internal-ops from PyPI - METADATA_SERVICE = "airbyte-ci/connectors/metadata_service/lib" - - -DAGGER_WRAP_ENV_VAR_NAME = "_DAGGER_WRAP_APPLIED" diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/connector/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/connector/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/connector/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/connector/hooks.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/connector/hooks.py deleted file mode 100644 index c9057533fa50..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/connector/hooks.py +++ /dev/null @@ -1,69 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import importlib.util -from importlib import metadata -from importlib.abc import Loader - -from dagger import Container - -from pipelines.airbyte_ci.connectors.context import ConnectorContext - - -def get_dagger_sdk_version() -> str: - try: - return metadata.version("dagger-io") - except metadata.PackageNotFoundError: - return "n/a" - - -async def finalize_build(context: ConnectorContext, connector_container: Container) -> Container: - """Finalize build by adding dagger engine version label and running finalize_build.sh or finalize_build.py if present in the connector directory.""" - original_user = (await connector_container.with_exec(["whoami"]).stdout()).strip() - # Switch to root to finalize the build with superuser permissions - connector_container = connector_container.with_user("root") - connector_container = connector_container.with_label("io.dagger.engine_version", get_dagger_sdk_version()) - connector_dir_with_finalize_script = await context.get_connector_dir(include=["finalize_build.sh", "finalize_build.py"]) - finalize_scripts = await connector_dir_with_finalize_script.entries() - if not finalize_scripts: - return connector_container - - # We don't want finalize scripts to override the entrypoint so we keep it in memory to reset it after finalization - original_entrypoint = await connector_container.entrypoint() - if not original_entrypoint: - original_entrypoint = [] - - has_finalize_bash_script = "finalize_build.sh" in finalize_scripts - has_finalize_python_script = "finalize_build.py" in finalize_scripts - if has_finalize_python_script and has_finalize_bash_script: - raise Exception("Connector has both finalize_build.sh and finalize_build.py, please remove one of them") - - if has_finalize_python_script: - context.logger.info(f"{context.connector.technical_name} has a finalize_build.py script, running it to finalize build...") - module_path = context.connector.code_directory / "finalize_build.py" - connector_finalize_module_spec = importlib.util.spec_from_file_location( - f"{context.connector.code_directory.name}_finalize", module_path - ) - if connector_finalize_module_spec is None: - raise Exception("Connector has a finalize_build.py script but it can't be loaded.") - connector_finalize_module = importlib.util.module_from_spec(connector_finalize_module_spec) - if not isinstance(connector_finalize_module_spec.loader, Loader): - raise Exception("Connector has a finalize_build.py script but it can't be loaded.") - connector_finalize_module_spec.loader.exec_module(connector_finalize_module) - try: - connector_container = await connector_finalize_module.finalize_build(context, connector_container) - except AttributeError: - raise Exception("Connector has a finalize_build.py script but it doesn't have a finalize_build function.") - - if has_finalize_bash_script: - context.logger.info(f"{context.connector.technical_name} has finalize_build.sh script, running it to finalize build...") - connector_container = ( - connector_container.with_file("/tmp/finalize_build.sh", connector_dir_with_finalize_script.file("finalize_build.sh")) - .with_entrypoint(["sh"]) - .with_exec(["/tmp/finalize_build.sh"], use_entrypoint=True) - ) - # Switch back to the original user - connector_container = connector_container.with_exec(["chown", "-R", f"{original_user}:{original_user}", "/tmp"]) - connector_container = connector_container.with_user(original_user) - return connector_container.with_entrypoint(original_entrypoint) diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/connector/normalization.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/connector/normalization.py deleted file mode 100644 index 406293ab9437..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/connector/normalization.py +++ /dev/null @@ -1,78 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from typing import Any, Dict - -from dagger import Container, Platform - -from pipelines.airbyte_ci.connectors.context import ConnectorContext - -BASE_DESTINATION_NORMALIZATION_BUILD_CONFIGURATION = { - "destination-clickhouse": { - "dockerfile": "clickhouse.Dockerfile", - "dbt_adapter": "dbt-clickhouse>=1.4.0", - "integration_name": "clickhouse", - "normalization_image": "airbyte/normalization-clickhouse:0.4.3", - "supports_in_connector_normalization": False, - "yum_packages": [], - }, - "destination-mssql": { - "dockerfile": "mssql.Dockerfile", - "dbt_adapter": "dbt-sqlserver==1.0.0", - "integration_name": "mssql", - "normalization_image": "airbyte/normalization-mssql:0.4.3", - "supports_in_connector_normalization": True, - "yum_packages": [], - }, - "destination-mysql": { - "dockerfile": "mysql.Dockerfile", - "dbt_adapter": "dbt-mysql==1.0.0", - "integration_name": "mysql", - "normalization_image": "airbyte/normalization-mysql:0.4.3", - "supports_in_connector_normalization": False, - "yum_packages": [], - }, - "destination-oracle": { - "dockerfile": "oracle.Dockerfile", - "dbt_adapter": "dbt-oracle==0.4.3", - "integration_name": "oracle", - "normalization_image": "airbyte/normalization-oracle:0.4.3", - "supports_in_connector_normalization": False, - "yum_packages": [], - }, - "destination-postgres": { - "dockerfile": "Dockerfile", - "dbt_adapter": "dbt-postgres==1.0.0", - "integration_name": "postgres", - "normalization_image": "airbyte/normalization:0.4.3", - "supports_in_connector_normalization": True, - "yum_packages": [], - }, - "destination-redshift": { - "dockerfile": "redshift.Dockerfile", - "dbt_adapter": "dbt-redshift==1.0.0", - "integration_name": "redshift", - "normalization_image": "airbyte/normalization-redshift:0.4.3", - "supports_in_connector_normalization": True, - "yum_packages": [], - }, - "destination-tidb": { - "dockerfile": "tidb.Dockerfile", - "dbt_adapter": "dbt-tidb==1.0.1", - "integration_name": "tidb", - "normalization_image": "airbyte/normalization-tidb:0.4.3", - "supports_in_connector_normalization": True, - "yum_packages": [], - }, -} -DESTINATION_NORMALIZATION_BUILD_CONFIGURATION: Dict[str, Dict[str, Any]] = { - **BASE_DESTINATION_NORMALIZATION_BUILD_CONFIGURATION, - **{f"{k}-strict-encrypt": v for k, v in BASE_DESTINATION_NORMALIZATION_BUILD_CONFIGURATION.items()}, -} - - -def with_normalization(context: ConnectorContext, build_platform: Platform) -> Container: - normalization_image_name = DESTINATION_NORMALIZATION_BUILD_CONFIGURATION[context.connector.technical_name]["normalization_image"] - assert isinstance(normalization_image_name, str) - return context.dagger_client.container(platform=build_platform).from_(normalization_image_name) diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/common.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/common.py deleted file mode 100644 index 48b00214c774..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/common.py +++ /dev/null @@ -1,350 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import re -from pathlib import Path -from typing import List, Optional, Sequence - -from click import UsageError -from dagger import Container, Directory - -from pipelines import hacks -from pipelines.airbyte_ci.connectors.context import ConnectorContext, PipelineContext -from pipelines.consts import PATH_TO_LOCAL_CDK -from pipelines.dagger.containers.python import with_pip_cache, with_poetry_cache, with_python_base -from pipelines.helpers.utils import check_path_in_workdir, get_file_contents, raise_if_not_user - - -def with_python_package( - context: PipelineContext, - python_environment: Container, - package_source_code_path: str, - exclude: Optional[List] = None, - include: Optional[List] = None, - owner: str | None = None, -) -> Container: - """Load a python package source code to a python environment container. - - Args: - context (PipelineContext): The current test context, providing the repository directory from which the python sources will be pulled. - python_environment (Container): An existing python environment in which the package will be installed. - package_source_code_path (str): The local path to the package source code. - additional_dependency_groups (Optional[List]): extra_requires dependency of setup.py to install. Defaults to None. - exclude (Optional[List]): A list of file or directory to exclude from the python package source code. - include (Optional[List]): A list of file or directory to include from the python package source code. - owner (str, optional): The owner of the mounted directory. Defaults to None. - Returns: - Container: A python environment container with the python package source code. - """ - package_source_code_directory: Directory = context.get_repo_dir(package_source_code_path, exclude=exclude, include=include) - work_dir_path = f"/{package_source_code_path}" - container = python_environment.with_mounted_directory(work_dir_path, package_source_code_directory, owner=owner).with_workdir( - work_dir_path - ) - return container - - -async def find_local_dependencies_in_setup_py(python_package: Container) -> List[str]: - """Find local dependencies of a python package in its setup.py file. - - Args: - python_package (Container): A python package container. - - Returns: - List[str]: Paths to the local dependencies relative to the airbyte repo. - """ - setup_file_content = await get_file_contents(python_package, "setup.py") - if not setup_file_content: - return [] - - local_setup_dependency_paths = [] - with_egg_info = python_package.with_exec(["python", "setup.py", "egg_info"], use_entrypoint=True) - egg_info_output = await with_egg_info.stdout() - dependency_in_requires_txt = [] - for line in egg_info_output.split("\n"): - if line.startswith("writing requirements to"): - # Find the path to the requirements.txt file that was generated by calling egg_info - requires_txt_path = line.replace("writing requirements to", "").strip() - requirements_txt_content = await with_egg_info.file(requires_txt_path).contents() - dependency_in_requires_txt = requirements_txt_content.split("\n") - - for dependency_line in dependency_in_requires_txt: - if "file://" in dependency_line: - match = re.search(r"file:///(.+)", dependency_line) - if match: - local_setup_dependency_paths.append([match.group(1)][0]) - return local_setup_dependency_paths - - -async def find_local_dependencies_in_requirements_txt(python_package: Container, package_source_code_path: str) -> List[str]: - """Find local dependencies of a python package in a requirements.txt file. - - Args: - python_package (Container): A python environment container with the python package source code. - package_source_code_path (str): The local path to the python package source code. - - Returns: - List[str]: Paths to the local dependencies relative to the airbyte repo. - """ - requirements_txt_content = await get_file_contents(python_package, "requirements.txt") - if not requirements_txt_content: - return [] - - local_requirements_dependency_paths = [] - for line in requirements_txt_content.split("\n"): - # Some package declare themselves as a requirement in requirements.txt, - # #Without line != "-e ." the package will be considered a dependency of itself which can cause an infinite loop - if line.startswith("-e .") and line != "-e .": - local_dependency_path = str((Path(package_source_code_path) / Path(line[3:])).resolve().relative_to(Path.cwd())) - local_requirements_dependency_paths.append(local_dependency_path) - return local_requirements_dependency_paths - - -async def find_local_python_dependencies( - context: PipelineContext, - package_source_code_path: str, - search_dependencies_in_setup_py: bool = True, - search_dependencies_in_requirements_txt: bool = True, -) -> List[str]: - """Find local python dependencies of a python package. The dependencies are found in the setup.py and requirements.txt files. - - Args: - context (PipelineContext): The current pipeline context, providing a dagger client and a repository directory. - package_source_code_path (str): The local path to the python package source code. - search_dependencies_in_setup_py (bool, optional): Whether to search for local dependencies in the setup.py file. Defaults to True. - search_dependencies_in_requirements_txt (bool, optional): Whether to search for local dependencies in the requirements.txt file. Defaults to True. - Returns: - List[str]: Paths to the local dependencies relative to the airbyte repo. - """ - python_environment = with_python_base(context) - container = with_python_package(context, python_environment, package_source_code_path) - - local_dependency_paths = [] - if search_dependencies_in_setup_py: - local_dependency_paths += await find_local_dependencies_in_setup_py(container) - if search_dependencies_in_requirements_txt: - local_dependency_paths += await find_local_dependencies_in_requirements_txt(container, package_source_code_path) - - transitive_dependency_paths = [] - for local_dependency_path in local_dependency_paths: - # Transitive local dependencies installation is achieved by calling their setup.py file, not their requirements.txt file. - transitive_dependency_paths += await find_local_python_dependencies(context, local_dependency_path, True, False) - - all_dependency_paths = local_dependency_paths + transitive_dependency_paths - if all_dependency_paths: - context.logger.debug(f"Found local dependencies for {package_source_code_path}: {all_dependency_paths}") - return all_dependency_paths - - -def _install_python_dependencies_from_setup_py( - container: Container, - additional_dependency_groups: Optional[Sequence[str]] = None, -) -> Container: - install_connector_package_cmd = ["pip", "install", "."] - container = container.with_exec(install_connector_package_cmd) - - if additional_dependency_groups: - # e.g. .[dev,tests] - group_string = f".[{','.join(additional_dependency_groups)}]" - group_install_cmd = ["pip", "install", group_string] - - container = container.with_exec(group_install_cmd) - - return container - - -def _install_python_dependencies_from_requirements_txt(container: Container) -> Container: - install_requirements_cmd = ["pip", "install", "-r", "requirements.txt"] - return container.with_exec(install_requirements_cmd) - - -def _install_python_dependencies_from_poetry( - container: Container, - additional_dependency_groups: Optional[Sequence[str]] = None, - install_root_package: bool = True, -) -> Container: - pip_install_poetry_cmd = ["pip", "install", "poetry"] - poetry_disable_virtual_env_cmd = ["poetry", "config", "virtualenvs.create", "false"] - poetry_install_cmd = ["poetry", "install"] - poetry_check_cmd = ["poetry", "check"] - if not install_root_package: - poetry_install_cmd += ["--no-root"] - if additional_dependency_groups: - for group in additional_dependency_groups: - poetry_install_cmd += ["--with", group] - else: - poetry_install_cmd += ["--only", "main"] - return ( - container.with_exec(pip_install_poetry_cmd) - .with_exec(poetry_disable_virtual_env_cmd) - .with_exec(poetry_check_cmd) - .with_exec(poetry_install_cmd) - ) - - -async def with_installed_python_package( - context: PipelineContext, - python_environment: Container, - package_source_code_path: str, - user: str, - additional_dependency_groups: Optional[Sequence[str]] = None, - exclude: Optional[List] = None, - include: Optional[List] = None, - install_root_package: bool = True, -) -> Container: - """Install a python package in a python environment container. - - Args: - context (PipelineContext): The current test context, providing the repository directory from which the python sources will be pulled. - python_environment (Container): An existing python environment in which the package will be installed. - package_source_code_path (str): The local path to the package source code. - user (str): The user to use in the container. - additional_dependency_groups (Optional[Sequence[str]]): extra_requires dependency of setup.py to install. Defaults to None. - exclude (Optional[List]): A list of file or directory to exclude from the python package source code. - include (Optional[List]): A list of file or directory to include from the python package source code. - install_root_package (bool): Whether to install the root package. Defaults to True. - - Returns: - Container: A python environment container with the python package installed. - """ - - container = with_python_package(context, python_environment, package_source_code_path, exclude=exclude, include=include, owner=user) - local_dependencies = await find_local_python_dependencies(context, package_source_code_path) - - for dependency_directory in local_dependencies: - container = container.with_mounted_directory("/" + dependency_directory, context.get_repo_dir(dependency_directory), owner=user) - - has_setup_py = await check_path_in_workdir(container, "setup.py") - has_requirements_txt = await check_path_in_workdir(container, "requirements.txt") - has_pyproject_toml = await check_path_in_workdir(container, "pyproject.toml") - - container = container.with_user("root") - # All of these will require root access to install dependencies - # Dependencies are installed at the system level, if the user is not root it is not allowed to install system level dependencies - if has_pyproject_toml: - container = with_poetry_cache(container, context.dagger_client, owner=user) - container = _install_python_dependencies_from_poetry(container, additional_dependency_groups, install_root_package) - elif has_setup_py: - container = with_pip_cache(container, context.dagger_client) - container = _install_python_dependencies_from_setup_py(container, additional_dependency_groups) - elif has_requirements_txt: - container = with_pip_cache(container, context.dagger_client) - container = _install_python_dependencies_from_requirements_txt(container) - - container = container.with_user(user) - - return container - - -def apply_python_development_overrides(context: ConnectorContext, connector_container: Container, current_user: str) -> Container: - # Run the connector using the local cdk if flag is set - if context.use_local_cdk: - # Assume CDK is cloned in a sibling dir to `airbyte`: - path_to_cdk = str(Path(PATH_TO_LOCAL_CDK).resolve()) - if not Path(path_to_cdk).exists(): - raise UsageError( - f"Local CDK not found at '{path_to_cdk}'. Please clone the CDK repository in a sibling directory to the airbyte repository. Or use --use-cdk-ref to specify a CDK ref." - ) - context.logger.info(f"Using local CDK found at: '{path_to_cdk}'") - directory_to_mount = context.dagger_client.host().directory(path_to_cdk) - cdk_mount_dir = "/airbyte-cdk/python" - - context.logger.info(f"Mounting CDK from '{path_to_cdk}' to '{cdk_mount_dir}'") - # Install the airbyte-cdk package from the local directory - connector_container = ( - connector_container.with_env_variable( - "POETRY_DYNAMIC_VERSIONING_BYPASS", - "0.0.0-dev.0", # Replace dynamic versioning with dev version - ) - .with_directory( - cdk_mount_dir, - directory_to_mount, - owner=current_user, - ) - # We switch to root as otherwise we get permission errors when installing the package - # Permissions errors are caused by the fact that the airbyte user does not have a home directory - # Pip tries to write to /nonexistent which does not exist and on which the airbyte user does not have permissions - # We could create a proper home directory for the airbyte user, but that should be done at the base image level. - # Installing as root should not cause any issues as the container is ephemeral and the image is not pushed to a registry. - # Moreover this install is a system-wide install so the airbyte user will be able to use the package. - .with_user("root") - .with_exec( - ["pip", "install", "--no-cache-dir", "--force-reinstall", f"{cdk_mount_dir}"], - # TODO: Consider moving to Poetry-native installation: - # ["poetry", "add", cdk_mount_dir] - ) - # Switch back to the original user - .with_user(current_user) - ) - elif context.use_cdk_ref: - cdk_ref = context.use_cdk_ref - if " " in cdk_ref: - raise ValueError("CDK ref should not contain spaces") - - context.logger.info("Using CDK ref: '{cdk_ref}'") - # Install the airbyte-cdk package from provided ref - connector_container = ( - connector_container.with_user("root") - .with_exec( - [ - "apt-get", - "install", - "-y", - "git", - ] - ) - .with_exec( - [ - "pip", - "install", - f"git+https://github.com/airbytehq/airbyte-python-cdk.git#{cdk_ref}", - ], - ) - .with_user(current_user) - ) - return connector_container - - -async def with_python_connector_installed( - context: ConnectorContext, - python_container: Container, - connector_source_path: str, - user: str, - additional_dependency_groups: Optional[Sequence[str]] = None, - exclude: Optional[List[str]] = None, - include: Optional[List[str]] = None, - install_root_package: bool = True, -) -> Container: - """Install an airbyte python connectors dependencies.""" - - # Download the latest CDK version to update the pip cache. - # This is a hack to ensure we always get the latest CDK version installed in connectors not pinning the CDK version. - await hacks.cache_latest_cdk(context) - container = await with_installed_python_package( - context, - python_container, - connector_source_path, - user, - additional_dependency_groups=additional_dependency_groups, - exclude=exclude, - include=include, - install_root_package=install_root_package, - ) - - container = await apply_python_development_overrides(context, container, user) - await raise_if_not_user(container, user) - return container - - -def with_pip_packages(base_container: Container, packages_to_install: List[str]) -> Container: - """Installs packages using pip - Args: - context (Container): A container with python installed - - Returns: - Container: A container with the pip packages installed. - - """ - package_install_command = ["pip", "install"] - return base_container.with_exec(package_install_command + packages_to_install) diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/pipx.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/pipx.py deleted file mode 100644 index aa8b7cd90654..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/pipx.py +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from typing import List, Optional - -from dagger import Container - -from pipelines.airbyte_ci.connectors.context import PipelineContext -from pipelines.dagger.actions.python.common import with_pip_packages, with_python_package -from pipelines.dagger.actions.python.poetry import find_local_dependencies_in_pyproject_toml - - -def with_pipx(base_python_container: Container) -> Container: - """Installs pipx in a python container. - - Args: - base_python_container (Container): The container to install pipx on. - - Returns: - Container: A python environment with pipx installed. - """ - python_with_pipx = with_pip_packages(base_python_container, ["pipx"]).with_env_variable("PIPX_BIN_DIR", "/usr/local/bin") - - return python_with_pipx - - -async def with_installed_pipx_package( - context: PipelineContext, - python_environment: Container, - package_source_code_path: str, - exclude: Optional[List] = None, -) -> Container: - """Install a python package in a python environment container using pipx. - - Args: - context (PipelineContext): The current test context, providing the repository directory from which the python sources will be pulled. - python_environment (Container): An existing python environment in which the package will be installed. - package_source_code_path (str): The local path to the package source code. - exclude (Optional[List]): A list of file or directory to exclude from the python package source code. - - Returns: - Container: A python environment container with the python package installed. - """ - pipx_python_environment = with_pipx(python_environment) - container = with_python_package(context, pipx_python_environment, package_source_code_path, exclude=exclude) - - local_dependencies = await find_local_dependencies_in_pyproject_toml(context, container, package_source_code_path, exclude=exclude) - for dependency_directory in local_dependencies: - container = container.with_mounted_directory("/" + dependency_directory, context.get_repo_dir(dependency_directory)) - - container = container.with_exec(["pipx", "install", f"/{package_source_code_path}"], use_entrypoint=True) - - return container diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/poetry.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/poetry.py deleted file mode 100644 index cc87e2506734..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/python/poetry.py +++ /dev/null @@ -1,93 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import uuid -from pathlib import Path -from typing import List, Optional - -import toml -from dagger import Container, Directory - -from pipelines.airbyte_ci.connectors.context import PipelineContext -from pipelines.consts import AIRBYTE_SUBMODULE_DIR_NAME -from pipelines.dagger.actions.python.common import with_pip_packages, with_python_package -from pipelines.dagger.actions.system.common import with_debian_packages -from pipelines.dagger.containers.python import with_python_base -from pipelines.helpers.utils import get_file_contents - - -async def find_local_dependencies_in_pyproject_toml( - context: PipelineContext, - base_container: Container, - pyproject_file_path: str, - exclude: Optional[List] = None, -) -> list: - """Find local dependencies of a python package in a pyproject.toml file. - - Args: - python_package (Container): A python environment container with the python package source code. - pyproject_file_path (str): The path to the pyproject.toml file. - - Returns: - list: Paths to the local dependencies relative to the current directory. - """ - python_package = with_python_package(context, base_container, pyproject_file_path) - pyproject_content_raw = await get_file_contents(python_package, "pyproject.toml") - if not pyproject_content_raw: - return [] - - pyproject_content = toml.loads(pyproject_content_raw) - local_dependency_paths = [] - for value in pyproject_content["tool"]["poetry"]["dependencies"].values(): - if isinstance(value, dict) and "path" in value: - local_dependency_path = str((Path(pyproject_file_path) / Path(value["path"])).resolve().relative_to(Path.cwd())) - # Support the edge case where the airbyte repo is used as a git submodule. - local_dependency_path = local_dependency_path.removeprefix(f"{AIRBYTE_SUBMODULE_DIR_NAME}/") - local_dependency_paths.append(local_dependency_path) - - # Ensure we parse the child dependencies - # TODO handle more than pyproject.toml - child_local_dependencies = await find_local_dependencies_in_pyproject_toml( - context, base_container, local_dependency_path, exclude=exclude - ) - local_dependency_paths += child_local_dependencies - - return local_dependency_paths - - -def with_poetry(context: PipelineContext) -> Container: - """Install poetry in a python environment. - - Args: - context (PipelineContext): The current test context, providing the repository directory from which the ci_credentials sources will be pulled. - Returns: - Container: A python environment with poetry installed. - """ - python_base_environment: Container = with_python_base(context) - python_with_git = with_debian_packages(python_base_environment, ["git"]) - python_with_poetry = with_pip_packages(python_with_git, ["poetry"]) - - # poetry_cache: CacheVolume = context.dagger_client.cache_volume("poetry_cache") - # poetry_with_cache = python_with_poetry.with_mounted_cache("/root/.cache/pypoetry", poetry_cache, sharing=CacheSharingMode.SHARED) - - return python_with_poetry - - -def with_poetry_module(context: PipelineContext, parent_dir: Directory, module_path: str) -> Container: - """Sets up a Poetry module. - - Args: - context (PipelineContext): The current test context, providing the repository directory from which the ci_credentials sources will be pulled. - Returns: - Container: A python environment with dependencies installed using poetry. - """ - poetry_install_dependencies_cmd = ["poetry", "install"] - - python_with_poetry = with_poetry(context) - return ( - python_with_poetry.with_mounted_directory("/src", parent_dir) - .with_workdir(f"/src/{module_path}") - .with_exec(poetry_install_dependencies_cmd) - .with_env_variable("CACHEBUSTER", str(uuid.uuid4())) - ) diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/remote_storage.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/remote_storage.py deleted file mode 100644 index f8f8f28accf7..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/remote_storage.py +++ /dev/null @@ -1,90 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""This module groups functions to interact with remote storage services like S3 or GCS.""" - -import uuid -from pathlib import Path -from typing import List, Optional, Tuple - -from dagger import Client, File - -from pipelines.helpers.utils import get_exec_result, secret_host_variable, with_exit_code -from pipelines.models.secrets import Secret - -GOOGLE_CLOUD_SDK_TAG = "425.0.0-slim" - - -async def upload_to_s3(dagger_client: Client, file_to_upload_path: Path, key: str, bucket: str) -> int: - """Upload a local file to S3 using the AWS CLI docker image and running aws s3 cp command. - - Args: - dagger_client (Client): The dagger client. - file_to_upload_path (Path): The local path to the file to upload. - key (str): The key that will be written on the S3 bucket. - bucket (str): The S3 bucket name. - - Returns: - int: Exit code of the upload process. - """ - s3_uri = f"s3://{bucket}/{key}" - file_to_upload: File = dagger_client.host().directory(".", include=[str(file_to_upload_path)]).file(str(file_to_upload_path)) - return await with_exit_code( - dagger_client.container() - .from_("amazon/aws-cli:latest") - .with_file(str(file_to_upload_path), file_to_upload) - .with_(secret_host_variable(dagger_client, "AWS_ACCESS_KEY_ID")) - .with_(secret_host_variable(dagger_client, "AWS_SECRET_ACCESS_KEY")) - .with_(secret_host_variable(dagger_client, "AWS_DEFAULT_REGION")) - .with_exec(["s3", "cp", str(file_to_upload_path), s3_uri], use_entrypoint=True) - ) - - -async def upload_to_gcs( - dagger_client: Client, - file_to_upload: File, - key: str, - bucket: str, - gcs_credentials: Secret, - flags: Optional[List] = None, - cache_upload: bool = False, -) -> Tuple[int, str, str]: - """Upload a local file to GCS using the AWS CLI docker image and running aws s3 cp command. - Args: - dagger_client (Client): The dagger client. - file_to_upload (File): The dagger File to upload. - key (str): The key that will be written on the S3 bucket. - bucket (str): The S3 bucket name. - gcs_credentials (Secret): The secret holding the credentials to get and upload the targeted GCS bucket. - flags (List[str]): Flags to be passed to the 'gcloud storage cp' command. - cache_upload (bool): If false, the gcloud commands will be executed on each call. - Returns: - Tuple[int, str, str]: Exit code, stdout, stderr - """ - flags = [] if flags is None else flags - gcs_uri = f"gs://{bucket}/{key}" - dagger_client = dagger_client - cp_command = ["gcloud", "storage", "cp"] + flags + ["to_upload", gcs_uri] - - gcloud_container = ( - dagger_client.container() - .from_(f"google/cloud-sdk:{GOOGLE_CLOUD_SDK_TAG}") - .with_workdir("/upload") - .with_mounted_secret("credentials.json", gcs_credentials.as_dagger_secret(dagger_client)) - .with_env_variable("GOOGLE_APPLICATION_CREDENTIALS", "/upload/credentials.json") - .with_file("to_upload", file_to_upload) - ) - if not cache_upload: - gcloud_container = gcloud_container.with_env_variable("CACHEBUSTER", str(uuid.uuid4())) - else: - gcloud_container = gcloud_container.without_env_variable("CACHEBUSTER") - - gcloud_auth_container = gcloud_container.with_exec(["gcloud", "auth", "login", "--cred-file=credentials.json"], use_entrypoint=True) - if (await with_exit_code(gcloud_auth_container)) == 1: - gcloud_auth_container = gcloud_container.with_exec( - ["gcloud", "auth", "activate-service-account", "--key-file", "credentials.json"], use_entrypoint=True - ) - - gcloud_cp_container = gcloud_auth_container.with_exec(cp_command) - return await get_exec_result(gcloud_cp_container) diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/secrets.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/secrets.py deleted file mode 100644 index 606adce68c8f..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/secrets.py +++ /dev/null @@ -1,83 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""This modules groups functions made to download/upload secrets from/to a remote secret service and provide these secret in a dagger Directory.""" - -from __future__ import annotations - -from typing import TYPE_CHECKING - -from pipelines.helpers.utils import get_secret_host_variable -from pipelines.models.secrets import Secret - -if TYPE_CHECKING: - from typing import Callable, List - - from dagger import Container - - from pipelines.airbyte_ci.connectors.context import ConnectorContext - - -# TODO deprecate to use Secret and SecretStores -# Not prioritized as few connectors have to export their secrets back to GSM -# This would require exposing a secret update interface on the SecretStore -# and a more complex structure / Logic to map container files to Secret objects -async def upload(context: ConnectorContext, gcp_gsm_env_variable_name: str = "GCP_GSM_CREDENTIALS") -> Container: - """Use the ci-credentials tool to upload the secrets stored in the context's updated_secrets-dir. - - Args: - context (ConnectorContext): The context providing a connector object and the update secrets dir. - gcp_gsm_env_variable_name (str, optional): The name of the environment variable holding credentials to connect to Google Secret Manager. Defaults to "GCP_GSM_CREDENTIALS". - - Returns: - container (Container): The executed ci-credentials update-secrets command. - - Raises: - ExecError: If the command returns a non-zero exit code. - """ - assert context.updated_secrets_dir is not None, "The context's updated_secrets_dir must be set to upload secrets." - # temp - fix circular import - from pipelines.dagger.containers.internal_tools import with_ci_credentials - - gsm_secret = get_secret_host_variable(context.dagger_client, gcp_gsm_env_variable_name) - secrets_path = f"/{context.connector.code_directory}/secrets" - - ci_credentials = await with_ci_credentials(context, gsm_secret) - - return await ci_credentials.with_directory(secrets_path, context.updated_secrets_dir).with_exec( - ["ci_credentials", context.connector.technical_name, "update-secrets"], use_entrypoint=True - ) - - -async def mounted_connector_secrets( - context: ConnectorContext, secret_directory_path: str, connector_secrets: List[Secret], owner: str | None = None -) -> Callable[[Container], Container]: - """Returns an argument for a dagger container's with_ method which mounts all connector secrets in it. - - Args: - context (ConnectorContext): The context providing a connector object and its secrets. - secret_directory_path (str): Container directory where the secrets will be mounted, as files. - connector_secrets (List[secrets]): List of secrets to mount to the connector container. - owner (str, optional): The owner of the mounted secrets. Defaults to None. - Returns: - fn (Callable[[Container], Container]): A function to pass as argument to the connector container's with_ method. - """ - java_log_scrub_pattern_secret = context.java_log_scrub_pattern_secret - - def with_secrets_mounted_as_dagger_secrets(container: Container) -> Container: - if java_log_scrub_pattern_secret: - # This LOG_SCRUB_PATTERN environment variable is used by our log4j test configuration - # to scrub secrets from the log messages. Although we already ensure that github scrubs them - # from its runner logs, this is required to prevent the secrets from leaking into gradle scans, - # test reports or any other build artifacts generated by a java connector test. - container = container.with_secret_variable("LOG_SCRUB_PATTERN", java_log_scrub_pattern_secret) - container = container.with_exec(["mkdir", "-p", secret_directory_path]) - for secret in connector_secrets: - if secret.file_name: - container = container.with_mounted_secret( - f"{secret_directory_path}/{secret.file_name}", secret.as_dagger_secret(context.dagger_client), owner=owner - ) - return container - - return with_secrets_mounted_as_dagger_secrets diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/system/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/system/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/system/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/system/common.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/system/common.py deleted file mode 100644 index 940d56a74260..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/system/common.py +++ /dev/null @@ -1,21 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from typing import List - -from dagger import Container - - -def with_debian_packages(base_container: Container, packages_to_install: List[str]) -> Container: - """Installs packages using apt-get. - Args: - context (Container): A alpine based container. - - Returns: - Container: A container with the packages installed. - - """ - update_packages_command = ["apt-get", "update"] - package_install_command = ["apt-get", "install", "-y"] - return base_container.with_exec(update_packages_command).with_exec(package_install_command + packages_to_install) diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/system/docker.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/system/docker.py deleted file mode 100644 index 2b61fe086274..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/actions/system/docker.py +++ /dev/null @@ -1,248 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import json -import logging -import platform -import uuid -from typing import Any, Callable, Coroutine, Dict, List, Optional, Union - -from dagger import Client, Container, File, Service -from dagger import Secret as DaggerSecret - -from pipelines import consts -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.consts import ( - DOCKER_HOST_NAME, - DOCKER_HOST_PORT, - DOCKER_REGISTRY_ADDRESS, - DOCKER_REGISTRY_MIRROR_URL, - DOCKER_TMP_VOLUME_NAME, - DOCKER_VAR_LIB_VOLUME_NAME, - STORAGE_DRIVER, -) -from pipelines.helpers.utils import sh_dash_c -from pipelines.models.secrets import Secret - - -def get_base_dockerd_container(dagger_client: Client) -> Container: - """Provision a container to run a docker daemon. - It will be used as a docker host for docker-in-docker use cases. - - Args: - dagger_client (Client): The dagger client used to create the container. - Returns: - Container: The container to run dockerd as a service - """ - apk_packages_to_install = [ - STORAGE_DRIVER, - # Curl is only used for debugging purposes. - "curl", - ] - base_container = ( - dagger_client.container() - .from_(consts.DOCKER_DIND_IMAGE) - # We set this env var because we need to use a non-default zombie reaper setting. - # The reason for this is that by default it will want to set its parent process ID to 1 when reaping. - # This won't be possible because of container-ception: dind is running inside the dagger engine. - # See https://github.com/krallin/tini#subreaping for details. - .with_env_variable("TINI_SUBREAPER", "") - .with_exec( - sh_dash_c( - [ - "apk update", - f"apk add {' '.join(apk_packages_to_install)}", - "mkdir /etc/docker", - ] - ) - ) - # Expose the docker host port. - .with_exec(["adduser", "-u", "1000", "-S", "-H", "airbyte"]) - .with_exposed_port(DOCKER_HOST_PORT) - # We cache /tmp for file sharing between client and daemon. - .with_mounted_cache("/tmp", dagger_client.cache_volume(DOCKER_TMP_VOLUME_NAME), owner="airbyte") - .with_exec(["chmod", "777", "/tmp"]) - ) - - # We cache /var/lib/docker to avoid downloading images and layers multiple times. - base_container = base_container.with_mounted_cache( - "/var/lib/docker", dagger_client.cache_volume(DOCKER_VAR_LIB_VOLUME_NAME), owner="airbyte" - ) - return base_container - - -def get_daemon_config_json(registry_mirror_url: Optional[str] = None) -> str: - """Get the json representation of the docker daemon config. - - Args: - registry_mirror_url (Optional[str]): The registry mirror url to use. - - Returns: - str: The json representation of the docker daemon config. - """ - storage_driver = "vfs" if platform.system() == "Darwin" else STORAGE_DRIVER - logging.info(f"Using storage driver: {storage_driver}") - daemon_config: Dict[str, Union[List[str], str]] = { - "storage-driver": storage_driver, - } - if registry_mirror_url: - daemon_config["registry-mirrors"] = ["http://" + registry_mirror_url] - daemon_config["insecure-registries"] = [registry_mirror_url] - return json.dumps(daemon_config) - - -def docker_login( - dockerd_container: Container, - docker_registry_username: DaggerSecret, - docker_registry_password: DaggerSecret, -) -> Container: - """Login to a docker registry if the username and password secrets are provided. - - Args: - dockerd_container (Container): The dockerd_container container to login to the registry. - docker_registry_username_secret (Secret): The docker registry username secret. - docker_registry_password_secret (Secret): The docker registry password secret. - docker_registry_address (Optional[str]): The docker registry address to login to. Defaults to "docker.io" (DockerHub). - Returns: - Container: The container with the docker login command executed if the username and password secrets are provided. Noop otherwise. - """ - if docker_registry_username and docker_registry_username: - return ( - dockerd_container - # We use a cache buster here to guarantee the docker login is always executed. - .with_env_variable("CACHEBUSTER", str(uuid.uuid4())) - .with_secret_variable("DOCKER_REGISTRY_USERNAME", docker_registry_username) - .with_secret_variable("DOCKER_REGISTRY_PASSWORD", docker_registry_password) - .with_exec(sh_dash_c([f"docker login -u $DOCKER_REGISTRY_USERNAME -p $DOCKER_REGISTRY_PASSWORD {DOCKER_REGISTRY_ADDRESS}"])) - ) - else: - return dockerd_container - - -def with_global_dockerd_service( - dagger_client: Client, - docker_hub_username: Optional[Secret] = None, - docker_hub_password: Optional[Secret] = None, -) -> Service: - """Create a container with a docker daemon running. - We expose its 2375 port to use it as a docker host for docker-in-docker use cases. - It is optionally connected to a DockerHub mirror if the DOCKER_REGISTRY_MIRROR_URL env var is set. - Args: - dagger_client (Client): The dagger client used to create the container. - docker_hub_username (Optional[Secret]): The DockerHub username secret. - docker_hub_password (Optional[Secret]): The DockerHub password secret. - Returns: - Container: The container running dockerd as a service - """ - - dockerd_container = get_base_dockerd_container(dagger_client) - if DOCKER_REGISTRY_MIRROR_URL is not None: - # Ping the registry mirror host to make sure it's reachable through VPN - # We set a cache buster here to guarantee the curl command is always executed. - dockerd_container = dockerd_container.with_env_variable("CACHEBUSTER", str(uuid.uuid4())).with_exec( - ["curl", "-vvv", f"http://{DOCKER_REGISTRY_MIRROR_URL}/v2/"] - ) - daemon_config_json = get_daemon_config_json(DOCKER_REGISTRY_MIRROR_URL) - else: - daemon_config_json = get_daemon_config_json() - - dockerd_container = dockerd_container.with_new_file("/etc/docker/daemon.json", contents=daemon_config_json) - if docker_hub_username and docker_hub_password: - # Docker login happens late because there's a cache buster in the docker login command. - dockerd_container = docker_login( - dockerd_container, docker_hub_username.as_dagger_secret(dagger_client), docker_hub_password.as_dagger_secret(dagger_client) - ) - return dockerd_container.with_exec( - ["dockerd", "--log-level=error", f"--host=tcp://0.0.0.0:{DOCKER_HOST_PORT}", "--tls=false"], - insecure_root_capabilities=True, - use_entrypoint=True, - ).as_service() - - -async def with_bound_docker_host( - context: ConnectorContext, - container: Container, -) -> Container: - """Bind a container to a docker host. It will use the dockerd service as a docker host. - - Args: - context (ConnectorContext): The current connector context. - container (Container): The container to bind to the docker host. - Returns: - Container: The container bound to the docker host. - """ - assert context.dockerd_service is not None - current_user = (await container.with_exec(["whoami"]).stdout()).strip() - return ( - container.with_env_variable("DOCKER_HOST", f"tcp://{DOCKER_HOST_NAME}:{DOCKER_HOST_PORT}") - .with_service_binding(DOCKER_HOST_NAME, context.dockerd_service) - .with_mounted_cache("/tmp", context.dagger_client.cache_volume(DOCKER_TMP_VOLUME_NAME), owner=current_user) - ) - - -def bound_docker_host(context: ConnectorContext) -> Callable[[Container], Coroutine[Any, Any, Container]]: - async def bound_docker_host_inner(container: Container) -> Container: - return await with_bound_docker_host(context, container) - - return bound_docker_host_inner - - -async def with_docker_cli(context: ConnectorContext) -> Container: - """Create a container with the docker CLI installed and bound to a persistent docker host. - - Args: - context (ConnectorContext): The current connector context. - - Returns: - Container: A docker cli container bound to a docker host. - """ - docker_cli = context.dagger_client.container().from_(consts.DOCKER_CLI_IMAGE) - return await with_bound_docker_host(context, docker_cli) - - -async def load_image_to_docker_host(context: ConnectorContext, tar_file: File, image_tag: str) -> str: - """Load a docker image tar archive to the docker host. - - Args: - context (ConnectorContext): The current connector context. - tar_file (File): The file object holding the docker image tar archive. - image_tag (str): The tag to create on the image if it has no tag. - """ - # Hacky way to make sure the image is always loaded - tar_name = f"{str(uuid.uuid4())}.tar" - docker_cli = (await with_docker_cli(context)).with_mounted_file(tar_name, tar_file) - - image_load_output = await docker_cli.with_exec(["docker", "load", "--input", tar_name], use_entrypoint=True).stdout() - # Not tagged images only have a sha256 id the load output shares. - if "sha256:" in image_load_output: - image_id = image_load_output.replace("\n", "").replace("Loaded image ID: sha256:", "") - await docker_cli.with_exec(["docker", "tag", image_id, image_tag], use_entrypoint=True) - image_sha = json.loads(await docker_cli.with_exec(["docker", "inspect", image_tag], use_entrypoint=True).stdout())[0].get("Id") - return image_sha - - -def with_crane( - context: ConnectorContext, -) -> Container: - """Crane is a tool to analyze and manipulate container images. - We can use it to extract the image manifest and the list of layers or list the existing tags on an image repository. - https://github.com/google/go-containerregistry/tree/main/cmd/crane - """ - - # We use the debug image as it contains a shell which we need to properly use environment variables - # https://github.com/google/go-containerregistry/tree/main/cmd/crane#images - base_container = context.dagger_client.container().from_( - "gcr.io/go-containerregistry/crane/debug:c195f151efe3369874c72662cd69ad43ee485128@sha256:94f61956845714bea3b788445454ae4827f49a90dcd9dac28255c4cccb6220ad" - ) - - if context.docker_hub_username and context.docker_hub_password: - base_container = ( - base_container.with_secret_variable("DOCKER_HUB_USERNAME", context.docker_hub_username.as_dagger_secret(context.dagger_client)) - .with_secret_variable("DOCKER_HUB_PASSWORD", context.docker_hub_password.as_dagger_secret(context.dagger_client)) - # We use sh -c to be able to use environment variables in the command - # This is a workaround as the default crane entrypoint doesn't support environment variables - .with_exec(sh_dash_c(["crane auth login index.docker.io -u $DOCKER_HUB_USERNAME -p $DOCKER_HUB_PASSWORD"])) - ) - - return base_container diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/containers/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/containers/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/containers/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/containers/git.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/containers/git.py deleted file mode 100644 index dda43fdb3116..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/containers/git.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -import os -from typing import Optional - -from dagger import Client, Container - -from pipelines.helpers.github import AIRBYTE_GITHUB_REPO_URL -from pipelines.helpers.utils import sh_dash_c - - -def get_authenticated_repo_url(url: str, github_token: str) -> str: - return url.replace("https://github.com", f"https://{github_token}@github.com") - - -async def checked_out_git_container( - dagger_client: Client, - current_git_branch: str, - current_git_revision: str, - diffed_branch: Optional[str] = None, - repo_url: str = AIRBYTE_GITHUB_REPO_URL, -) -> Container: - """ - Create a container with git in it. - We add the airbyte repo as the origin remote and the target repo as the target remote. - We fetch the diffed branch from the origin remote and the current branch from the target remote. - We then checkout the current branch. - """ - origin_repo_url = AIRBYTE_GITHUB_REPO_URL - target_repo_url = repo_url - current_git_branch = current_git_branch.removeprefix("origin/") - diffed_branch = current_git_branch if diffed_branch is None else diffed_branch.removeprefix("origin/") - if github_token := os.environ.get("CI_GITHUB_ACCESS_TOKEN"): - origin_repo_url = get_authenticated_repo_url(origin_repo_url, github_token) - target_repo_url = get_authenticated_repo_url(target_repo_url, github_token) - origin_repo_url_secret = dagger_client.set_secret("ORIGIN_REPO_URL", origin_repo_url) - target_repo_url_secret = dagger_client.set_secret("TARGET_REPO_URL", target_repo_url) - - git_container = ( - dagger_client.container() - .from_("alpine/git:latest") - .with_workdir("/repo") - .with_exec(["init"], use_entrypoint=True) - .with_env_variable("CACHEBUSTER", current_git_revision) - .with_secret_variable("ORIGIN_REPO_URL", origin_repo_url_secret) - .with_secret_variable("TARGET_REPO_URL", target_repo_url_secret) - .with_exec(sh_dash_c(["git remote add origin ${ORIGIN_REPO_URL}"])) - .with_exec(sh_dash_c(["git remote add target ${TARGET_REPO_URL}"])) - .with_exec(["fetch", "origin", diffed_branch], use_entrypoint=True) - ) - if diffed_branch != current_git_branch: - git_container = git_container.with_exec(["fetch", "target", current_git_branch], use_entrypoint=True) - return await git_container.with_exec(["checkout", current_git_branch], use_entrypoint=True) diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/containers/internal_tools.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/containers/internal_tools.py deleted file mode 100644 index 8438fcec56e1..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/containers/internal_tools.py +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from dagger import Container, Secret - -from pipelines.airbyte_ci.connectors.context import PipelineContext -from pipelines.consts import INTERNAL_TOOL_PATHS -from pipelines.dagger.actions.python.pipx import with_installed_pipx_package -from pipelines.dagger.containers.python import with_python_base - - -async def with_ci_credentials(context: PipelineContext, gsm_secret: Secret) -> Container: - """Install the ci_credentials package in a python environment. - - Args: - context (PipelineContext): The current test context, providing the repository directory from which the ci_credentials sources will be pulled. - gsm_secret (Secret): The secret holding GCP_GSM_CREDENTIALS env variable value. - - Returns: - Container: A python environment with the ci_credentials package installed. - """ - python_base_environment: Container = with_python_base(context) - ci_credentials = await with_installed_pipx_package(context, python_base_environment, INTERNAL_TOOL_PATHS.CI_CREDENTIALS.value) - ci_credentials = ci_credentials.with_env_variable("VERSION", "dagger_ci") - return ci_credentials.with_secret_variable("GCP_GSM_CREDENTIALS", gsm_secret).with_workdir("/") - - -async def with_connector_ops(context: PipelineContext) -> Container: - """Installs the connector_ops package in a Container running Python > 3.10 with git.. - - Args: - context (PipelineContext): The current test context, providing the repository directory from which the ci_connector_sources sources will be pulled. - - Returns: - Container: A python environment container with connector_ops installed. - """ - python_base_environment: Container = with_python_base(context) - - return await with_installed_pipx_package(context, python_base_environment, INTERNAL_TOOL_PATHS.CONNECTOR_OPS.value) diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/containers/java.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/containers/java.py deleted file mode 100644 index 61ee8c4337d7..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/containers/java.py +++ /dev/null @@ -1,193 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import datetime - -from dagger import CacheVolume, Container, File, Platform - -from pipelines.airbyte_ci.connectors.context import ConnectorContext, PipelineContext -from pipelines.consts import AMAZONCORRETTO_IMAGE -from pipelines.dagger.actions.connector.hooks import finalize_build -from pipelines.dagger.actions.connector.normalization import DESTINATION_NORMALIZATION_BUILD_CONFIGURATION, with_normalization -from pipelines.helpers.utils import deprecated, sh_dash_c - - -@deprecated("This function is deprecated. Please declare an explicit base image to use in the java connector metadata.") -def with_integration_base(context: PipelineContext, build_platform: Platform) -> Container: - return ( - context.dagger_client.container(platform=build_platform) - .from_("amazonlinux:2022.0.20220831.1") - .with_workdir("/airbyte") - .with_file("base.sh", context.get_repo_dir("airbyte-integrations/bases/base", include=["base.sh"]).file("base.sh")) - .with_env_variable("AIRBYTE_ENTRYPOINT", "/airbyte/base.sh") - .with_label("io.airbyte.version", "0.1.0") - .with_label("io.airbyte.name", "airbyte/integration-base") - ) - - -@deprecated("This function is deprecated. Please declare an explicit base image to use in the java connector metadata.") -def with_integration_base_java(context: PipelineContext, build_platform: Platform) -> Container: - integration_base = with_integration_base(context, build_platform) - yum_packages_to_install = [ - "tar", # required to untar java connector binary distributions. - "openssl", # required because we need to ssh and scp sometimes. - "findutils", # required for xargs, which is shipped as part of findutils. - ] - return ( - context.dagger_client.container(platform=build_platform) - # Use a linux+jdk base image with long-term support, such as amazoncorretto. - .from_(AMAZONCORRETTO_IMAGE) - # Bust the cache on a daily basis to get fresh packages. - .with_env_variable("DAILY_CACHEBUSTER", datetime.datetime.now().strftime("%Y-%m-%d")) - # Install a bunch of packages as early as possible. - .with_exec( - sh_dash_c( - [ - # Update first, but in the same .with_exec step as the package installation. - # Otherwise, we risk caching stale package URLs. - "yum update -y --security", - # - f"yum install -y {' '.join(yum_packages_to_install)}", - # Remove any dangly bits. - "yum clean all", - ] - ) - ) - # Add what files we need to the /airbyte directory. - # Copy base.sh from the airbyte/integration-base image. - .with_directory("/airbyte", integration_base.directory("/airbyte")) - .with_workdir("/airbyte") - # Download a utility jar from the internet. - .with_file("dd-java-agent.jar", context.dagger_client.http("https://dtdg.co/latest-java-tracer")) - # Copy javabase.sh from the git repo. - .with_file("javabase.sh", context.get_repo_dir("airbyte-integrations/bases/base-java", include=["javabase.sh"]).file("javabase.sh")) - # Set a bunch of env variables used by base.sh. - .with_env_variable("AIRBYTE_SPEC_CMD", "/airbyte/javabase.sh --spec") - .with_env_variable("AIRBYTE_CHECK_CMD", "/airbyte/javabase.sh --check") - .with_env_variable("AIRBYTE_DISCOVER_CMD", "/airbyte/javabase.sh --discover") - .with_env_variable("AIRBYTE_READ_CMD", "/airbyte/javabase.sh --read") - .with_env_variable("AIRBYTE_WRITE_CMD", "/airbyte/javabase.sh --write") - .with_env_variable("AIRBYTE_ENTRYPOINT", "/airbyte/base.sh") - # Set image labels. - .with_label("io.airbyte.version", "0.1.2") - .with_label("io.airbyte.name", "airbyte/integration-base-java") - ) - - -@deprecated("This function is deprecated. Please declare an explicit base image to use in the java connector metadata.") -def with_integration_base_java_and_normalization(context: ConnectorContext, build_platform: Platform) -> Container: - yum_packages_to_install = [ - "python3", - "python3-devel", - "jq", - "sshpass", - "git", - ] - - additional_yum_packages = DESTINATION_NORMALIZATION_BUILD_CONFIGURATION[context.connector.technical_name]["yum_packages"] - yum_packages_to_install += additional_yum_packages - - dbt_adapter_package = DESTINATION_NORMALIZATION_BUILD_CONFIGURATION[context.connector.technical_name]["dbt_adapter"] - assert isinstance(dbt_adapter_package, str) - normalization_integration_name = DESTINATION_NORMALIZATION_BUILD_CONFIGURATION[context.connector.technical_name]["integration_name"] - assert isinstance(normalization_integration_name, str) - - pip_cache: CacheVolume = context.dagger_client.cache_volume("pip_cache") - - return ( - with_integration_base_java(context, build_platform) - # Bust the cache on a daily basis to get fresh packages. - .with_env_variable("DAILY_CACHEBUSTER", datetime.datetime.now().strftime("%Y-%m-%d")) - .with_exec( - sh_dash_c( - [ - "yum update -y --security", - f"yum install -y {' '.join(yum_packages_to_install)}", - "yum clean all", - "alternatives --install /usr/bin/python python /usr/bin/python3 60", - ] - ) - ) - .with_mounted_cache("/root/.cache/pip", pip_cache) - .with_exec( - sh_dash_c( - [ - "python -m ensurepip --upgrade", - # Workaround for https://github.com/yaml/pyyaml/issues/601 - "pip3 install 'Cython<3.0' 'pyyaml~=5.4' --no-build-isolation", - # Required for dbt https://github.com/dbt-labs/dbt-core/issues/7075 - "pip3 install 'pytz~=2023.3'", - f"pip3 install {dbt_adapter_package}", - # amazon linux 2 isn't compatible with urllib3 2.x, so force 1.x - "pip3 install 'urllib3<2'", - ] - ) - ) - .with_directory("airbyte_normalization", with_normalization(context, build_platform).directory("/airbyte")) - .with_workdir("airbyte_normalization") - .with_exec(sh_dash_c(["mv * .."])) - .with_workdir("/airbyte") - .with_exec(["rm", "-rf", "airbyte_normalization"], use_entrypoint=True) - .with_workdir("/airbyte/normalization_code") - .with_exec(["pip3", "install", "."], use_entrypoint=True) - .with_workdir("/airbyte/normalization_code/dbt-template/") - .with_exec(["dbt", "deps"], use_entrypoint=True) - .with_workdir("/airbyte") - .with_file( - "run_with_normalization.sh", - context.get_repo_dir("airbyte-integrations/bases/base-java", include=["run_with_normalization.sh"]).file( - "run_with_normalization.sh" - ), - ) - .with_env_variable("AIRBYTE_NORMALIZATION_INTEGRATION", normalization_integration_name) - .with_env_variable("AIRBYTE_ENTRYPOINT", "/airbyte/run_with_normalization.sh") - ) - - -async def with_airbyte_java_connector(context: ConnectorContext, connector_java_tar_file: File, build_platform: Platform) -> Container: - application = context.connector.technical_name - - build_stage = ( - with_integration_base_java(context, build_platform) - .with_workdir("/airbyte") - .with_env_variable("APPLICATION", context.connector.technical_name) - .with_file(f"{application}.tar", connector_java_tar_file) - .with_exec( - sh_dash_c( - [ - f"tar xf {application}.tar --strip-components=1", - f"rm -rf {application}.tar", - ] - ) - ) - ) - # TODO: remove the condition below once all connectors have a base image declared in their metadata. - if "connectorBuildOptions" in context.connector.metadata and "baseImage" in context.connector.metadata["connectorBuildOptions"]: - base_image_address = context.connector.metadata["connectorBuildOptions"]["baseImage"] - context.logger.info(f"Using base image {base_image_address} from connector metadata to build connector.") - base = context.dagger_client.container(platform=build_platform).from_(base_image_address) - elif ( - context.connector.supports_normalization - and DESTINATION_NORMALIZATION_BUILD_CONFIGURATION[context.connector.technical_name]["supports_in_connector_normalization"] - ): - context.logger.warn( - f"Connector {context.connector.technical_name} has in-connector normalization enabled. This is supposed to be deprecated. " - f"Please declare a base image address in the connector metadata.yaml file (connectorBuildOptions.baseImage)." - ) - base = with_integration_base_java_and_normalization(context, build_platform).with_entrypoint(["/airbyte/run_with_normalization.sh"]) - else: - context.logger.warn( - f"Connector {context.connector.technical_name} does not declare a base image in its connector metadata. " - f"Please declare a base image address in the connector metadata.yaml file (connectorBuildOptions.baseImage)." - ) - base = with_integration_base_java(context, build_platform).with_entrypoint(["/airbyte/base.sh"]) - - current_user = (await base.with_exec(["whoami"]).stdout()).strip() - connector_container = ( - base.with_workdir("/airbyte") - .with_env_variable("APPLICATION", application) - .with_mounted_directory("built_artifacts", build_stage.directory("/airbyte"), owner=current_user) - .with_exec(sh_dash_c(["mv built_artifacts/* ."])) - ) - return await finalize_build(context, connector_container) diff --git a/airbyte-ci/connectors/pipelines/pipelines/dagger/containers/python.py b/airbyte-ci/connectors/pipelines/pipelines/dagger/containers/python.py deleted file mode 100644 index 7bd6f1e024bc..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/dagger/containers/python.py +++ /dev/null @@ -1,92 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - - -from dagger import CacheSharingMode, CacheVolume, Client, Container - -from pipelines.airbyte_ci.connectors.context import PipelineContext -from pipelines.consts import ( - CONNECTOR_TESTING_REQUIREMENTS, - PIP_CACHE_PATH, - PIP_CACHE_VOLUME_NAME, - POETRY_CACHE_PATH, - POETRY_CACHE_VOLUME_NAME, - PYPROJECT_TOML_FILE_PATH, -) -from pipelines.helpers.utils import sh_dash_c - - -def with_python_base(context: PipelineContext, python_version: str = "3.11") -> Container: - """Build a Python container with a cache volume for pip cache. - - Args: - context (PipelineContext): The current test context, providing a dagger client and a repository directory. - python_image_name (str, optional): The python image to use to build the python base environment. Defaults to "python:3.9-slim". - - Raises: - ValueError: Raised if the python_image_name is not a python image. - - Returns: - Container: The python base environment container. - """ - - pip_cache: CacheVolume = context.dagger_client.cache_volume("pip_cache") - - base_container = ( - context.dagger_client.container() - .from_(f"python:{python_version}-slim") - .with_mounted_cache("/root/.cache/pip", pip_cache) - .with_exec( - sh_dash_c( - [ - "apt-get update", - "apt-get install -y build-essential cmake g++ libffi-dev libstdc++6 git", - "pip install pip==23.1.2", - ] - ) - ) - ) - - return base_container - - -def with_testing_dependencies(context: PipelineContext) -> Container: - """Build a testing environment by installing testing dependencies on top of a python base environment. - - Args: - context (PipelineContext): The current test context, providing a dagger client and a repository directory. - - Returns: - Container: The testing environment container. - """ - python_environment: Container = with_python_base(context) - pyproject_toml_file = context.get_repo_dir(".", include=[PYPROJECT_TOML_FILE_PATH]).file(PYPROJECT_TOML_FILE_PATH) - - return python_environment.with_exec(["pip", "install"] + CONNECTOR_TESTING_REQUIREMENTS).with_file( - f"/{PYPROJECT_TOML_FILE_PATH}", pyproject_toml_file - ) - - -def with_pip_cache(container: Container, dagger_client: Client, owner: str | None = None) -> Container: - """Mounts the pip cache in the container. - Args: - container (Container): A container with python installed - owner (str, optional): The owner of the cache. Defaults to None. - Returns: - Container: A container with the pip cache mounted. - """ - pip_cache_volume = dagger_client.cache_volume(PIP_CACHE_VOLUME_NAME) - return container.with_mounted_cache(PIP_CACHE_PATH, pip_cache_volume, sharing=CacheSharingMode.SHARED, owner=owner) - - -def with_poetry_cache(container: Container, dagger_client: Client, owner: str | None = None) -> Container: - """Mounts the poetry cache in the container. - Args: - container (Container): A container with python installed - owner (str, optional): The owner of the cache. Defaults to None. - Returns: - Container: A container with the poetry cache mounted. - """ - poetry_cache_volume = dagger_client.cache_volume(POETRY_CACHE_VOLUME_NAME) - return container.with_mounted_cache(POETRY_CACHE_PATH, poetry_cache_volume, sharing=CacheSharingMode.SHARED, owner=owner) diff --git a/airbyte-ci/connectors/pipelines/pipelines/external_scripts/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/external_scripts/__init__.py deleted file mode 100644 index f70ecfc3a89e..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/external_scripts/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. diff --git a/airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_check.sh b/airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_check.sh deleted file mode 100755 index b46d5a6c3313..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_check.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env bash -set -o errexit -o nounset -o pipefail - -echo "Checking if airbyte-ci is correctly installed..." - -INSTALL_DIR="$HOME/.local/bin" -HUMAN_READABLE_INSTALL_DIR="\$HOME/.local/bin" - -# Check that the target directory is on the PATH -# If not print an error message and exit -if ! echo "$PATH" | grep -q "$INSTALL_DIR"; then - echo "The target directory $INSTALL_DIR is not on the PATH" - echo "Check that $HUMAN_READABLE_INSTALL_DIR is part of the PATH" - echo "" - echo "If not, please add 'export PATH=\"$HUMAN_READABLE_INSTALL_DIR:\$PATH\"' to your shell profile" - exit 1 -fi - -# Check that airbyte-ci is on the PATH -# If not print an error message and exit -if ! which airbyte-ci >/dev/null 2>&1; then - echo "airbyte-ci is not installed" - echo "" - echo "Please run 'make tools.airbyte-ci.install' to install airbyte-ci" - exit 1 -fi - -EXPECTED_PATH="$INSTALL_DIR/airbyte-ci" -AIRBYTE_CI_PATH=$(which airbyte-ci 2>/dev/null) -if [ "$AIRBYTE_CI_PATH" != "$EXPECTED_PATH" ]; then - echo "airbyte-ci is not from the expected install location: $EXPECTED_PATH" - echo "airbyte-ci is installed at: $AIRBYTE_CI_PATH" - echo "Check that airbyte-ci exists at $HUMAN_READABLE_INSTALL_DIR and $HUMAN_READABLE_INSTALL_DIR is part of the PATH" - echo "" - echo "If it is, try running 'make tools.airbyte-ci.clean', then run 'make tools.airbyte-ci.install' again" - exit 1 -fi - -# Check if the AIRBYTE_CI_PATH is a symlink -if [ -L "$AIRBYTE_CI_PATH" ]; then - echo "" - echo "#########################################################################" - echo "# #" - echo "# Warning: airbyte-ci at $AIRBYTE_CI_PATH is a symlink. #" - echo "# You are possibly using a development version of airbyte-ci. #" - echo "# To update to a release version, run 'make tools.airbyte-ci.install' #" - echo "# #" - echo "# If this warning persists, try running 'make tools.airbyte-ci.clean' #" - echo "# Then run 'make tools.airbyte-ci.install' again. #" - echo "# #" - echo "#########################################################################" - echo "" -fi - -echo "airbyte-ci is correctly installed at $EXPECTED_PATH" diff --git a/airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_clean.sh b/airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_clean.sh deleted file mode 100755 index 56d2c1fbf371..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_clean.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash -set -o errexit -o nounset -o pipefail - -# Check if pipx is on the path and if so, uninstall pipelines -if which pipx >/dev/null 2>&1; then - # ignore errors if pipelines is not installed - pipx uninstall pipelines || true - echo "Uninstalled pipelines via pipx" -else - echo "pipx not found, skipping uninstall of pipelines" -fi - -# Remove airbyte-ci if it's on the path -while which airbyte-ci >/dev/null 2>&1; do - echo "Removing $(which airbyte-ci)" - rm "$(which airbyte-ci)" -done -echo "Removed airbyte-ci" - -# Remove airbyte-ci-internal if it's on the path -while which airbyte-ci-internal >/dev/null 2>&1; do - echo "Removing $(which airbyte-ci)" - rm "$(which airbyte-ci-internal)" -done -echo "Removed airbyte-ci-internal" - -# Remove airbyte-ci-dev if it's on the path -while which airbyte-ci-dev >/dev/null 2>&1; do - echo "Removing $(which airbyte-ci)" - rm "$(which airbyte-ci-dev)" -done - echo "Removed airbyte-ci-dev" - -# Check if airbyte-ci is stashed away in pyenv -# If so, remove it -# This prevents `pyenv init -` from adding it back to the path -while pyenv whence --path airbyte-ci >/dev/null 2>&1; do - rm "$(pyenv whence --path airbyte-ci)" - echo "Uninstalled pipelines via pyenv" -done - echo "All airbyte-ci references removed from pyenv versions." - -echo "Cleanup of airbyte-ci install completed." diff --git a/airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_dev_install.py b/airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_dev_install.py deleted file mode 100755 index 32a7aa43a9fc..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_dev_install.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -# !IMPORTANT! This script is used to install the airbyte-ci tool on a Linux or macOS system. -# Meaning, no external dependencies are allowed as we don't want users to have to run anything -# other than this script to install the tool. - -import subprocess -import sys - - -def check_command_exists(command: str, not_found_message: str) -> None: - """ - Check if a command exists in the system path. - """ - try: - subprocess.check_call(["which", command], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) - except subprocess.CalledProcessError: - print(not_found_message) - sys.exit(1) - - -def main() -> None: - # Check if Python 3.10 is on the path - check_command_exists( - "python3.11", - """python3.10 not found on the path. -Please install Python 3.11 using pyenv: -1. Install pyenv if not already installed: - brew install pyenv -2. Install Python 3.10 using pyenv: - pyenv install 3.10.12""", - ) - print("Python 3.10 is already installed.") - - # Check if pipx is installed - check_command_exists( - "uv", - """uv not found. Please install uv: `brew install uv` - -After installation, restart your terminal or source your shell -configuration file to ensure the uv command is available.""", - ) - print("uv is already installed.") - - # Install airbyte-ci development version - subprocess.run(["uv", "tool", "install", "--editable", "--force", "--python=python3.11", "airbyte-ci/connectors/pipelines/"]) - print("Development version of airbyte-ci installed successfully.") - - -if __name__ == "__main__": - main() diff --git a/airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_install.py b/airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_install.py deleted file mode 100755 index 01ed0ce20f90..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/external_scripts/airbyte_ci_install.py +++ /dev/null @@ -1,138 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -# !IMPORTANT! This script is used to install the airbyte-ci tool on a Linux or macOS system. -# Meaning, no external dependencies are allowed as we don't want users to have to run anything -# other than this script to install the tool. - -from __future__ import annotations - -import os -import shutil -import ssl -import sys -import urllib.request -from typing import TYPE_CHECKING - -# !IMPORTANT! This constant is inline here instead of being imported from pipelines/consts.py -# because we don't want to introduce any dependencies on other files in the repository. -RELEASE_URL = os.getenv("RELEASE_URL", "https://connectors.airbyte.com/files/airbyte-ci/releases") - -if TYPE_CHECKING: - from typing import Optional - - -def _get_custom_certificate_path() -> Optional[str]: - """ - Returns the path to the custom certificate file if certifi is installed, otherwise None. - - HACK: This is a workaround for the fact that the pyinstaller binary does not know how or where to - find the ssl certificates file. This happens because the binary is built on a different system - than the one it is being run on. This function will return the path to the certifi certificate file - if it is installed, otherwise it will return None. This function is used in get_ssl_context() below. - - WHY: this works when certifi is not found: - If you run this file directly, it will use the system python interpreter and will be able to find - the ssl certificates file. e.g. when running in dev mode or via the makefile. - - WHY: this works when certifi is found: - When this file is run by the pyinstaller binary, it is through the pipelines project, which has - certifi installed. This means that when this file is run by the pyinstaller binary, it will be able - to find the ssl certificates file in the certifi package. - - """ - # if certifi is not installed, do nothing - try: - import certifi - - return certifi.where() - except ImportError: - return None - - -def get_ssl_context() -> ssl.SSLContext: - """ - Returns an ssl.SSLContext object with the custom certificate file if certifi is installed, otherwise - returns the default ssl.SSLContext object. - """ - certifi_path = _get_custom_certificate_path() - if certifi_path is None: - return ssl.create_default_context() - - return ssl.create_default_context(cafile=certifi_path) - - -def get_airbyte_os_name() -> Optional[str]: - """ - Returns 'ubuntu' if the system is Linux or 'macos' if the system is macOS. - """ - OS = os.uname().sysname - if OS == "Linux": - print("Linux based system detected.") - return "ubuntu" - elif OS == "Darwin": - print("macOS based system detected.") - return "macos" - else: - return None - - -def main(version: str = "latest") -> None: - # Determine the operating system - os_name = get_airbyte_os_name() - if os_name is None: - print("Unsupported operating system") - return - - url = f"{RELEASE_URL}/{os_name}/{version}/airbyte-ci" - - # Create the directory if it does not exist - destination_dir = os.path.expanduser("~/.local/bin") - os.makedirs(destination_dir, exist_ok=True) - - # Set the path of the versioned binary - versioned_path = os.path.join(destination_dir, f"airbyte-ci-{version}") - - # If the version is not explicit, delete any existing versioned binary - if version == "latest" and os.path.exists(versioned_path): - os.remove(versioned_path) - - # Download the versioned binary if it doesn't exist - if not os.path.exists(versioned_path): - # Download the file using urllib.request - print(f"Downloading from {url}") - ssl_context = get_ssl_context() - with urllib.request.urlopen(url, context=ssl_context) as response, open(versioned_path, "wb") as out_file: - shutil.copyfileobj(response, out_file) - - # Make the versioned binary executable - os.chmod(versioned_path, 0o755) - - # Ensure that the destination path does not exist. - destination_path = os.path.join(destination_dir, "airbyte-ci") - if os.path.exists(destination_path): - os.remove(destination_path) - - # Symlink the versioned binary to the destination path - os.symlink(versioned_path, destination_path) - - # ASCII Art and Completion Message - install_complete_message = f""" - ╔───────────────────────────────────────────────────────────────────────────────╗ - │ │ - │ AAA IIIII RRRRRR BBBBB YY YY TTTTTTT EEEEEEE CCCCC IIIII │ - │ AAAAA III RR RR BB B YY YY TTT EE CC III │ - │ AA AA III RRRRRR BBBBBB YYYYY TTT EEEEE _____ CC III │ - │ AAAAAAA III RR RR BB BB YYY TTT EE CC III │ - │ AA AA IIIII RR RR BBBBBB YYY TTT EEEEEEE CCCCC IIIII │ - │ │ - │ === Installation complete. v({version})=== │ - │ {destination_path} │ - ╚───────────────────────────────────────────────────────────────────────────────╝ - """ - - print(install_complete_message) - - -if __name__ == "__main__": - version_arg = sys.argv[1] if len(sys.argv) > 1 else "latest" - main(version_arg) diff --git a/airbyte-ci/connectors/pipelines/pipelines/hacks.py b/airbyte-ci/connectors/pipelines/pipelines/hacks.py deleted file mode 100644 index 28b7b298c4ae..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/hacks.py +++ /dev/null @@ -1,145 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""This module contains hacks used in connectors pipelines. They're gathered here for tech debt visibility.""" - -from __future__ import annotations - -from logging import Logger -from typing import TYPE_CHECKING, Callable, List - -import asyncclick as click -from connector_ops.utils import ConnectorLanguage # type: ignore - -from pipelines import consts -from pipelines.airbyte_ci.steps.base_image import UpdateBaseImageMetadata -from pipelines.helpers.github import AIRBYTE_GITHUB_REPO_URL, is_automerge_pull_request, update_commit_status_check - -if TYPE_CHECKING: - from dagger import Container - - from pipelines.airbyte_ci.connectors.context import ConnectorContext - from pipelines.models.steps import StepResult - - -async def cache_latest_cdk(context: ConnectorContext) -> None: - """ - Download the latest CDK version to update the pip cache. - - Underlying issue: - Most Python connectors, or normalization, are not pinning the CDK version they use. - It means that the will get whatever version is in the pip cache. - But the original goal of not pinning the CDK version is to always get the latest version. - - Hack: - Call this function before building connector test environment to update the cache with the latest CDK version. - - Github Issue: - Revisiting and aligning how we build Python connectors and using the same container for test, build and publish will provide better control over the CDK version. - https://github.com/airbytehq/airbyte/issues/25523 - Args: - dagger_client (Client): Dagger client. - """ - # We want the CDK to be re-downloaded on every run per connector to ensure we always get the latest version. - # But we don't want to invalidate the pip cache on every run because it could lead to a different CDK version installed on different architecture build. - cachebuster_value = f"{context.connector.technical_name}_{context.pipeline_start_timestamp}" - - await ( - context.dagger_client.container() - .from_("python:3.9-slim") - .with_mounted_cache(consts.PIP_CACHE_PATH, context.dagger_client.cache_volume(consts.PIP_CACHE_VOLUME_NAME)) - .with_env_variable("CACHEBUSTER", cachebuster_value) - .with_exec(["pip", "install", "--force-reinstall", "airbyte-cdk", "-vvv"], use_entrypoint=True) - .sync() - ) - - -def never_fail_exec(command: List[str]) -> Callable[[Container], Container]: - """ - Wrap a command execution with some bash sugar to always exit with a 0 exit code but write the actual exit code to a file. - - Underlying issue: - When a classic dagger with_exec is returning a >0 exit code an ExecError is raised. - It's OK for the majority of our container interaction. - But some execution, like running CAT, are expected to often fail. - In CAT we don't want ExecError to be raised on container interaction because CAT might write updated secrets that we need to pull from the container after the test run. - The bash trick below is a hack to always return a 0 exit code but write the actual exit code to a file. - The file is then read by the pipeline to determine the exit code of the container. - - Args: - command (List[str]): The command to run in the container. - - Returns: - Callable: _description_ - """ - - def never_fail_exec_inner(container: Container) -> Container: - return container.with_exec(["sh", "-c", f"{' '.join(command)}; echo $? > /exit_code"]) - - return never_fail_exec_inner - - -def do_regression_test_status_check(ctx: click.Context, status_check_name: str, logger: Logger) -> None: - """ - Emit a failing status check that requires a manual override, via a /-command. - - Only required for certified connectors. - """ - commit = ctx.obj["git_revision"] - run_url = ctx.obj["gha_workflow_run_url"] - should_send = ctx.obj.get("ci_context") == consts.CIContext.PULL_REQUEST - - if ( - (not is_automerge_pull_request(ctx.obj.get("pull_request"))) - and (ctx.obj["git_repo_url"] == AIRBYTE_GITHUB_REPO_URL) - and any( - [ - (connector.language == ConnectorLanguage.PYTHON and connector.support_level == "certified") - for connector in ctx.obj["selected_connectors_with_modified_files"] - ] - ) - ): - logger.info(f'is_automerge_pull_request={is_automerge_pull_request(ctx.obj.get("pull_request"))}') - logger.info(f'git_repo_url={ctx.obj["git_repo_url"]}') - for connector in ctx.obj["selected_connectors_with_modified_files"]: - logger.info(f"connector = {connector.name}") - logger.info(f"connector.language={connector.language}") - logger.info(f"connector.support_level = {connector.support_level}") - update_commit_status_check( - commit, - "failure", - run_url, - description="Check if regression tests have been manually approved", - context=status_check_name, - is_optional=False, - should_send=should_send, - logger=logger, - ) - else: - update_commit_status_check( - commit, - "success", - run_url, - description="[Skipped]", - context=status_check_name, - is_optional=True, - should_send=should_send, - logger=logger, - ) - - -def determine_changelog_entry_comment(upgrade_base_image_in_metadata_result: StepResult, default_comment: str) -> str: - assert isinstance( - upgrade_base_image_in_metadata_result.step, UpdateBaseImageMetadata - ), "StepResult's step must be instance of UpdateBaseImageMetadata" - if upgrade_base_image_in_metadata_result.output is not None and upgrade_base_image_in_metadata_result.output.get( - "updated_base_image_address" - ): - updated_base_image_address = upgrade_base_image_in_metadata_result.output.get("updated_base_image_address") - if ( - "airbyte/python-connector-base:3.0.0" in updated_base_image_address - or "airbyte/source-declarative-manifest:6.9.2" in updated_base_image_address - ): - return "Starting with this version, the Docker image is now rootless. Please note that this and future versions will not be compatible with Airbyte versions earlier than 0.64" - return default_comment diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/cache_keys.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/cache_keys.py deleted file mode 100644 index c5fd9b75130a..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/cache_keys.py +++ /dev/null @@ -1,13 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from pipelines.helpers.utils import slugify - - -def get_black_cache_key(black_version: str) -> str: - return slugify(f"black-{black_version}") - - -def get_prettier_cache_key(prettier_version: str) -> str: - return slugify(f"prettier-{prettier_version}") diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/changelog.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/changelog.py deleted file mode 100644 index a062b185f767..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/changelog.py +++ /dev/null @@ -1,126 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import datetime -import re -from dataclasses import dataclass -from operator import attrgetter -from typing import Set, Tuple - -import semver - -from pipelines.helpers.github import AIRBYTE_GITHUB_REPO - - -class ChangelogParsingException(Exception): - pass - - -@dataclass(frozen=True) -class ChangelogEntry: - date: datetime.date - version: semver.Version - pr_number: int | str - comment: str - - def to_markdown(self, github_repo: str = AIRBYTE_GITHUB_REPO) -> str: - return f'| {self.version} | {self.date.strftime("%Y-%m-%d")} | [{self.pr_number}](https://github.com/{github_repo}/pull/{self.pr_number}) | {self.comment} |' - - def __str__(self) -> str: - return f'version={self.version}, data={self.date.strftime("%Y-%m-%d")}, pr_number={self.pr_number}, comment={self.comment}' - - def __repr__(self) -> str: - return "ChangelogEntry: " + self.__str__() - - def __eq__(self, other: object) -> bool: - if not isinstance(other, ChangelogEntry): - return False - entry_matches = ( - self.date == other.date - and self.version == other.version - and str(self.pr_number) == str(other.pr_number) - and self.comment == other.comment - ) - return entry_matches - - def __ne__(self, other: object) -> bool: - return not (self.__eq__(other)) - - def __hash__(self) -> int: - return self.__str__().__hash__() - - -def parse_markdown(markdown_lines: list[str], github_repo: str) -> Tuple[int, Set[ChangelogEntry]]: - """This parses the markdown to find the changelog table, and then populates entries with the existing entries""" - changelog_entry_re = ( - "^\\| *(?P[0-9]+\\.[0-9+]+\\.[0-9]+?) *\\| *" - + "(?P[0-9]{4}-[0-9]{2}-[0-9]{2}) *\\| *" - + "\\[?(?P[0-9]+)\\]? ?\\(https://github.com/" - + github_repo - + "/pull/(?P[0-9]+)\\) *\\| *" - + "(?P[^ ].*[^ ]) *\\| *$" - ) - changelog_header_line_index = -1 - changelog_line_enumerator = enumerate(markdown_lines) - for line_index, line in changelog_line_enumerator: - if re.search(r"\| *Version *\| *Date *\| *Pull Request *\| *Subject *\|", line): - changelog_header_line_index = line_index - break - if changelog_header_line_index == -1: - raise ChangelogParsingException("Could not find the changelog section table in the documentation file.") - if markdown_lines[changelog_header_line_index - 1] != "": - raise ChangelogParsingException( - "Found changelog section table in the documentation file at line but there is not blank line before it." - ) - if not re.search(r"(\|[- :]*){4}\|", next(changelog_line_enumerator)[1]): - raise ChangelogParsingException("The changelog table in the documentation file is missing the header delimiter.") - changelog_entries_start_line_index = changelog_header_line_index + 2 - - # parse next line to see if it needs to be cut - entries = set() - for line_index, line in changelog_line_enumerator: - changelog_entry_regexp = re.search(changelog_entry_re, line) - if not changelog_entry_regexp or changelog_entry_regexp.group("pr_number1") != changelog_entry_regexp.group("pr_number2"): - break - entry_version = semver.VersionInfo.parse(changelog_entry_regexp.group("version")) - entry_date = datetime.datetime.strptime(changelog_entry_regexp.group("day"), "%Y-%m-%d").date() - entry_pr_number = int(changelog_entry_regexp.group("pr_number1")) - entry_comment = changelog_entry_regexp.group("comment") - changelog_entry = ChangelogEntry(entry_date, entry_version, entry_pr_number, entry_comment) - entries.add(changelog_entry) - - return changelog_entries_start_line_index, entries - - -class Changelog: - def __init__(self, markdown: str, github_repo: str = AIRBYTE_GITHUB_REPO) -> None: - self.original_markdown_lines = markdown.splitlines() - self.changelog_entries_start_line_index, self.original_entries = parse_markdown(self.original_markdown_lines, github_repo) - self.new_entries: Set[ChangelogEntry] = set() - self.github_repo = github_repo - - def add_entry(self, version: semver.Version, date: datetime.date, pull_request_number: int | str, comment: str) -> None: - self.new_entries.add(ChangelogEntry(date, version, pull_request_number, comment)) - - def to_markdown(self) -> str: - """ - Generates the complete markdown content for the changelog, - including both original and new entries, sorted by version, date, pull request number, and comment. - """ - all_entries = set(self.original_entries.union(self.new_entries)) - sorted_entries = sorted( - sorted( - all_entries, - key=attrgetter("date"), - reverse=True, - ), - key=attrgetter("version"), - reverse=True, - ) - new_lines = ( - self.original_markdown_lines[: self.changelog_entries_start_line_index] - + [line.to_markdown(self.github_repo) for line in sorted_entries] - + self.original_markdown_lines[(self.changelog_entries_start_line_index + len(self.original_entries)) :] - ) - return "\n".join(new_lines) + "\n" diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/cli.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/cli.py deleted file mode 100644 index 4440fd4e466c..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/cli.py +++ /dev/null @@ -1,101 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - - -from dataclasses import dataclass -from logging import Logger -from typing import Any, List, Optional - -import asyncclick as click -import asyncer -from jinja2 import Template - -from pipelines.models.steps import CommandResult - -ALL_RESULTS_KEY = "_run_all_results" - -SUMMARY_TEMPLATE_STR = """ -{% if command_results %} -Summary of commands results -======================== -{% for command_result in command_results %} -{{ '✅' if command_result.success else '❌' }} {{ command_result.command.name }} -{% endfor %} -{% endif %} -""" - -DETAILS_TEMPLATE_STR = """ -{% for command_result in command_results %} -{% if command_result.stdout or command_result.stderr %} -================================= - -Details for {{ command_result.command.name }} command -{% if command_result.stdout %} -STDOUT: -{{ command_result.stdout }} -{% endif %} -{% if command_result.stderr %} -STDERR: -{{ command_result.stderr }} -{% endif %} -{% endif %} -{% endfor %} - -""" - - -@dataclass -class LogOptions: - quiet: bool = True - help_message: Optional[str] = None - - -def log_command_results( - ctx: click.Context, command_results: List[CommandResult], logger: Logger, options: LogOptions = LogOptions() -) -> None: - """ - Log the output of the subcommands run by `run_all_subcommands`. - """ - - if not options.quiet: - details_template = Template(DETAILS_TEMPLATE_STR) - details_message = details_template.render(command_results=command_results) - logger.info(details_message) - - summary_template = Template(SUMMARY_TEMPLATE_STR) - summary_message = summary_template.render(command_results=command_results) - logger.info(summary_message) - - if options.help_message: - logger.info(options.help_message) - - -async def invoke_commands_concurrently(ctx: click.Context, commands: List[click.Command]) -> List[Any]: - """ - Run click commands concurrently and return a list of their return values. - """ - - soon_command_executions_results = [] - async with asyncer.create_task_group() as command_task_group: - for command in commands: - soon_command_execution_result = command_task_group.soonify(command.invoke)(ctx) - soon_command_executions_results.append(soon_command_execution_result) - return [r.value for r in soon_command_executions_results] - - -async def invoke_commands_sequentially(ctx: click.Context, commands: List[click.Command]) -> List[Any]: - """ - Run click commands sequentially and return a list of their return values. - """ - command_executions_results = [] - for command in commands: - command_executions_results.append(await command.invoke(ctx)) - return command_executions_results - - -def get_all_sibling_commands(ctx: click.Context) -> List[click.Command]: - """ - Get all sibling commands of the current command. - """ - return [c for c in ctx.parent.command.commands.values() if c.name != ctx.command.name] # type: ignore diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/cdk_helpers.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/cdk_helpers.py deleted file mode 100644 index 30f546aca752..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/cdk_helpers.py +++ /dev/null @@ -1,26 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -import re - -import requests -from dagger import Directory - - -def get_latest_python_cdk_version() -> str: - """ - Get the latest version of airbyte-cdk from pypi - """ - cdk_pypi_url = "https://pypi.org/pypi/airbyte-cdk/json" - response = requests.get(cdk_pypi_url) - response.raise_for_status() - package_info = response.json() - return package_info["info"]["version"] - - -async def get_latest_java_cdk_version(repo_dir: Directory) -> str: - version_file_content = await repo_dir.file("airbyte-cdk/java/airbyte-cdk/core/src/main/resources/version.properties").contents() - match = re.search(r"version *= *(?P[0-9]*\.[0-9]*\.[0-9]*)", version_file_content) - if match: - return match.group("version") - raise ValueError("Could not find version in version.properties") diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/command.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/command.py deleted file mode 100644 index 2f822c0e8f2b..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/command.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from typing import TYPE_CHECKING, Any, Callable, List - -import asyncclick as click - -from pipelines.airbyte_ci.connectors.context import ConnectorContext -from pipelines.airbyte_ci.connectors.pipeline import run_connectors_pipelines -from pipelines.airbyte_ci.connectors.reports import ConnectorReport, Report -from pipelines.helpers.execution.run_steps import STEP_TREE, run_steps -from pipelines.models.steps import Step, StepStatus - -if TYPE_CHECKING: - from anyio import Semaphore - - -def get_connector_contexts(ctx: click.Context, pipeline_description: str, enable_report_auto_open: bool) -> List[ConnectorContext]: - connectors_contexts = [ - ConnectorContext( - pipeline_name=f"{pipeline_description}: {connector.technical_name}", - connector=connector, - is_local=ctx.obj["is_local"], - git_branch=ctx.obj["git_branch"], - git_revision=ctx.obj["git_revision"], - diffed_branch=ctx.obj["diffed_branch"], - git_repo_url=ctx.obj["git_repo_url"], - ci_report_bucket=ctx.obj["ci_report_bucket_name"], - report_output_prefix=ctx.obj["report_output_prefix"], - gha_workflow_run_url=ctx.obj.get("gha_workflow_run_url"), - dagger_logs_url=ctx.obj.get("dagger_logs_url"), - pipeline_start_timestamp=ctx.obj.get("pipeline_start_timestamp"), - ci_context=ctx.obj.get("ci_context"), - ci_gcp_credentials=ctx.obj["ci_gcp_credentials"], - ci_git_user=ctx.obj["ci_git_user"], - ci_github_access_token=ctx.obj["ci_github_access_token"], - enable_report_auto_open=enable_report_auto_open, - docker_hub_username=ctx.obj.get("docker_hub_username"), - docker_hub_password=ctx.obj.get("docker_hub_password"), - s3_build_cache_access_key_id=ctx.obj.get("s3_build_cache_access_key_id"), - s3_build_cache_secret_key=ctx.obj.get("s3_build_cache_secret_key"), - genai_api_key=ctx.obj.get("genai_api_key"), - dbdocs_token=ctx.obj.get("dbdocs_token"), - ) - for connector in ctx.obj["selected_connectors_with_modified_files"] - ] - return connectors_contexts - - -async def run_connector_pipeline( - ctx: click.Context, - pipeline_description: str, - enable_report_auto_open: bool, - connector_pipeline: Callable, - *args: Any, -) -> bool: - connectors_contexts = get_connector_contexts(ctx, pipeline_description, enable_report_auto_open=enable_report_auto_open) - await run_connectors_pipelines( - connectors_contexts, - connector_pipeline, - pipeline_description, - ctx.obj["concurrency"], - ctx.obj["dagger_logs_path"], - ctx.obj["execute_timeout"], - *args, - ) - - return True - - -async def run_connector_steps( - context: ConnectorContext, semaphore: "Semaphore", steps_to_run: STEP_TREE, restore_original_state: Step | None = None -) -> Report: - async with semaphore: - async with context: - try: - result_dict = await run_steps( - runnables=steps_to_run, - options=context.run_step_options, - ) - except Exception as e: - if restore_original_state: - await restore_original_state.run() - raise e - results = list(result_dict.values()) - if restore_original_state: - if any(step_result.status is StepStatus.FAILURE for step_result in results): - await restore_original_state.run() - else: - # cleanup if available - if hasattr(restore_original_state, "_cleanup"): - method = getattr(restore_original_state, "_cleanup") - if callable(method): - await method() - - report = ConnectorReport(context, steps_results=results, name="TEST RESULTS") - context.report = report - return report diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/dagger_fs.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/dagger_fs.py deleted file mode 100644 index e6fb8fa43f42..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/dagger_fs.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from pathlib import Path - -from dagger import Directory, QueryError - - -# TODO: sometimes we have the full path (connector.metadata_file_path) but we want to be using just the connector dir -# so we could pass in a subdir here: -# await file_exists(connector_dir, connector.metadata_file_path, relative_to=connector.code_directory) -async def dagger_file_exists(dir: Directory, path: Path | str) -> bool: - try: - await dir.file(str(path)) - return True - except QueryError: - return False - - -async def dagger_read_file(directory: Directory, path: Path | str) -> str: - if str(path) not in await directory.entries(): - raise FileNotFoundError(f"File {path} not found in directory {directory}") - content = await directory.file(str(path)).contents() - return content - - -def dagger_write_file(directory: Directory, path: Path | str, new_content: str) -> Directory: - directory = directory.with_new_file(str(path), contents=new_content) - return directory - - -async def dagger_export_file(directory: Directory, path: Path | str) -> bool: - await directory.file(str(path)).export(str(path)) - return True - - -async def dagger_dir_exists(dir: Directory, path: Path | str) -> bool: - try: - await dir.directory(str(path)) - return True - except QueryError: - return False diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/format.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/format.py deleted file mode 100644 index 10aab0946569..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/format.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -import logging -import subprocess -from pathlib import Path -from typing import List - -from pipelines.cli.ensure_repo_root import get_airbyte_repo_path_with_fallback - - -async def format_prettier(files: List[Path], logger: logging.Logger) -> None: - if len(files) == 0: - return - - repo_root_path = get_airbyte_repo_path_with_fallback() - config_path = repo_root_path / ".prettierrc" - if not config_path.exists(): - raise Exception(f"Prettier config file not found: {config_path}") - - to_format = [str(file) for file in files] - - logger.info(f" Formatting files: npx prettier --write {' '.join(to_format)}") - command = ["npx", "prettier", "--config", str(config_path), "--write"] + to_format - result = subprocess.run(command, capture_output=True, text=True) - if result.returncode == 0: - logger.info(" Files formatted successfully.") - else: - logger.warn(" Error formatting files.") - - -def verify_formatters() -> None: - try: - subprocess.run(["npx", "--version"], check=True) - except subprocess.CalledProcessError: - raise Exception("npx is required to format files. Please install Node.js and npm.") diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/modifed.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/modifed.py deleted file mode 100644 index 7fcad4bfc83e..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/modifed.py +++ /dev/null @@ -1,89 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from dataclasses import dataclass, field -from pathlib import Path -from typing import FrozenSet, Set, Union - -from connector_ops.utils import Connector # type: ignore - -from pipelines import main_logger -from pipelines.helpers.utils import IGNORED_FILE_EXTENSIONS, IGNORED_FILE_NAMES, METADATA_FILE_NAME - - -def get_connector_modified_files(connector: Connector, all_modified_files: Set[Path]) -> FrozenSet[Path]: - connector_modified_files = set() - for modified_file in all_modified_files: - modified_file_path = Path(modified_file) - if modified_file_path.is_relative_to(connector.code_directory): - connector_modified_files.add(modified_file) - return frozenset(connector_modified_files) - - -def _is_connector_modified_directly(connector: Connector, modified_files: Set[Path]) -> bool: - """Test if the connector is being impacted by file changes in the connector itself.""" - for file_path in modified_files: - if _is_ignored_file(file_path): - continue - - if Path(file_path).is_relative_to(Path(connector.code_directory)) or file_path == connector.documentation_file_path: - main_logger.info(f"Adding connector '{connector}' due to connector file modification: {file_path}.") - return True - - return False - - -def _is_connector_modified_indirectly(connector: Connector, modified_files: Set[Path]) -> bool: - """Test if the connector is being impacted by file changes in the connector's dependencies.""" - connector_dependencies = connector.get_local_dependency_paths() - - for file_path in modified_files: - if _is_ignored_file(file_path): - continue - - for connector_dependency in connector_dependencies: - if Path(file_path).is_relative_to(Path(connector_dependency)): - main_logger.info(f"Adding connector '{connector}' due to dependency modification: '{file_path}'.") - return True - - return False - - -def _is_ignored_file(file_path: Union[str, Path]) -> bool: - """Check if the provided file has an ignored extension.""" - return Path(file_path).suffix in IGNORED_FILE_EXTENSIONS or Path(file_path).name in IGNORED_FILE_NAMES - - -def get_modified_connectors(modified_files: Set[Path], all_connectors: Set[Connector], dependency_scanning: bool) -> Set[Connector]: - """Create a mapping of modified connectors (key) and modified files (value). - If dependency scanning is enabled any modification to a dependency will trigger connector pipeline for all connectors that depend on it. - It currently works only for Java connectors . - It's especially useful to trigger tests of strict-encrypt variant when a change is made to the base connector. - Or to tests all jdbc connectors when a change is made to source-jdbc or base-java. - We'll consider extending the dependency resolution to Python connectors once we confirm that it's needed and feasible in term of scale. - """ - modified_connectors = set() - active_connectors = {conn for conn in all_connectors if conn.support_level != "archived"} - main_logger.info( - f"Checking for modified files. Skipping {len(all_connectors) - len(active_connectors)} connectors with support level 'archived'." - ) - # Ignore files with certain extensions - active_modified_files = {f for f in modified_files if not _is_ignored_file(f)} - - for connector in active_connectors: - if _is_connector_modified_directly(connector, active_modified_files): - modified_connectors.add(connector) - elif dependency_scanning and _is_connector_modified_indirectly(connector, active_modified_files): - modified_connectors.add(connector) - - return modified_connectors - - -@dataclass(frozen=True) -class ConnectorWithModifiedFiles(Connector): - modified_files: FrozenSet[Path] = field(default_factory=frozenset) - - @property - def has_metadata_change(self) -> bool: - return any(path.name == METADATA_FILE_NAME for path in self.modified_files) diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/yaml.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/yaml.py deleted file mode 100644 index 5b6a544e6e46..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/connectors/yaml.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -import copy -import io -from pathlib import Path -from typing import List - -from dagger import Directory -from ruamel.yaml import YAML # type: ignore - - -def read_yaml(file_path: Path | str) -> dict: - yaml = YAML() - yaml.preserve_quotes = True - return yaml.load(file_path) - - -async def read_yaml_from_directory(directory: Directory, file_path: str | Path) -> dict: - yaml = YAML() - yaml.preserve_quotes = True - if str(file_path) not in await directory.entries(): - raise FileNotFoundError(f"File {file_path} not found in directory {directory}") - contents = await directory.file(str(file_path)).contents() - return yaml.load(contents) - - -async def write_yaml_to_directory(directory: Directory, yaml_input: dict | List, file_path: str | Path) -> Directory: - data = copy.deepcopy(yaml_input) - yaml = YAML() - buffer = io.BytesIO() - yaml.dump(data, buffer) - new_content = buffer.getvalue().decode("utf-8") - directory = await directory.with_new_file(str(file_path), contents=new_content) - return directory - - -def write_yaml(input: dict | List, file_path: str | Path) -> None: - data = copy.deepcopy(input) - yaml = YAML() - buffer = io.BytesIO() - yaml.dump(data, buffer) - with open(file_path, "w") as file: - file.write(buffer.getvalue().decode("utf-8")) diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/execution/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/execution/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/execution/argument_parsing.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/execution/argument_parsing.py deleted file mode 100644 index af32aa52b213..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/execution/argument_parsing.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -import re -from typing import TYPE_CHECKING - -import asyncclick as click - -if TYPE_CHECKING: - from enum import Enum - from typing import Callable, Dict, Tuple, Type - - from pipelines.models.steps import STEP_PARAMS - -# Pattern for extra param options: --.= -EXTRA_PARAM_PATTERN_FOR_OPTION = re.compile(r"^--([a-zA-Z_][a-zA-Z0-9_]*)\.([a-zA-Z_-][a-zA-Z0-9_-]*)=([^=]+)$") -# Pattern for extra param flag: --. -EXTRA_PARAM_PATTERN_FOR_FLAG = re.compile(r"^--([a-zA-Z_][a-zA-Z0-9_]*)\.([a-zA-Z_-][a-zA-Z0-9_-]*)$") -EXTRA_PARAM_PATTERN_ERROR_MESSAGE = "The extra flags must be structured as --. for flags or --.= for options. You can use - or -- for option/flag names." - - -def build_extra_params_mapping(SupportedStepIds: Type[Enum]) -> Callable: - def callback(ctx: click.Context, argument: click.core.Argument, raw_extra_params: Tuple[str]) -> Dict[str, STEP_PARAMS]: - """Build a mapping of step id to extra params. - Validate the extra params and raise a ValueError if they are invalid. - Validation rules: - - The extra params must be structured as --.= for options or --. for flags. - - The step id must be one of the existing step ids. - - - Args: - ctx (click.Context): The click context. - argument (click.core.Argument): The click argument. - raw_extra_params (Tuple[str]): The extra params provided by the user. - Raises: - ValueError: Raised if the extra params format is invalid. - ValueError: Raised if the step id in the extra params is not one of the unique steps to run. - - Returns: - Dict[Literal, STEP_PARAMS]: The mapping of step id to extra params. - """ - extra_params_mapping: Dict[str, STEP_PARAMS] = {} - for param in raw_extra_params: - is_flag = "=" not in param - pattern = EXTRA_PARAM_PATTERN_FOR_FLAG if is_flag else EXTRA_PARAM_PATTERN_FOR_OPTION - matches = pattern.match(param) - if not matches: - raise ValueError(f"Invalid parameter {param}. {EXTRA_PARAM_PATTERN_ERROR_MESSAGE}") - if is_flag: - step_name, param_name = matches.groups() - param_value = None - else: - step_name, param_name, param_value = matches.groups() - try: - step_id = SupportedStepIds(step_name).value - except ValueError: - raise ValueError(f"Invalid step name {step_name}, it must be one of {[step_id.value for step_id in SupportedStepIds]}") - - extra_params_mapping.setdefault(step_id, {}).setdefault(param_name, []) - # param_value is None if the param is a flag - if param_value is not None: - extra_params_mapping[step_id][param_name].append(param_value) - return extra_params_mapping - - return callback diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/execution/run_steps.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/execution/run_steps.py deleted file mode 100644 index 2d6abeede1ad..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/execution/run_steps.py +++ /dev/null @@ -1,345 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""The actions package is made to declare reusable pipeline components.""" - -from __future__ import annotations - -import inspect -from dataclasses import dataclass, field -from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict, List, Optional, Set, Tuple, Union - -import anyio -import asyncer -import dpath - -from pipelines import main_logger -from pipelines.models.steps import StepStatus - -if TYPE_CHECKING: - from pipelines.airbyte_ci.connectors.consts import CONNECTOR_TEST_STEP_ID - from pipelines.models.steps import STEP_PARAMS, Step, StepResult - - RESULTS_DICT = Dict[str, StepResult] - ARGS_TYPE = Union[Dict, Callable[[RESULTS_DICT], Dict], Awaitable[Dict]] - - -class InvalidStepConfiguration(Exception): - pass - - -def _get_dependency_graph(steps: STEP_TREE) -> Dict[str, List[str]]: - """ - Get the dependency graph of a step tree. - """ - dependency_graph: Dict[str, List[str]] = {} - for step in steps: - if isinstance(step, StepToRun): - dependency_graph[step.id] = step.depends_on - elif isinstance(step, list): - nested_dependency_graph = _get_dependency_graph(list(step)) - dependency_graph = {**dependency_graph, **nested_dependency_graph} - else: - raise Exception(f"Unexpected step type: {type(step)}") - - return dependency_graph - - -def _get_transitive_dependencies_for_step_id( - dependency_graph: Dict[str, List[str]], step_id: str, visited: Optional[Set[str]] = None -) -> List[str]: - """Get the transitive dependencies for a step id. - - Args: - dependency_graph (Dict[str, str]): The dependency graph to use. - step_id (str): The step id to get the transitive dependencies for. - visited (Optional[Set[str]], optional): The set of visited step ids. Defaults to None. - - Returns: - List[str]: List of transitive dependencies as step ids. - """ - if visited is None: - visited = set() - - if step_id not in visited: - visited.add(step_id) - - dependencies: List[str] = dependency_graph.get(step_id, []) - for dependency in dependencies: - dependencies.extend(_get_transitive_dependencies_for_step_id(dependency_graph, dependency, visited)) - - return dependencies - else: - return [] - - -@dataclass -class RunStepOptions: - """Options for the run_step function.""" - - fail_fast: bool = True - skip_steps: List[str] = field(default_factory=list) - keep_steps: List[str] = field(default_factory=list) - log_step_tree: bool = True - concurrency: int = 10 - step_params: Dict[CONNECTOR_TEST_STEP_ID, STEP_PARAMS] = field(default_factory=dict) - - def __post_init__(self) -> None: - if self.skip_steps and self.keep_steps: - raise ValueError("Cannot use both skip_steps and keep_steps at the same time") - - def get_step_ids_to_skip(self, runnables: STEP_TREE) -> List[str]: - if self.skip_steps: - return self.skip_steps - if self.keep_steps: - step_ids_to_keep = set(self.keep_steps) - dependency_graph = _get_dependency_graph(runnables) - all_step_ids = set(dependency_graph.keys()) - for step_id in self.keep_steps: - step_ids_to_keep.update(_get_transitive_dependencies_for_step_id(dependency_graph, step_id)) - return list(all_step_ids - step_ids_to_keep) - return [] - - @staticmethod - def get_item_or_default(options: Dict[str, List[Any]], key: str, default: Any) -> Any: # noqa: ANN401 - try: - item = dpath.util.get(options, key, separator="/") - except KeyError: - return default - - if not isinstance(item, List): - return item - if len(item) > 1: - raise ValueError(f"Only one value for {key} is allowed. Got {len(item)}") - return item[0] if item else default - - -@dataclass(frozen=True) -class StepToRun: - """ - A class to wrap a Step with its id and args. - - Used to coordinate the execution of multiple steps inside a pipeline. - """ - - id: CONNECTOR_TEST_STEP_ID - step: Step - args: ARGS_TYPE = field(default_factory=dict) - depends_on: List[str] = field(default_factory=list) - - -STEP_TREE = List[StepToRun | List[StepToRun]] - - -async def evaluate_run_args(args: ARGS_TYPE, results: RESULTS_DICT) -> Dict: - """ - Evaluate the args of a StepToRun using the results of previous steps. - """ - if inspect.iscoroutinefunction(args): - return await args(results) - elif callable(args): - return args(results) - elif isinstance(args, dict): - return args - - raise TypeError(f"Unexpected args type: {type(args)}") - - -def _skip_remaining_steps(remaining_steps: STEP_TREE) -> RESULTS_DICT: - """ - Skip all remaining steps. - """ - skipped_results: Dict[str, StepResult] = {} - for runnable_step in remaining_steps: - if isinstance(runnable_step, StepToRun): - skipped_results[runnable_step.id] = runnable_step.step.skip() - elif isinstance(runnable_step, list): - nested_skipped_results = _skip_remaining_steps(list(runnable_step)) - skipped_results = {**skipped_results, **nested_skipped_results} - else: - raise Exception(f"Unexpected step type: {type(runnable_step)}") - - return skipped_results - - -def _step_dependencies_succeeded(step_to_eval: StepToRun, results: RESULTS_DICT) -> bool: - """ - Check if all dependencies of a step have succeeded. - """ - main_logger.info(f"Checking if dependencies {step_to_eval.depends_on} have succeeded") - - # Check if all depends_on keys are in the results dict - # If not, that means a step has not been run yet - # Implying that the order of the steps are not correct - for step_id in step_to_eval.depends_on: - if step_id not in results: - raise InvalidStepConfiguration( - f"Step {step_to_eval.id} depends on {step_id} which has not been run yet. This implies that the order of the steps is not correct. Please check that the steps are in the correct order." - ) - - return all( - results[step_id] and (results[step_id].status is StepStatus.SUCCESS or not results[step_id].consider_in_overall_status) - for step_id in step_to_eval.depends_on - ) - - -def _filter_skipped_steps(steps_to_evaluate: STEP_TREE, skip_steps: List[str], results: RESULTS_DICT) -> Tuple[STEP_TREE, RESULTS_DICT]: - """ - Filter out steps that should be skipped. - - Either because they are in the skip list or because one of their dependencies failed. - """ - steps_to_run: STEP_TREE = [] - for step_to_eval in steps_to_evaluate: - # ignore nested steps - if isinstance(step_to_eval, list): - steps_to_run.append(step_to_eval) - continue - - # skip step if its id is in the skip list - if step_to_eval.id in skip_steps: - main_logger.info(f"Skipping step {step_to_eval.id}") - results[step_to_eval.id] = step_to_eval.step.skip("Skipped by user") - - # skip step if a dependency failed - elif not _step_dependencies_succeeded(step_to_eval, results): - main_logger.info( - f"Skipping step {step_to_eval.id} because one of the dependencies have not been met: {step_to_eval.depends_on}" - ) - results[step_to_eval.id] = step_to_eval.step.skip("Skipped because a dependency was not met") - - else: - steps_to_run.append(step_to_eval) - - return steps_to_run, results - - -def _get_next_step_group(steps: STEP_TREE) -> Tuple[STEP_TREE, STEP_TREE]: - """ - Get the next group of steps to run concurrently. - """ - if not steps: - return [], [] - - if isinstance(steps[0], list): - return list(steps[0]), list(steps[1:]) - else: - # Termination case: if the next step is not a list that means we have reached the max depth - return steps, [] - - -def _log_step_tree(step_tree: STEP_TREE, options: RunStepOptions, depth: int = 0) -> None: - """ - Log the step tree to the console. - - e.g. - Step tree - - step1 - - step2 - - step3 - - step4 (skip) - - step5 - - step6 - """ - indent = " " - for steps in step_tree: - if isinstance(steps, list): - _log_step_tree(list(steps), options, depth + 1) - else: - if steps.id in options.skip_steps: - main_logger.info(f"{indent * depth}- {steps.id} (skip)") - else: - main_logger.info(f"{indent * depth}- {steps.id}") - - -async def run_steps( - runnables: STEP_TREE, - results: RESULTS_DICT = {}, - options: RunStepOptions = RunStepOptions(), -) -> RESULTS_DICT: - """Run multiple steps sequentially, or in parallel if steps are wrapped into a sublist. - - Examples - -------- - >>> from pipelines.models.steps import Step, StepResult, StepStatus - >>> class TestStep(Step): - ... async def _run(self) -> StepResult: - ... return StepResult(step=self, status=StepStatus.SUCCESS) - >>> steps = [ - ... StepToRun(id="step1", step=TestStep()), - ... [ - ... StepToRun(id="step2", step=TestStep()), - ... StepToRun(id="step3", step=TestStep()), - ... ], - ... StepToRun(id="step4", step=TestStep()), - ... ] - >>> results = await run_steps(steps) - >>> results["step1"].status - - >>> results["step2"].status - - >>> results["step3"].status - - >>> results["step4"].status - - - - Args: - runnables (List[StepToRun]): List of steps to run. - results (RESULTS_DICT, optional): Dictionary of step results, used for recursion. - - Returns: - RESULTS_DICT: Dictionary of step results. - """ - # If there are no steps to run, return the results - if not runnables: - return results - - step_ids_to_skip = options.get_step_ids_to_skip(runnables) - # Log the step tree - if options.log_step_tree: - main_logger.info(f"STEP TREE: {runnables}") - _log_step_tree(runnables, options) - options.log_step_tree = False - - # If any of the previous steps failed, skip the remaining steps - if options.fail_fast and any(result.status is StepStatus.FAILURE and result.consider_in_overall_status for result in results.values()): - skipped_results = _skip_remaining_steps(runnables) - return {**results, **skipped_results} - - # Pop the next step to run - steps_to_evaluate, remaining_steps = _get_next_step_group(runnables) - - # Remove any skipped steps - steps_to_run, results = _filter_skipped_steps(steps_to_evaluate, step_ids_to_skip, results) - - # Run all steps in list concurrently - semaphore = anyio.Semaphore(options.concurrency) - async with semaphore: - async with asyncer.create_task_group() as task_group: - tasks = [] - for step_to_run in steps_to_run: - # if the step to run is a list, run it in parallel - if isinstance(step_to_run, list): - tasks.append(task_group.soonify(run_steps)(list(step_to_run), results, options)) - else: - step_args = await evaluate_run_args(step_to_run.args, results) - step_to_run.step.extra_params = options.step_params.get(step_to_run.id, {}) - main_logger.info(f"QUEUING STEP {step_to_run.id}") - tasks.append(task_group.soonify(step_to_run.step.run)(**step_args)) - - # Apply new results - new_results: Dict[str, Any] = {} - for i, task in enumerate(tasks): - step_to_run = steps_to_run[i] - if isinstance(step_to_run, list): - new_results = {**new_results, **task.value} - else: - new_results[step_to_run.id] = task.value - - return await run_steps( - runnables=remaining_steps, - results={**results, **new_results}, - options=options, - ) diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/gcs.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/gcs.py deleted file mode 100644 index a73cf7f686ec..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/gcs.py +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import json -from pathlib import Path -from typing import Tuple - -from google.cloud import storage # type: ignore -from google.oauth2 import service_account # type: ignore - -from pipelines import main_logger -from pipelines.consts import GCS_PUBLIC_DOMAIN - - -def upload_to_gcs(file_path: Path, bucket_name: str, object_name: str, credentials: str) -> Tuple[str, str]: - """Upload a file to a GCS bucket. - - Args: - file_path (Path): The path to the file to upload. - bucket_name (str): The name of the GCS bucket. - object_name (str): The name of the object in the GCS bucket. - credentials (str): The GCS credentials as a JSON string. - """ - # Exit early if file does not exist - if not file_path.exists(): - main_logger.warning(f"File {file_path} does not exist. Skipping upload to GCS.") - return "", "" - - credentials = service_account.Credentials.from_service_account_info(json.loads(credentials)) - client = storage.Client(credentials=credentials) - bucket = client.get_bucket(bucket_name) - blob = bucket.blob(object_name) - blob.upload_from_filename(str(file_path)) - gcs_uri = f"gs://{bucket_name}/{object_name}" - public_url = f"{GCS_PUBLIC_DOMAIN}/{bucket_name}/{object_name}" - return gcs_uri, public_url - - -def sanitize_gcp_credentials(raw_value: str) -> str: - """Try to parse the raw string input that should contain a json object with the GCS credentials. - It will raise an exception if the parsing fails and help us to fail fast on invalid credentials input. - - Args: - raw_value (str): A string representing a json object with the GCS credentials. - - Returns: - str: The raw value string if it was successfully parsed. - """ - return json.dumps(json.loads(raw_value)) diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/git.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/git.py deleted file mode 100644 index 926a07a76867..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/git.py +++ /dev/null @@ -1,129 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import functools -from typing import Set - -import git -from dagger import Connection, SessionError - -from pipelines.consts import CIContext -from pipelines.dagger.containers.git import checked_out_git_container -from pipelines.helpers.github import AIRBYTE_GITHUB_REPO_URL -from pipelines.helpers.utils import DAGGER_CONFIG, DIFF_FILTER - - -def get_current_git_revision() -> str: # noqa D103 - return git.Repo(search_parent_directories=True).head.object.hexsha - - -def get_current_git_branch() -> str: # noqa D103 - return git.Repo(search_parent_directories=True).active_branch.name - - -async def get_modified_files_in_branch_remote( - current_git_repo_url: str, current_git_branch: str, current_git_revision: str, diffed_branch: str = "master", retries: int = 3 -) -> Set[str]: - """Use git diff to spot the modified files on the remote branch.""" - try: - async with Connection(DAGGER_CONFIG) as dagger_client: - container = await checked_out_git_container( - dagger_client, current_git_branch, current_git_revision, diffed_branch, repo_url=current_git_repo_url - ) - modified_files = await container.with_exec( - ["diff", f"--diff-filter={DIFF_FILTER}", "--name-only", f"origin/{diffed_branch}...target/{current_git_branch}"], - use_entrypoint=True, - ).stdout() - except SessionError: - if retries > 0: - return await get_modified_files_in_branch_remote( - current_git_repo_url, current_git_branch, current_git_revision, diffed_branch, retries - 1 - ) - else: - raise - return set(modified_files.split("\n")) - - -def get_modified_files_local(current_git_revision: str, diffed: str = "master") -> Set[str]: - """Use git diff and git status to spot the modified files in the local repo.""" - airbyte_repo = git.Repo() - modified_files = airbyte_repo.git.diff(f"--diff-filter={DIFF_FILTER}", "--name-only", f"{diffed}...{current_git_revision}").split("\n") - status_output = airbyte_repo.git.status("--porcelain") - for not_committed_change in status_output.split("\n"): - file_path = not_committed_change.strip().split(" ")[-1] - if file_path: - modified_files.append(file_path) - return set(modified_files) - - -async def get_modified_files_in_branch( - current_repo_url: str, current_git_branch: str, current_git_revision: str, diffed_branch: str, is_local: bool = True -) -> Set[str]: - """Retrieve the list of modified files on the branch.""" - if is_local: - return get_modified_files_local(current_git_revision, diffed_branch) - else: - return await get_modified_files_in_branch_remote(current_repo_url, current_git_branch, current_git_revision, diffed_branch) - - -async def get_modified_files_in_commit_remote(current_git_branch: str, current_git_revision: str, retries: int = 3) -> Set[str]: - try: - async with Connection(DAGGER_CONFIG) as dagger_client: - container = await checked_out_git_container(dagger_client, current_git_branch, current_git_revision) - modified_files = await container.with_exec( - ["diff-tree", "--no-commit-id", "--name-only", current_git_revision, "-r"], use_entrypoint=True - ).stdout() - except SessionError: - if retries > 0: - return await get_modified_files_in_commit_remote(current_git_branch, current_git_revision, retries - 1) - else: - raise - return set(modified_files.split("\n")) - - -def get_modified_files_in_commit_local(current_git_revision: str) -> Set[str]: - airbyte_repo = git.Repo() - modified_files = airbyte_repo.git.diff_tree("--no-commit-id", "--name-only", current_git_revision, "-r").split("\n") - return set(modified_files) - - -async def get_modified_files_in_commit(current_git_branch: str, current_git_revision: str, is_local: bool = True) -> Set[str]: - if is_local: - return get_modified_files_in_commit_local(current_git_revision) - else: - return await get_modified_files_in_commit_remote(current_git_branch, current_git_revision) - - -@functools.cache -def get_git_repo() -> git.Repo: - """Retrieve the git repo.""" - return git.Repo(search_parent_directories=True) - - -@functools.cache -def get_git_repo_path() -> str: - """Retrieve the git repo path.""" - return str(get_git_repo().working_tree_dir) - - -async def get_modified_files( - git_branch: str, - git_revision: str, - diffed_branch: str, - is_local: bool, - ci_context: CIContext, - git_repo_url: str = AIRBYTE_GITHUB_REPO_URL, -) -> Set[str]: - """Get the list of modified files in the current git branch. - If the current branch is master, it will return the list of modified files in the head commit. - The head commit on master should be the merge commit of the latest merged pull request as we squash commits on merge. - Pipelines like "publish on merge" are triggered on each new commit on master. - - If the CI context is a pull request, it will return the list of modified files in the pull request, without using git diff. - If the current branch is not master, it will return the list of modified files in the current branch. - This latest case is the one we encounter when running the pipeline locally, on a local branch, or manually on GHA with a workflow dispatch event. - """ - if ci_context is CIContext.MASTER or (ci_context is CIContext.MANUAL and git_branch == "master"): - return await get_modified_files_in_commit(git_branch, git_revision, is_local) - return await get_modified_files_in_branch(git_repo_url, git_branch, git_revision, diffed_branch, is_local) diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/github.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/github.py deleted file mode 100644 index 086cdce36c44..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/github.py +++ /dev/null @@ -1,237 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""Module grouping functions interacting with the GitHub API.""" - -from __future__ import annotations - -import base64 -import os -from dataclasses import dataclass -from pathlib import Path -from typing import TYPE_CHECKING - -import github as github_sdk -from connector_ops.utils import console # type: ignore - -from pipelines import main_logger -from pipelines.consts import CIContext -from pipelines.models.secrets import Secret - -if TYPE_CHECKING: - from logging import Logger - from typing import Iterable, List, Optional - - -DEFAULT_AIRBYTE_GITHUB_REPO = "airbytehq/airbyte" -AIRBYTE_GITHUB_REPO = os.environ.get("AIRBYTE_GITHUB_REPO", DEFAULT_AIRBYTE_GITHUB_REPO) -AIRBYTE_GITHUBUSERCONTENT_URL_PREFIX = f"https://raw.githubusercontent.com/{AIRBYTE_GITHUB_REPO}" -AIRBYTE_GITHUB_REPO_URL_PREFIX = f"https://github.com/{AIRBYTE_GITHUB_REPO}" -AIRBYTE_GITHUB_REPO_URL = f"{AIRBYTE_GITHUB_REPO_URL_PREFIX}.git" -BASE_BRANCH = "master" - - -def safe_log(logger: Optional[Logger], message: str, level: str = "info") -> None: - """Log a message to a logger if one is available, otherwise print to the console.""" - if logger: - log_method = getattr(logger, level.lower()) - log_method(message) - else: - main_logger.info(message) - - -def update_commit_status_check( - sha: str, - state: str, - target_url: str, - description: str, - context: str, - is_optional: bool = False, - should_send: bool = True, - logger: Optional[Logger] = None, -) -> None: - """Call the GitHub API to create commit status check. - - Args: - sha (str): Hash of the commit for which you want to create a status check. - state (str): The check state (success, failure, pending) - target_url (str): The URL to attach to the commit check for details. - description (str): Description of the check that is run. - context (str): Name of the Check context e.g: source-pokeapi tests - should_send (bool, optional): Whether the commit check should actually be sent to GitHub API. Defaults to True. - logger (Logger, optional): A logger to log info about updates. Defaults to None. - """ - if not should_send: - return - - safe_log(logger, f"Attempting to create {state} status for commit {sha} on Github in {context} context.") - try: - github_client = github_sdk.Github(auth=github_sdk.Auth.Token(os.environ["CI_GITHUB_ACCESS_TOKEN"])) - airbyte_repo = github_client.get_repo(AIRBYTE_GITHUB_REPO) - except Exception as e: - if logger: - logger.error("No commit status check sent, the connection to Github API failed", exc_info=True) - else: - console.print(e) - return - - # If the check is optional, we don't want to fail the build if it fails. - # Instead, we want to mark it as a warning. - # Unfortunately, Github doesn't have a warning state, so we use success instead. - if is_optional and state == "failure": - state = "success" - description = f"[WARNING] optional check failed {context}: {description}" - - context = context if bool(os.environ.get("PRODUCTION", False)) is True else f"[please ignore] {context}" - airbyte_repo.get_commit(sha=sha).create_status( - state=state, - target_url=target_url, - description=description, - context=context, - ) - safe_log(logger, f"Created {state} status for commit {sha} on Github in {context} context with desc: {description}.") - - -def get_pull_request(pull_request_number: int, github_access_token: Secret) -> github_sdk.PullRequest.PullRequest: - """Get a pull request object from its number. - - Args: - pull_request_number (str): The number of the pull request to get. - github_access_token (Secret): The GitHub access token to use to authenticate. - Returns: - PullRequest: The pull request object. - """ - github_client = github_sdk.Github(auth=github_sdk.Auth.Token(github_access_token.value)) - airbyte_repo = github_client.get_repo(AIRBYTE_GITHUB_REPO) - return airbyte_repo.get_pull(pull_request_number) - - -def update_global_commit_status_check_for_tests(click_context: dict, github_state: str, logger: Optional[Logger] = None) -> None: - update_commit_status_check( - click_context["git_revision"], - github_state, - click_context["gha_workflow_run_url"], - click_context["global_status_check_description"], - click_context["global_status_check_context"], - should_send=click_context.get("ci_context") == CIContext.PULL_REQUEST, - logger=logger, - ) - - -@dataclass -class ChangedFile: - path: str - sha: str | None - - -def create_or_update_github_pull_request( - modified_repo_files: Iterable[Path], - github_token: str, - branch_id: str, - commit_message: str, - pr_title: str, - pr_body: str, - repo_name: str = AIRBYTE_GITHUB_REPO, - logger: Optional[Logger] = None, - skip_ci: bool = False, - labels: Optional[Iterable[str]] = None, - force_push: bool = True, - github_auto_merge: bool = False, -) -> github_sdk.PullRequest.PullRequest: - logger = logger or main_logger - g = github_sdk.Github(auth=github_sdk.Auth.Token(github_token)) - repo = g.get_repo(repo_name) - commit_message = commit_message if not skip_ci else f"[skip ci] {commit_message}" - - changed_files: List[ChangedFile] = [] - for modified_file in modified_repo_files: # these are relative to the repo root - if modified_file.exists(): - with open(modified_file, "rb") as file: - logger.info(f"Reading file: {modified_file}") - content = base64.b64encode(file.read()).decode("utf-8") # Encode file content to base64 - blob = repo.create_git_blob(content, "base64") - changed_file = ChangedFile(path=str(modified_file), sha=blob.sha) - changed_files.append(changed_file) - else: - logger.info(f"{modified_file} no longer exists, adding to PR as a deletion") - changed_file = ChangedFile(path=str(modified_file), sha=None) - changed_files.append(changed_file) - existing_ref = None - try: - existing_ref = repo.get_git_ref(f"heads/{branch_id}") - logger.info(f"Git ref {branch_id} already exists") - except github_sdk.GithubException: - pass - - base_sha = repo.get_branch(BASE_BRANCH).commit.sha - if not existing_ref: - repo.create_git_ref(f"refs/heads/{branch_id}", base_sha) - - parent_commit = repo.get_git_commit(base_sha) - parent_tree = repo.get_git_tree(base_sha) - - # Filter and update tree elements - tree_elements: List[github_sdk.InputGitTreeElement] = [] - for changed_file in changed_files: - if changed_file.sha is None: - # make sure it's actually in the current tree - try: - # Attempt to get the file from the specified commit - repo.get_contents(changed_file.path, ref=base_sha) - # logger.info(f"File {changed_file.path} exists in commit {base_sha}") - except github_sdk.UnknownObjectException: - # don't need to add it to the tree - logger.info(f"{changed_file.path} not in parent: {base_sha}") - continue - - # Update or new file addition or needed deletion - tree_elements.append( - github_sdk.InputGitTreeElement( - path=changed_file.path, - mode="100644", - type="blob", - sha=changed_file.sha, - ) - ) - - # Create a new commit pointing to that tree - tree = repo.create_git_tree(tree_elements, base_tree=parent_tree) - commit = repo.create_git_commit(commit_message, tree, [parent_commit]) - repo.get_git_ref(f"heads/{branch_id}").edit(sha=commit.sha, force=force_push) - # Check if there's an existing pull request - found_pr = None - open_pulls = repo.get_pulls(state="open", base=BASE_BRANCH) - for pr in open_pulls: - if pr.head.ref == branch_id: - found_pr = pr - logger.info(f"Pull request already exists: {pr.html_url}") - if found_pr: - pull_request = found_pr - found_pr.edit(title=pr_title, body=pr_body) - else: - pull_request = repo.create_pull( - title=pr_title, - body=pr_body, - base=BASE_BRANCH, - head=branch_id, - ) - logger.info(f"Created pull request: {pull_request.html_url}") - - labels = labels or [] - for label in labels: - pull_request.add_to_labels(label) - logger.info(f"Added label {label} to pull request") - - if github_auto_merge: - logger.info("Enabling (native) GitHub auto-merge for the pull request") - pull_request.enable_automerge("SQUASH") - - return pull_request - - -def is_automerge_pull_request(pull_request: Optional[github_sdk.PullRequest.PullRequest]) -> bool: - labels = [label.name for label in pull_request.get_labels()] if pull_request else [] - if labels and "auto-merge" in labels: - return True - return False diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/pip.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/pip.py deleted file mode 100644 index ea982af53364..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/pip.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -from typing import Optional - -import requests - - -def is_package_published(package_name: Optional[str], version: Optional[str], registry_url: str) -> bool: - """ - Check if a package with a specific version is published on a python registry. - """ - if not package_name or not version: - return False - - url = f"{registry_url}/{package_name}/{version}/json" - - try: - response = requests.get(url) - return response.status_code == 200 - except requests.exceptions.ConnectionError: - return False diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/sentry_utils.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/sentry_utils.py deleted file mode 100644 index ae190629e364..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/sentry_utils.py +++ /dev/null @@ -1,92 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -import importlib.metadata -import os -from typing import TYPE_CHECKING - -import sentry_sdk -from connector_ops.utils import Connector # type: ignore - -if TYPE_CHECKING: - from typing import Any, Callable, Dict, Optional - - from asyncclick import Command, Context - - from pipelines.models.steps import Step - - -def initialize() -> None: - if "SENTRY_DSN" in os.environ: - sentry_sdk.init( - dsn=os.environ.get("SENTRY_DSN"), - environment=os.environ.get("SENTRY_ENVIRONMENT") or "production", - before_send=before_send, # type: ignore - release=f"pipelines@{importlib.metadata.version('pipelines')}", - ) - - -def before_send(event: Dict[str, Any], hint: Dict[str, Any]) -> Optional[Dict[str, Any]]: - # Ignore logged errors that do not contain an exception - if "log_record" in hint and "exc_info" not in hint: - return None - - return event - - -def with_step_context(func: Callable) -> Callable: - def wrapper(self: Step, *args: Any, **kwargs: Any) -> Step: - with sentry_sdk.configure_scope() as scope: - step_name = self.__class__.__name__ - scope.set_tag("pipeline_step", step_name) - scope.set_context( - "Pipeline Step", - { - "name": step_name, - "step_title": self.title, - "max_retries": self.max_retries, - "max_duration": self.max_duration, - "retry_count": self.retry_count, - }, - ) - - if hasattr(self.context, "connector"): - connector: Connector = self.context.connector - scope.set_tag("connector", connector.technical_name) - scope.set_context( - "Connector", - { - "name": connector.name, - "technical_name": connector.technical_name, - "language": connector.language, - "version": connector.version, - "support_level": connector.support_level, - }, - ) - - return func(self, *args, **kwargs) - - return wrapper - - -def with_command_context(func: Callable) -> Callable: - def wrapper(self: Command, ctx: Context, *args: Any, **kwargs: Any) -> Command: - with sentry_sdk.configure_scope() as scope: - scope.set_tag("pipeline_command", self.name) - scope.set_context( - "Pipeline Command", - { - "name": self.name, - "params": self.params, - }, - ) - - scope.set_context("Click Context", ctx.obj) - scope.set_tag("git_branch", ctx.obj.get("git_branch", "unknown")) - scope.set_tag("git_revision", ctx.obj.get("git_revision", "unknown")) - - return func(self, ctx, *args, **kwargs) - - return wrapper diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/slack.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/slack.py deleted file mode 100644 index 38c1818b0b7b..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/slack.py +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -from __future__ import annotations - -import json -import typing - -import requests - -from pipelines import main_logger - -if typing.TYPE_CHECKING: - from typing import List - - -def send_message_to_webhook(message: str, channels: List[str], webhook: str) -> List[requests.Response]: - responses = [] - for channel in channels: - channel = channel[1:] if channel.startswith("#") else channel - payload = {"channel": f"#{channel}", "username": "Connectors CI/CD Bot", "text": message} - response = requests.post(webhook, data={"payload": json.dumps(payload)}) - - # log if the request failed, but don't fail the pipeline - if not response.ok: - main_logger.error(f"Failed to send message to slack webhook: {response.text}") - responses.append(response) - - return responses diff --git a/airbyte-ci/connectors/pipelines/pipelines/helpers/utils.py b/airbyte-ci/connectors/pipelines/pipelines/helpers/utils.py deleted file mode 100644 index c93394e4d215..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/helpers/utils.py +++ /dev/null @@ -1,409 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""This module groups util function used in pipelines.""" - -from __future__ import annotations - -import contextlib -import datetime -import functools -import os -import re -import sys -import unicodedata -import warnings -import xml.sax.saxutils -from io import TextIOWrapper -from pathlib import Path -from typing import TYPE_CHECKING - -import asyncclick as click -import asyncer -from dagger import Client, Config, Container, Directory, ExecError, File, ImageLayerCompression, Platform, Secret -from exceptiongroup import ExceptionGroup -from more_itertools import chunked - -if TYPE_CHECKING: - from typing import Any, Callable, Generator, List, Optional, Set, Tuple - - from pipelines.airbyte_ci.connectors.context import ConnectorContext - -DAGGER_CONFIG = Config(log_output=sys.stderr) -METADATA_FILE_NAME = "metadata.yaml" -MANIFEST_FILE_NAME = "manifest.yaml" -METADATA_ICON_FILE_NAME = "icon.svg" -DIFF_FILTER = "MADRT" # Modified, Added, Deleted, Renamed, Type changed -IGNORED_FILE_EXTENSIONS: list[str] = [".md"] -IGNORED_FILE_NAMES: list[str] = [ - ".coveragerc", - "poe_tasks.toml", -] - - -# This utils will probably be redundant once https://github.com/dagger/dagger/issues/3764 is implemented -async def check_path_in_workdir(container: Container, path: str) -> bool: - """Check if a local path is mounted to the working directory of a container. - - Args: - container (Container): The container on which we want the check the path existence. - path (str): Directory or file path we want to check the existence in the container working directory. - - Returns: - bool: Whether the path exists in the container working directory. - """ - workdir = (await container.with_exec(["pwd"]).stdout()).strip() - mounts = await container.mounts() - if workdir in mounts: - expected_file_path = Path(workdir[1:]) / path - return expected_file_path.is_file() or expected_file_path.is_dir() - else: - return False - - -def secret_host_variable(client: Client, name: str, default: str = "") -> Callable[[Container], Container]: - """Add a host environment variable as a secret in a container. - - Example: - container.with_(secret_host_variable(client, "MY_SECRET")) - - Args: - client (Client): The dagger client. - name (str): The name of the environment variable. The same name will be - used in the container, for the secret name and for the host variable. - default (str): The default value to use if the host variable is not set. Defaults to "". - - Returns: - Callable[[Container], Container]: A function that can be used in a `Container.with_()` method. - """ - - def _secret_host_variable(container: Container) -> Container: - return container.with_secret_variable(name, get_secret_host_variable(client, name, default)) - - return _secret_host_variable - - -def get_secret_host_variable(client: Client, name: str, default: str = "") -> Secret: - """Creates a dagger.Secret from a host environment variable. - - Args: - client (Client): The dagger client. - name (str): The name of the environment variable. The same name will be used for the secret. - default (str): The default value to use if the host variable is not set. Defaults to "". - - Returns: - Secret: A dagger secret. - """ - return client.set_secret(name, os.environ.get(name, default)) - - -# This utils will probably be redundant once https://github.com/dagger/dagger/issues/3764 is implemented -async def get_file_contents(container: Container, path: str) -> Optional[str]: - """Retrieve a container file contents. - - Args: - container (Container): The container hosting the file you want to read. - path (str): Path, in the container, to the file you want to read. - - Returns: - Optional[str]: The file content if the file exists in the container, None otherwise. - """ - dir_name, file_name = os.path.split(path) - if file_name not in set(await container.directory(dir_name).entries()): - return None - return await container.file(path).contents() - - -@contextlib.contextmanager -def catch_exec_error_group() -> Generator: - try: - yield - except ExceptionGroup as eg: - for e in eg.exceptions: - if isinstance(e, ExecError): - raise e - raise - - -async def get_container_output(container: Container) -> Tuple[str, str]: - """Retrieve both stdout and stderr of a container, concurrently. - - Args: - container (Container): The container to execute. - - Returns: - Tuple[str, str]: The stdout and stderr of the container, respectively. - """ - with catch_exec_error_group(): - async with asyncer.create_task_group() as task_group: - soon_stdout = task_group.soonify(container.stdout)() - soon_stderr = task_group.soonify(container.stderr)() - return soon_stdout.value, soon_stderr.value - - -async def get_exec_result(container: Container) -> Tuple[int, str, str]: - """Retrieve the exit_code along with stdout and stderr of a container by handling the ExecError. - - Note: It is preferrable to not worry about the exit code value and just capture - ExecError to handle errors. This is offered as a convenience when the exit code - value is actually needed. - - If the container has a file at /exit_code, the exit code will be read from it. - See hacks.never_fail_exec for more details. - - Args: - container (Container): The container to execute. - - Returns: - Tuple[int, str, str]: The exit_code, stdout and stderr of the container, respectively. - """ - try: - exit_code = 0 - in_file_exit_code = await get_file_contents(container, "/exit_code") - if in_file_exit_code: - exit_code = int(in_file_exit_code) - return exit_code, *(await get_container_output(container)) - except ExecError as e: - return e.exit_code, e.stdout, e.stderr - - -async def with_exit_code(container: Container) -> int: - """Read the container exit code. - - Args: - container (Container): The container from which you want to read the exit code. - - Returns: - int: The exit code. - """ - try: - await container - except ExecError as e: - return e.exit_code - return 0 - - -async def with_stderr(container: Container) -> str: - """Retrieve the stderr of a container even on execution error.""" - try: - return await container.stderr() - except ExecError as e: - return e.stderr - - -async def with_stdout(container: Container) -> str: - """Retrieve the stdout of a container even on execution error.""" - try: - return await container.stdout() - except ExecError as e: - return e.stdout - - -def get_current_epoch_time() -> int: # noqa D103 - return round(datetime.datetime.utcnow().timestamp()) - - -def slugify(value: object, allow_unicode: bool = False) -> str: - """ - Taken from https://github.com/django/django/blob/master/django/utils/text.py. - - Convert to ASCII if 'allow_unicode' is False. Convert spaces or repeated - dashes to single dashes. Remove characters that aren't alphanumerics, - underscores, or hyphens. Convert to lowercase. Also strip leading and - trailing whitespace, dashes, and underscores. - """ - value = str(value) - if allow_unicode: - value = unicodedata.normalize("NFKC", value) - else: - value = unicodedata.normalize("NFKD", value).encode("ascii", "ignore").decode("ascii") - value = re.sub(r"[^\w\s-]", "", value.lower()) - return re.sub(r"[-\s]+", "-", value).strip("-_") - - -def key_value_text_to_dict(text: str) -> dict: - kv = {} - for line in text.split("\n"): - if "=" in line: - try: - k, v = line.split("=") - except ValueError: - continue - kv[k] = v - return kv - - -async def key_value_file_to_dict(file: File) -> dict: - return key_value_text_to_dict(await file.contents()) - - -async def get_dockerfile_labels(dockerfile: File) -> dict: - return {k.replace("LABEL ", ""): v for k, v in (await key_value_file_to_dict(dockerfile)).items() if k.startswith("LABEL")} - - -async def get_version_from_dockerfile(dockerfile: File) -> str: - dockerfile_labels = await get_dockerfile_labels(dockerfile) - try: - return dockerfile_labels["io.airbyte.version"] - except KeyError: - raise Exception("Could not get the version from the Dockerfile labels.") - - -def create_and_open_file(file_path: Path) -> TextIOWrapper: - """Create a file and open it for writing. - - Args: - file_path (Path): The path to the file to create. - - Returns: - File: The file object. - """ - file_path.parent.mkdir(parents=True, exist_ok=True) - file_path.touch() - return file_path.open("w") - - -async def execute_concurrently(steps: List[Callable], concurrency: int = 5) -> List[Any]: - tasks = [] - # Asyncer does not have builtin semaphore, so control concurrency via chunks of steps - # Anyio has semaphores but does not have the soonify method which allow access to results via the value task attribute. - for chunk in chunked(steps, concurrency): - async with asyncer.create_task_group() as task_group: - tasks += [task_group.soonify(step)() for step in chunk] - return [task.value for task in tasks] - - -async def export_container_to_tarball( - context: ConnectorContext, container: Container, platform: Platform, tar_file_name: Optional[str] = None -) -> Tuple[Optional[File], Optional[Path]]: - """Save the container image to the host filesystem as a tar archive. - - Exports a container to a tarball file. - The tarball file is saved to the host filesystem in the directory specified by the host_image_export_dir_path attribute of the context. - - Args: - context (ConnectorContext): The current connector context. - container (Container) : The list of container variants to export. - platform (Platform): The platform of the container to export. - tar_file_name (Optional[str], optional): The name of the tar archive file. Defaults to None. - - Returns: - Tuple[Optional[File], Optional[Path]]: A tuple with the file object holding the tar archive on the host and its path. - """ - tar_file_name = ( - f"{slugify(context.connector.technical_name)}_{context.git_revision}_{platform.replace('/', '_')}.tar" - if tar_file_name is None - else tar_file_name - ) - local_path = Path(f"{context.host_image_export_dir_path}/{tar_file_name}") - export_success = await container.export(str(local_path), forced_compression=ImageLayerCompression.Gzip) - if export_success: - return context.dagger_client.host().file(str(local_path)), local_path - return None, None - - -def format_duration(time_delta: datetime.timedelta) -> str: - total_seconds = time_delta.total_seconds() - if total_seconds < 60: - return "{:.2f}s".format(total_seconds) - minutes = int(total_seconds // 60) - seconds = int(total_seconds % 60) - return "{:02d}mn{:02d}s".format(minutes, seconds) - - -def sh_dash_c(lines: List[str]) -> List[str]: - """Wrap sequence of commands in shell for safe usage of dagger Container's with_exec method.""" - return ["sh", "-c", " && ".join(["set -o xtrace"] + lines)] - - -def transform_strs_to_paths(str_paths: Set[str]) -> List[Path]: - """Transform a list of string paths to an ordered list of Path objects. - - Args: - str_paths (Set[str]): A set of string paths. - - Returns: - List[Path]: A list of Path objects. - """ - return sorted([Path(str_path) for str_path in str_paths]) - - -def fail_if_missing_docker_hub_creds(ctx: click.Context) -> None: - if ctx.obj["docker_hub_username"] is None or ctx.obj["docker_hub_password"] is None: - raise click.UsageError( - "You need to be logged to DockerHub registry to run this command. Please set DOCKER_HUB_USERNAME and DOCKER_HUB_PASSWORD environment variables." - ) - - -def java_log_scrub_pattern(secrets_to_mask: List[str]) -> str: - """Transforms a list of secrets into a LOG_SCRUB_PATTERN env var value for our log4j test configuration.""" - # Build a regex pattern that matches any of the secrets to mask. - regex_pattern = "|".join(map(re.escape, secrets_to_mask)) - # Now, make this string safe to consume by the log4j configuration. - # Its parser is XML-based so the pattern needs to be escaped again, and carefully. - return xml.sax.saxutils.escape( - regex_pattern, - # Annoyingly, the log4j properties file parser is quite brittle when it comes to - # handling log message patterns. In our case the env var is injected like this: - # - # ${env:LOG_SCRUB_PATTERN:-defaultvalue} - # - # We must avoid confusing the parser with curly braces or colons otherwise the - # printed log messages will just consist of `%replace`. - { - "\t": " ", - "'": "'", - '"': """, - "{": "{", - "}": "}", - ":": ":", - }, - ) - - -def dagger_directory_as_zip_file(dagger_client: Client, directory: Directory, directory_name: str) -> File: - """Compress a directory and return a File object representing the zip file. - - Args: - dagger_client (Client): The dagger client. - directory (Path): The directory to compress. - directory_name (str): The name of the directory. - - Returns: - File: The File object representing the zip file. - """ - return ( - dagger_client.container() - .from_("alpine:3.19.1") - .with_exec(sh_dash_c(["apk update", "apk add zip"])) - .with_mounted_directory(f"/{directory_name}", directory) - .with_exec(["zip", "-r", "/zipped.zip", f"/{directory_name}"]) - .file("/zipped.zip") - ) - - -async def raise_if_not_user(container: Container, expected_user: str) -> None: - """Raise an error if the container is not running as the specified user. - - Args: - container (Container): The container to check. - expected_user (str): The expected user. - """ - actual_user = (await container.with_exec(["whoami"]).stdout()).strip() - - assert ( - actual_user == expected_user - ), f"Container is not running as the expected user '{expected_user}', it is running as '{actual_user}'." - - -def deprecated(reason: str) -> Callable: - def decorator(func: Callable) -> Callable: - @functools.wraps(func) - def wrapper(*args: Any, **kwargs: Any) -> Any: - warnings.warn(f"{func.__name__} is deprecated: {reason}", DeprecationWarning, stacklevel=2) - return func(*args, **kwargs) - - return wrapper - - return decorator diff --git a/airbyte-ci/connectors/pipelines/pipelines/models/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/models/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/models/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/models/artifacts.py b/airbyte-ci/connectors/pipelines/pipelines/models/artifacts.py deleted file mode 100644 index 295faf9acbcb..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/models/artifacts.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -from dataclasses import dataclass -from pathlib import Path -from typing import Optional - -import dagger - -from pipelines.consts import GCS_PUBLIC_DOMAIN -from pipelines.dagger.actions import remote_storage -from pipelines.models.secrets import Secret - - -@dataclass(kw_only=True) -class Artifact: - """A dataclass to represent an artifact produced by a pipeline execution.""" - - name: str - content_type: str - content: dagger.File - to_upload: bool = True - local_path: Optional[Path] = None - gcs_url: Optional[str] = None - - async def save_to_local_path(self, path: Path) -> Path: - exported = await self.content.export(str(path)) - if exported: - self.local_path = path - return path - else: - raise Exception(f"Failed to save artifact {self.name} to local path {path}") - - async def upload_to_gcs(self, dagger_client: dagger.Client, bucket: str, key: str, gcs_credentials: Secret) -> str: - gcs_cp_flags = [f'--content-disposition=filename="{self.name}"'] - if self.content_type is not None: - gcs_cp_flags = gcs_cp_flags + [f"--content-type={self.content_type}"] - - report_upload_exit_code, _, _ = await remote_storage.upload_to_gcs( - dagger_client=dagger_client, - file_to_upload=self.content, - key=key, - bucket=bucket, - gcs_credentials=gcs_credentials, - flags=gcs_cp_flags, - ) - if report_upload_exit_code != 0: - raise Exception(f"Failed to upload artifact {self.name} to GCS. Exit code: {report_upload_exit_code}.") - self.gcs_url = f"{GCS_PUBLIC_DOMAIN}/{bucket}/{key}" - return f"{GCS_PUBLIC_DOMAIN}/{bucket}/{key}" diff --git a/airbyte-ci/connectors/pipelines/pipelines/models/ci_requirements.py b/airbyte-ci/connectors/pipelines/pipelines/models/ci_requirements.py deleted file mode 100644 index 8da589d2fffa..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/models/ci_requirements.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - -import json -from dataclasses import dataclass -from importlib import metadata - - -@dataclass -class CIRequirements: - """ - A dataclass to store the CI requirements. - It used to make airbyte-ci client define the CI runners it will run on. - """ - - dagger_version = metadata.version("dagger-io") - - @property - def dagger_engine_image(self) -> str: - return f"registry.dagger.io/engine:v{self.dagger_version}" - - def to_json(self) -> str: - return json.dumps( - { - "dagger_version": self.dagger_version, - "dagger_engine_image": self.dagger_engine_image, - } - ) diff --git a/airbyte-ci/connectors/pipelines/pipelines/models/contexts/__init__.py b/airbyte-ci/connectors/pipelines/pipelines/models/contexts/__init__.py deleted file mode 100644 index c941b3045795..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/models/contexts/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-ci/connectors/pipelines/pipelines/models/contexts/click_pipeline_context.py b/airbyte-ci/connectors/pipelines/pipelines/models/contexts/click_pipeline_context.py deleted file mode 100644 index 471b5840addb..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/models/contexts/click_pipeline_context.py +++ /dev/null @@ -1,122 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import io -import sys -import tempfile -from pathlib import Path -from typing import Any, Callable, Dict, Optional, TextIO, Tuple - -import anyio -import dagger -from asyncclick import Context, get_current_context -from pydantic import BaseModel, Field, PrivateAttr - -from pipelines import main_logger -from pipelines.cli.click_decorators import LazyPassDecorator - -from ..singleton import Singleton - - -class ClickPipelineContext(BaseModel, Singleton): - """ - A replacement class for the Click context object passed to click functions. - - This class is meant to serve as a singleton object that initializes and holds onto a single instance of the - Dagger client, which is used to create containers for running pipelines. - """ - - dockerd_service: Optional[dagger.Container] = Field(default=None) - _dagger_client: Optional[dagger.Client] = PrivateAttr(default=None) - _click_context: Callable[[], Context] = PrivateAttr(default_factory=lambda: get_current_context) - _og_click_context: Context = PrivateAttr(default=None) - - @property - def params(self) -> Dict[str, Any]: - """ - Returns a combination of the click context object and the click context params. - - This means that any arguments or options defined in the parent command will be available to the child command. - """ - ctx = self._click_context() - click_obj = ctx.obj - click_params = ctx.params - command_name = ctx.command.name - - # Error if click_obj and click_params have the same key, and not the same value - intersection = set(click_obj.keys()) & set(click_params.keys()) - if intersection: - for key in intersection: - if click_obj[key] != click_params[key]: - raise ValueError( - f"Your command '{command_name}' has defined options/arguments with the same key as its parent, but with different values: {intersection}" - ) - - return {**click_obj, **click_params} - - class Config: - arbitrary_types_allowed = True - - def __init__(self, **data: dict[str, Any]) -> None: - """ - Initialize the ClickPipelineContext instance. - - This method checks the _initialized flag for the ClickPipelineContext class in the Singleton base class. - If the flag is False, the initialization logic is executed and the flag is set to True. - If the flag is True, the initialization logic is skipped. - - This ensures that the initialization logic is only executed once, even if the ClickPipelineContext instance is retrieved multiple times. - This can be useful if the initialization logic is expensive (e.g., it involves network requests or database queries). - """ - if not Singleton._initialized[ClickPipelineContext]: - super().__init__(**data) - Singleton._initialized[ClickPipelineContext] = True - - """ - Note: Its important to hold onto the original click context object, as it is used to hold onto the Dagger client. - """ - self._og_click_context = self._click_context() - - _dagger_client_lock: anyio.Lock = PrivateAttr(default_factory=anyio.Lock) - - async def get_dagger_client(self) -> dagger.Client: - """ - Get (or initialize) the Dagger Client instance. - """ - if not self._dagger_client: - async with self._dagger_client_lock: - if not self._dagger_client: - connection = dagger.Connection(dagger.Config(log_output=self.get_log_output())) - """ - Sets up the '_dagger_client' attribute, intended for single-threaded use within connectors. - - Caution: - Avoid using this client across multiple thread pools, as it can lead to errors. - Cross-thread pool calls are generally considered an anti-pattern. - """ - self._dagger_client = await self._og_click_context.with_async_resource(connection) - - assert self._dagger_client, "Error initializing Dagger client" - return self._dagger_client - - def get_log_output(self) -> TextIO: - # This `show_dagger_logs` flag is likely going to be removed in the future. - # See https://github.com/airbytehq/airbyte/issues/33487 - if self.params.get("show_dagger_logs", False): - return sys.stdout - else: - log_output, self._click_context().obj["dagger_logs_path"] = self._create_dagger_client_log_file() - return log_output - - def _create_dagger_client_log_file(self) -> Tuple[TextIO, Path]: - """ - Create the dagger client log file. - """ - dagger_logs_file_descriptor, dagger_logs_temp_file_path = tempfile.mkstemp(dir="/tmp", prefix="dagger_client_", suffix=".log") - main_logger.info(f"Dagger client logs stored in {dagger_logs_temp_file_path}") - return io.TextIOWrapper(io.FileIO(dagger_logs_file_descriptor, "w+")), Path(dagger_logs_temp_file_path) - - -# Create @pass_pipeline_context decorator for use in click commands -pass_pipeline_context: LazyPassDecorator = LazyPassDecorator(ClickPipelineContext) diff --git a/airbyte-ci/connectors/pipelines/pipelines/models/contexts/pipeline_context.py b/airbyte-ci/connectors/pipelines/pipelines/models/contexts/pipeline_context.py deleted file mode 100644 index 8b816c31334e..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/models/contexts/pipeline_context.py +++ /dev/null @@ -1,351 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""Module declaring context related classes.""" - -from __future__ import annotations - -import logging -import os -from datetime import datetime -from functools import lru_cache -from glob import glob -from types import TracebackType -from typing import TYPE_CHECKING, Dict - -from asyncer import asyncify -from dagger import Client, Directory, File, GitRepository, Service -from dagger import Secret as DaggerSecret -from github import PullRequest - -from pipelines.airbyte_ci.connectors.reports import ConnectorReport -from pipelines.consts import MANUAL_PIPELINE_STATUS_CHECK_OVERRIDE_PREFIXES, CIContext, ContextState -from pipelines.helpers.execution.run_steps import RunStepOptions -from pipelines.helpers.github import AIRBYTE_GITHUB_REPO_URL, update_commit_status_check -from pipelines.helpers.slack import send_message_to_webhook -from pipelines.helpers.utils import java_log_scrub_pattern -from pipelines.models.reports import Report -from pipelines.models.secrets import Secret, SecretStore - -if TYPE_CHECKING: - from typing import List, Optional - - -class PipelineContext: - """The pipeline context is used to store configuration for a specific pipeline run.""" - - _dagger_client: Optional[Client] - _report: Optional[Report | ConnectorReport] - dockerd_service: Optional[Service] - started_at: Optional[datetime] - stopped_at: Optional[datetime] - - secrets_to_mask: List[str] - - PRODUCTION = bool(os.environ.get("PRODUCTION", False)) # Set this to True to enable production mode (e.g. to send PR comments) - - @lru_cache - def get_default_excluded_files(self) -> list[str]: - return ( - [".git", "airbyte-ci/connectors/pipelines/*"] - + glob("**/build", recursive=True) - + glob("**/.venv", recursive=True) - + glob("**/secrets", recursive=True) - + glob("**/__pycache__", recursive=True) - + glob("**/*.egg-info", recursive=True) - + glob("**/.vscode", recursive=True) - + glob("**/.pytest_cache", recursive=True) - + glob("**/.eggs", recursive=True) - + glob("**/.mypy_cache", recursive=True) - + glob("**/.DS_Store", recursive=True) - + glob("**/airbyte_ci_logs", recursive=True) - + glob("**/.gradle", recursive=True) - ) - - def __init__( - self, - pipeline_name: str, - is_local: bool, - git_branch: str, - git_revision: str, - diffed_branch: str, - git_repo_url: str, - report_output_prefix: str, - gha_workflow_run_url: Optional[str] = None, - dagger_logs_url: Optional[str] = None, - pipeline_start_timestamp: Optional[int] = None, - ci_context: Optional[str] = None, - is_ci_optional: bool = False, - slack_webhook: Optional[str] = None, - pull_request: Optional[PullRequest.PullRequest] = None, - ci_report_bucket: Optional[str] = None, - ci_gcp_credentials: Optional[Secret] = None, - ci_git_user: Optional[str] = None, - ci_github_access_token: Optional[Secret] = None, - run_step_options: RunStepOptions = RunStepOptions(), - enable_report_auto_open: bool = True, - secret_stores: Dict[str, SecretStore] | None = None, - ) -> None: - """Initialize a pipeline context. - - Args: - pipeline_name (str): The pipeline name. - is_local (bool): Whether the context is for a local run or a CI run. - git_branch (str): The current git branch name. - git_revision (str): The current git revision, commit hash. - diffed_branch (str): The branch to diff against. - git_repo_url (str): The git repository URL. - report_output_prefix (str): The prefix to use for the report output. - gha_workflow_run_url (Optional[str], optional): URL to the github action workflow run. Only valid for CI run. Defaults to None. - dagger_logs_url (Optional[str], optional): URL to the dagger logs. Only valid for CI run. Defaults to None. - pipeline_start_timestamp (Optional[int], optional): Timestamp at which the pipeline started. Defaults to None. - ci_context (Optional[str], optional): Pull requests, workflow dispatch or nightly build. Defaults to None. - is_ci_optional (bool, optional): Whether the CI is optional. Defaults to False. - slack_webhook (Optional[str], optional): Slack webhook to send messages to. Defaults to None. - pull_request (PullRequest, optional): The pull request object if the pipeline was triggered by a pull request. Defaults to None. - """ - self.pipeline_name = pipeline_name - self.is_local = is_local - self.git_branch = git_branch - self.git_revision = git_revision - self.diffed_branch = diffed_branch - self.git_repo_url = git_repo_url - self.report_output_prefix = report_output_prefix - self.gha_workflow_run_url = gha_workflow_run_url - self.dagger_logs_url = dagger_logs_url - self.pipeline_start_timestamp = pipeline_start_timestamp - self.created_at = datetime.utcnow() - self.ci_context = ci_context - self.state = ContextState.INITIALIZED - self.is_ci_optional = is_ci_optional - self.slack_webhook = slack_webhook - self.pull_request = pull_request - self.logger = logging.getLogger(self.pipeline_name) - self._dagger_client = None - self._report = None - self.dockerd_service = None - self.ci_gcp_credentials = ci_gcp_credentials - self.ci_report_bucket = ci_report_bucket - self.ci_git_user = ci_git_user - self.ci_github_access_token = ci_github_access_token - self.started_at = None - self.stopped_at = None - self.secrets_to_mask = [] - self.run_step_options = run_step_options - self.enable_report_auto_open = enable_report_auto_open - self.secret_stores = secret_stores if secret_stores else {} - update_commit_status_check(**self.github_commit_status) - - @property - def dagger_client(self) -> Client: - assert self._dagger_client is not None, "The dagger client was not set on this PipelineContext" - return self._dagger_client - - @dagger_client.setter - def dagger_client(self, dagger_client: Client) -> None: - self._dagger_client = dagger_client - - @property - def is_ci(self) -> bool: - return self.is_local is False - - @property - def is_pr(self) -> bool: - return self.ci_context == CIContext.PULL_REQUEST - - @property - def repo(self) -> GitRepository: - return self.dagger_client.git(AIRBYTE_GITHUB_REPO_URL, keep_git_dir=True) - - @property - def report(self) -> Report | ConnectorReport | None: - return self._report - - @report.setter - def report(self, report: Report | ConnectorReport) -> None: - self._report = report - - @property - def java_log_scrub_pattern_secret(self) -> Optional[DaggerSecret]: - if not self.secrets_to_mask: - return None - return self.dagger_client.set_secret("log_scrub_pattern", java_log_scrub_pattern(self.secrets_to_mask)) - - @property - def github_commit_status(self) -> dict: - """Build a dictionary used as kwargs to the update_commit_status_check function.""" - target_url: Optional[str] = self.gha_workflow_run_url - - if ( - self.remote_storage_enabled - and self.state not in [ContextState.RUNNING, ContextState.INITIALIZED] - and isinstance(self.report, ConnectorReport) - ): - target_url = self.report.html_report_url - - return { - "sha": self.git_revision, - "state": self.state.value["github_state"], - "target_url": target_url, - "description": self.state.value["description"], - "context": self.pipeline_name, - "should_send": self._should_send_status_check(), - "logger": self.logger, - "is_optional": self.is_ci_optional, - } - - @property - def should_send_slack_message(self) -> bool: - return self.slack_webhook is not None - - @property - def has_dagger_cloud_token(self) -> bool: - return "_EXPERIMENTAL_DAGGER_CLOUD_TOKEN" in os.environ - - @property - def dagger_cloud_url(self) -> Optional[str]: - """Gets the link to the Dagger Cloud runs page for the current commit.""" - if self.is_local or not self.has_dagger_cloud_token: - return None - - return f"https://alpha.dagger.cloud/changeByPipelines?filter=dagger.io/git.ref:{self.git_revision}" - - @property - def remote_storage_enabled(self) -> bool: - return bool(self.ci_report_bucket) and bool(self.ci_gcp_credentials) - - def _should_send_status_check(self) -> bool: - should_send = self.is_pr or any( - self.pipeline_name.startswith(override) for override in MANUAL_PIPELINE_STATUS_CHECK_OVERRIDE_PREFIXES - ) - self.logger.info(f"Should send status check: {should_send}") - return should_send - - def get_repo_file(self, file_path: str) -> File: - """Get a file from the current repository. - - The file is extracted from the host file system. - - Args: - file_path (str): Path to the file to get. - - Returns: - Path: The selected repo file. - """ - return self.dagger_client.host().file(file_path) - - def get_repo_dir(self, subdir: str = ".", exclude: Optional[List[str]] = None, include: Optional[List[str]] = None) -> Directory: - """Get a directory from the current repository. - - The directory is extracted from the host file system. - A couple of files or directories that could corrupt builds are exclude by default (check DEFAULT_EXCLUDED_FILES). - - Args: - subdir (str, optional): Path to the subdirectory to get. Defaults to "." to get the full repository. - exclude ([List[str], optional): List of files or directories to exclude from the directory. Defaults to None. - include ([List[str], optional): List of files or directories to include in the directory. Defaults to None. - - Returns: - Directory: The selected repo directory. - """ - - if exclude is None: - exclude = self.get_default_excluded_files() - else: - exclude += self.get_default_excluded_files() - exclude = list(set(exclude)) - exclude.sort() # sort to make sure the order is always the same to not burst the cache. Casting exclude to set can change the order - if subdir != ".": - subdir = f"{subdir}/" if not subdir.endswith("/") else subdir - exclude = [f.replace(subdir, "") for f in exclude if subdir in f] - return self.dagger_client.host().directory(subdir, exclude=exclude, include=include) - - def create_slack_message(self) -> str: - raise NotImplementedError() - - def get_slack_channels(self) -> List[str]: - raise NotImplementedError() - - async def __aenter__(self) -> PipelineContext: - """Perform setup operation for the PipelineContext. - - Updates the current commit status on Github. - - Raises: - Exception: An error is raised when the context was not initialized with a Dagger client - Returns: - PipelineContext: A running instance of the PipelineContext. - """ - if self.dagger_client is None: - raise Exception("A Pipeline can't be entered with an undefined dagger_client") - self.state = ContextState.RUNNING - self.started_at = datetime.utcnow() - self.logger.info("Caching the latest CDK version...") - await asyncify(update_commit_status_check)(**self.github_commit_status) - if self.should_send_slack_message: - # Using a type ignore here because the should_send_slack_message property is checking for non nullity of the slack_webhook - await asyncify(send_message_to_webhook)(self.create_slack_message(), self.get_slack_channels(), self.slack_webhook) # type: ignore - return self - - @staticmethod - def determine_final_state(report: Optional[Report], exception_value: Optional[BaseException]) -> ContextState: - """Determine the final state of the context from the report or the exception value. - - Args: - report (Optional[Report]): The pipeline report if any. - exception_value (Optional[BaseException]): The exception value if an exception was raised in the context execution, None otherwise. - Returns: - ContextState: The final state of the context. - """ - if exception_value is not None or report is None: - return ContextState.ERROR - if report is not None and report.considered_failed_steps: - return ContextState.FAILURE - if report is not None and report.success: - return ContextState.SUCCESSFUL - raise Exception( - f"The final state of the context could not be determined for the report and exception value provided. Report: {report}, Exception: {exception_value}" - ) - - async def __aexit__( - self, exception_type: Optional[type[BaseException]], exception_value: Optional[BaseException], traceback: Optional[TracebackType] - ) -> bool: - """Perform teardown operation for the PipelineContext. - - On the context exit the following operations will happen: - - Log the error value if an error was handled. - - Log the test report. - - Update the commit status check on GitHub if running in a CI environment. - - It should gracefully handle all the execution errors that happened and always upload a test report and update commit status check. - - Args: - exception_type (Optional[type[BaseException]]): The exception type if an exception was raised in the context execution, None otherwise. - exception_value (Optional[BaseException]): The exception value if an exception was raised in the context execution, None otherwise. - traceback (Optional[TracebackType]): The traceback if an exception was raised in the context execution, None otherwise. - Returns: - bool: Whether the teardown operation ran successfully. - """ - if exception_value: - self.logger.error("An error was handled by the Pipeline", exc_info=True) - - if self.report is None: - self.logger.error("No test report was provided. This is probably due to an upstream error") - self.report = Report(self, steps_results=[]) - - self.state = self.determine_final_state(self.report, exception_value) - self.stopped_at = datetime.utcnow() - - self.report.print() - - await asyncify(update_commit_status_check)(**self.github_commit_status) - if self.should_send_slack_message: - # Using a type ignore here because the should_send_slack_message property is checking for non nullity of the slack_webhook - await asyncify(send_message_to_webhook)( - self.create_slack_message(), - self.get_slack_channels(), - self.slack_webhook, # type: ignore - ) - # supress the exception if it was handled - return True diff --git a/airbyte-ci/connectors/pipelines/pipelines/models/contexts/python_registry_publish.py b/airbyte-ci/connectors/pipelines/pipelines/models/contexts/python_registry_publish.py deleted file mode 100644 index 9e8a75371b13..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/models/contexts/python_registry_publish.py +++ /dev/null @@ -1,116 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from dataclasses import dataclass -from datetime import datetime -from typing import Optional, Type - -from pipelines.airbyte_ci.connectors.context import PipelineContext -from pipelines.airbyte_ci.connectors.publish.context import PublishConnectorContext -from pipelines.consts import DEFAULT_PYTHON_PACKAGE_REGISTRY_URL -from pipelines.models.secrets import Secret - - -@dataclass -class PythonPackageMetadata: - name: Optional[str] - version: Optional[str] - - -class PythonRegistryPublishContext(PipelineContext): - def __init__( - self, - python_registry_token: Secret, - registry_check_url: str, - package_path: str, - report_output_prefix: str, - is_local: bool, - git_branch: str, - git_revision: str, - diffed_branch: str, - git_repo_url: str, - ci_report_bucket: Optional[str] = None, - registry: str = DEFAULT_PYTHON_PACKAGE_REGISTRY_URL, - gha_workflow_run_url: Optional[str] = None, - dagger_logs_url: Optional[str] = None, - pipeline_start_timestamp: Optional[int] = None, - ci_context: Optional[str] = None, - ci_gcp_credentials: Optional[Secret] = None, - package_name: Optional[str] = None, - version: Optional[str] = None, - ) -> None: - self.python_registry_token = python_registry_token - self.registry = registry - self.registry_check_url = registry_check_url - self.package_path = package_path - self.package_metadata = PythonPackageMetadata(package_name, version) - - pipeline_name = f"Publish PyPI {package_path}" - - super().__init__( - pipeline_name=pipeline_name, - report_output_prefix=report_output_prefix, - ci_report_bucket=ci_report_bucket, - is_local=is_local, - git_branch=git_branch, - git_revision=git_revision, - diffed_branch=diffed_branch, - git_repo_url=git_repo_url, - gha_workflow_run_url=gha_workflow_run_url, - dagger_logs_url=dagger_logs_url, - pipeline_start_timestamp=pipeline_start_timestamp, - ci_context=ci_context, - ci_gcp_credentials=ci_gcp_credentials, - ) - - @classmethod - async def from_publish_connector_context( - cls: Type["PythonRegistryPublishContext"], connector_context: PublishConnectorContext - ) -> Optional["PythonRegistryPublishContext"]: - """ - Create a PythonRegistryPublishContext from a ConnectorContext. - - The metadata of the connector is read from the current workdir to capture changes that are not yet published. - If pypi is not enabled, this will return None. - """ - - current_metadata = connector_context.connector.metadata - connector_context.logger.info(f"Current metadata: {str(current_metadata)}") - if ( - "remoteRegistries" not in current_metadata - or "pypi" not in current_metadata["remoteRegistries"] - or not current_metadata["remoteRegistries"]["pypi"]["enabled"] - ): - return None - - version = current_metadata["dockerImageTag"] - if connector_context.pre_release: - # use current date as pre-release version - # we can't use the git revision because not all python registries allow local version identifiers. Public version identifiers must conform to PEP 440 and only allow digits. - release_candidate_tag = datetime.now().strftime("%Y%m%d%H%M") - version = f"{version}.dev{release_candidate_tag}" - - assert connector_context.python_registry_token is not None, "The connector context must have python_registry_token Secret attribute" - pypi_context = cls( - python_registry_token=connector_context.python_registry_token, - registry=str(connector_context.python_registry_url), - registry_check_url=str(connector_context.python_registry_check_url), - package_path=str(connector_context.connector.code_directory), - package_name=current_metadata["remoteRegistries"]["pypi"]["packageName"], - version=version, - ci_report_bucket=connector_context.ci_report_bucket, - report_output_prefix=connector_context.report_output_prefix, - is_local=connector_context.is_local, - git_branch=connector_context.git_branch, - git_revision=connector_context.git_revision, - diffed_branch=connector_context.diffed_branch, - git_repo_url=connector_context.git_repo_url, - gha_workflow_run_url=connector_context.gha_workflow_run_url, - dagger_logs_url=connector_context.dagger_logs_url, - pipeline_start_timestamp=connector_context.pipeline_start_timestamp, - ci_context=connector_context.ci_context, - ci_gcp_credentials=connector_context.ci_gcp_credentials, - ) - pypi_context.dagger_client = connector_context.dagger_client - return pypi_context diff --git a/airbyte-ci/connectors/pipelines/pipelines/models/reports.py b/airbyte-ci/connectors/pipelines/pipelines/models/reports.py deleted file mode 100644 index 408b5ecded6b..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/models/reports.py +++ /dev/null @@ -1,212 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -"""This module declare base / abstract models to be reused in a pipeline lifecycle.""" - -from __future__ import annotations - -import json -import time -import typing -from dataclasses import dataclass, field -from datetime import datetime, timedelta -from pathlib import Path -from typing import List - -from connector_ops.utils import console # type: ignore -from rich.console import Group -from rich.panel import Panel -from rich.style import Style -from rich.table import Table -from rich.text import Text - -from pipelines.consts import LOCAL_REPORTS_PATH_ROOT -from pipelines.helpers.utils import format_duration, slugify -from pipelines.models.artifacts import Artifact -from pipelines.models.steps import StepResult, StepStatus - -if typing.TYPE_CHECKING: - from rich.tree import RenderableType - - from pipelines.models.contexts.pipeline_context import PipelineContext - - -@dataclass(frozen=True) -class Report: - """A dataclass to build reports to share pipelines executions results with the user.""" - - pipeline_context: PipelineContext - steps_results: List[StepResult] - created_at: datetime = field(default_factory=datetime.utcnow) - name: str = "REPORT" - filename: str = "output" - - @property - def report_output_prefix(self) -> str: - return self.pipeline_context.report_output_prefix - - @property - def report_dir_path(self) -> Path: - return Path(f"{LOCAL_REPORTS_PATH_ROOT}/{self.report_output_prefix}") - - @property - def json_report_file_name(self) -> str: - return self.filename + ".json" - - @property - def json_report_remote_storage_key(self) -> str: - return f"{self.report_output_prefix}/{self.json_report_file_name}" - - @property - def failed_steps(self) -> List[StepResult]: - return [step_result for step_result in self.steps_results if step_result.status is StepStatus.FAILURE] - - @property - def considered_failed_steps(self) -> List[StepResult]: - return [step_result for step_result in self.failed_steps if step_result.consider_in_overall_status] - - @property - def successful_steps(self) -> List[StepResult]: - return [step_result for step_result in self.steps_results if step_result.status is StepStatus.SUCCESS] - - @property - def skipped_steps(self) -> List[StepResult]: - return [step_result for step_result in self.steps_results if step_result.status is StepStatus.SKIPPED] - - @property - def success(self) -> bool: - return len(self.considered_failed_steps) == 0 and (len(self.skipped_steps) > 0 or len(self.successful_steps) > 0) - - @property - def run_duration(self) -> timedelta: - assert self.pipeline_context.started_at is not None, "The pipeline started_at timestamp must be set to save reports." - assert self.pipeline_context.stopped_at is not None, "The pipeline stopped_at timestamp must be set to save reports." - return self.pipeline_context.stopped_at - self.pipeline_context.started_at - - @property - def lead_duration(self) -> timedelta: - assert self.pipeline_context.started_at is not None, "The pipeline started_at timestamp must be set to save reports." - assert self.pipeline_context.stopped_at is not None, "The pipeline stopped_at timestamp must be set to save reports." - return self.pipeline_context.stopped_at - self.pipeline_context.created_at - - async def save(self) -> None: - self.report_dir_path.mkdir(parents=True, exist_ok=True) - await self.save_json_report() - await self.save_step_result_artifacts() - - async def save_json_report(self) -> None: - """Save the report as JSON, upload it to GCS if the pipeline is running in CI""" - - json_report_path = self.report_dir_path / self.json_report_file_name - report_dir = self.pipeline_context.dagger_client.host().directory(str(self.report_dir_path)) - local_json_report_file = report_dir.with_new_file(self.json_report_file_name, self.to_json()).file(self.json_report_file_name) - json_report_artifact = Artifact(name="JSON Report", content_type="application/json", content=local_json_report_file) - await json_report_artifact.save_to_local_path(json_report_path) - absolute_path = json_report_path.absolute() - self.pipeline_context.logger.info(f"Report saved locally at {absolute_path}") - if self.pipeline_context.remote_storage_enabled: - gcs_url = await json_report_artifact.upload_to_gcs( - dagger_client=self.pipeline_context.dagger_client, - bucket=self.pipeline_context.ci_report_bucket, # type: ignore - key=self.json_report_remote_storage_key, - gcs_credentials=self.pipeline_context.ci_gcp_credentials, # type: ignore - ) - self.pipeline_context.logger.info(f"JSON Report uploaded to {gcs_url}") - else: - self.pipeline_context.logger.info("JSON Report not uploaded to GCS because remote storage is disabled.") - - async def save_step_result_artifacts(self) -> None: - local_artifacts_dir = self.report_dir_path / "artifacts" - local_artifacts_dir.mkdir(parents=True, exist_ok=True) - # TODO: concurrent save and upload - for step_result in self.steps_results: - for artifact in step_result.artifacts: - step_artifacts_dir = local_artifacts_dir / slugify(step_result.step.title) - step_artifacts_dir.mkdir(parents=True, exist_ok=True) - await artifact.save_to_local_path(step_artifacts_dir / artifact.name) - if self.pipeline_context.remote_storage_enabled: - upload_time = int(time.time()) - gcs_url = await artifact.upload_to_gcs( - dagger_client=self.pipeline_context.dagger_client, - bucket=self.pipeline_context.ci_report_bucket, # type: ignore - key=f"{self.report_output_prefix}/artifacts/{slugify(step_result.step.title)}/{upload_time}_{artifact.name}", - gcs_credentials=self.pipeline_context.ci_gcp_credentials, # type: ignore - ) - self.pipeline_context.logger.info(f"Artifact {artifact.name} for {step_result.step.title} uploaded to {gcs_url}") - else: - self.pipeline_context.logger.info( - f"Artifact {artifact.name} for {step_result.step.title} not uploaded to GCS because remote storage is disabled." - ) - - def to_json(self) -> str: - """Create a JSON representation of the report. - - Returns: - str: The JSON representation of the report. - """ - assert self.pipeline_context.pipeline_start_timestamp is not None, "The pipeline start timestamp must be set to save reports." - assert self.pipeline_context.started_at is not None, "The pipeline started_at timestamp must be set to save reports." - assert self.pipeline_context.stopped_at is not None, "The pipeline stopped_at timestamp must be set to save reports." - return json.dumps( - { - "pipeline_name": self.pipeline_context.pipeline_name, - "run_timestamp": self.pipeline_context.started_at.isoformat(), - "run_duration": self.run_duration.total_seconds(), - "success": self.success, - "failed_steps": [s.step.__class__.__name__ for s in self.failed_steps], - "successful_steps": [s.step.__class__.__name__ for s in self.successful_steps], - "skipped_steps": [s.step.__class__.__name__ for s in self.skipped_steps], - "gha_workflow_run_url": self.pipeline_context.gha_workflow_run_url, - "pipeline_start_timestamp": self.pipeline_context.pipeline_start_timestamp, - "pipeline_end_timestamp": round(self.pipeline_context.stopped_at.timestamp()), - "pipeline_duration": round(self.pipeline_context.stopped_at.timestamp()) - self.pipeline_context.pipeline_start_timestamp, - "git_branch": self.pipeline_context.git_branch, - "git_revision": self.pipeline_context.git_revision, - "ci_context": self.pipeline_context.ci_context, - "pull_request_url": self.pipeline_context.pull_request.html_url if self.pipeline_context.pull_request else None, - "dagger_cloud_url": self.pipeline_context.dagger_cloud_url, - } - ) - - def print(self) -> None: - """Print the test report to the console in a nice way.""" - pipeline_name = self.pipeline_context.pipeline_name - main_panel_title = Text(f"{pipeline_name.upper()} - {self.name}") - main_panel_title.stylize(Style(color="blue", bold=True)) - duration_subtitle = Text(f"⏲️ Total pipeline duration for {pipeline_name}: {format_duration(self.run_duration)}") - step_results_table = Table(title="Steps results") - step_results_table.add_column("Step") - step_results_table.add_column("Result") - step_results_table.add_column("Finished after") - - for step_result in self.steps_results: - step = Text(step_result.step.title) - step.stylize(step_result.status.get_rich_style()) - result = Text(step_result.status.value) - result.stylize(step_result.status.get_rich_style()) - - if step_result.status is StepStatus.SKIPPED: - step_results_table.add_row(step, result, "N/A") - else: - assert step_result.step.started_at is not None, "The step started_at timestamp must be set to print reports." - run_time = format_duration((step_result.created_at - step_result.step.started_at)) - step_results_table.add_row(step, result, run_time) - - to_render: List[RenderableType] = [step_results_table] - if self.failed_steps: - sub_panels = [] - for failed_step in self.failed_steps: - errors = Text(failed_step.stderr) if failed_step.stderr else Text("") - panel_title = Text(f"{pipeline_name} {failed_step.step.title.lower()} failures") - panel_title.stylize(Style(color="red", bold=True)) - sub_panel = Panel(errors, title=panel_title) - sub_panels.append(sub_panel) - failures_group = Group(*sub_panels) - to_render.append(failures_group) - - if self.pipeline_context.dagger_cloud_url: - self.pipeline_context.logger.info(f"🔗 View runs for commit in Dagger Cloud: {self.pipeline_context.dagger_cloud_url}") - - main_panel = Panel(Group(*to_render), title=main_panel_title, subtitle=duration_subtitle) - console.print(main_panel) diff --git a/airbyte-ci/connectors/pipelines/pipelines/models/secrets.py b/airbyte-ci/connectors/pipelines/pipelines/models/secrets.py deleted file mode 100644 index a8a0aa7eb120..000000000000 --- a/airbyte-ci/connectors/pipelines/pipelines/models/secrets.py +++ /dev/null @@ -1,140 +0,0 @@ -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. - -from __future__ import annotations - -import hashlib -import json -import os -from abc import ABC, abstractmethod -from dataclasses import dataclass -from pathlib import Path -from typing import Dict, List - -from dagger import Client as DaggerClient -from dagger import Secret as DaggerSecret -from google.cloud import secretmanager_v1 # type: ignore -from google.oauth2 import service_account # type: ignore - - -class SecretNotFoundError(Exception): - pass - - -class SecretString(str): - """The use of this string subtype will prevent accidental prints of secret value to the console.""" - - @property - def _masked_value(self) -> str: - return "