airbyte-agent-zendesk-support 0.18.36__py3-none-any.whl → 0.18.44__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- airbyte_agent_zendesk_support/__init__.py +111 -18
- airbyte_agent_zendesk_support/_vendored/connector_sdk/auth_strategies.py +2 -5
- airbyte_agent_zendesk_support/_vendored/connector_sdk/auth_template.py +1 -1
- airbyte_agent_zendesk_support/_vendored/connector_sdk/cloud_utils/client.py +26 -26
- airbyte_agent_zendesk_support/_vendored/connector_sdk/connector_model_loader.py +1 -2
- airbyte_agent_zendesk_support/_vendored/connector_sdk/executor/hosted_executor.py +10 -11
- airbyte_agent_zendesk_support/_vendored/connector_sdk/executor/local_executor.py +72 -13
- airbyte_agent_zendesk_support/_vendored/connector_sdk/extensions.py +1 -2
- airbyte_agent_zendesk_support/_vendored/connector_sdk/http/response.py +2 -0
- airbyte_agent_zendesk_support/_vendored/connector_sdk/logging/logger.py +9 -9
- airbyte_agent_zendesk_support/_vendored/connector_sdk/logging/types.py +10 -10
- airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/config.py +2 -2
- airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/models.py +6 -6
- airbyte_agent_zendesk_support/_vendored/connector_sdk/observability/session.py +7 -5
- airbyte_agent_zendesk_support/_vendored/connector_sdk/performance/metrics.py +3 -3
- airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/base.py +21 -18
- airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/components.py +58 -58
- airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/connector.py +22 -33
- airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/extensions.py +103 -10
- airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/operations.py +31 -31
- airbyte_agent_zendesk_support/_vendored/connector_sdk/schema/security.py +36 -36
- airbyte_agent_zendesk_support/_vendored/connector_sdk/secrets.py +2 -2
- airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/events.py +7 -7
- airbyte_agent_zendesk_support/_vendored/connector_sdk/telemetry/tracker.py +6 -5
- airbyte_agent_zendesk_support/_vendored/connector_sdk/types.py +2 -2
- airbyte_agent_zendesk_support/connector.py +154 -158
- airbyte_agent_zendesk_support/connector_model.py +3 -3
- airbyte_agent_zendesk_support/models.py +21 -69
- {airbyte_agent_zendesk_support-0.18.36.dist-info → airbyte_agent_zendesk_support-0.18.44.dist-info}/METADATA +12 -9
- {airbyte_agent_zendesk_support-0.18.36.dist-info → airbyte_agent_zendesk_support-0.18.44.dist-info}/RECORD +31 -31
- {airbyte_agent_zendesk_support-0.18.36.dist-info → airbyte_agent_zendesk_support-0.18.44.dist-info}/WHEEL +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import base64
|
|
4
4
|
from datetime import UTC, datetime
|
|
5
|
-
from typing import Any, Dict, List
|
|
5
|
+
from typing import Any, Dict, List
|
|
6
6
|
|
|
7
7
|
from pydantic import BaseModel, ConfigDict, Field, field_serializer, field_validator
|
|
8
8
|
|
|
@@ -27,12 +27,12 @@ class RequestLog(BaseModel):
|
|
|
27
27
|
url: str
|
|
28
28
|
path: str
|
|
29
29
|
headers: Dict[str, str] = Field(default_factory=dict)
|
|
30
|
-
params:
|
|
31
|
-
body:
|
|
32
|
-
response_status:
|
|
33
|
-
response_body:
|
|
34
|
-
timing_ms:
|
|
35
|
-
error:
|
|
30
|
+
params: Dict[str, Any] | None = None
|
|
31
|
+
body: Any | None = None
|
|
32
|
+
response_status: int | None = None
|
|
33
|
+
response_body: Any | None = None
|
|
34
|
+
timing_ms: float | None = None
|
|
35
|
+
error: str | None = None
|
|
36
36
|
|
|
37
37
|
@field_serializer("timestamp")
|
|
38
38
|
def serialize_datetime(self, value: datetime) -> str:
|
|
@@ -50,9 +50,9 @@ class LogSession(BaseModel):
|
|
|
50
50
|
|
|
51
51
|
session_id: str
|
|
52
52
|
started_at: datetime = Field(default_factory=_utc_now)
|
|
53
|
-
connector_name:
|
|
53
|
+
connector_name: str | None = None
|
|
54
54
|
logs: List[RequestLog] = Field(default_factory=list)
|
|
55
|
-
max_logs:
|
|
55
|
+
max_logs: int | None = Field(
|
|
56
56
|
default=10000,
|
|
57
57
|
description="Maximum number of logs to keep in memory. "
|
|
58
58
|
"When limit is reached, oldest logs should be flushed before removal. "
|
|
@@ -60,7 +60,7 @@ class LogSession(BaseModel):
|
|
|
60
60
|
)
|
|
61
61
|
chunk_logs: List[bytes] = Field(
|
|
62
62
|
default_factory=list,
|
|
63
|
-
description="Captured chunks from streaming responses.
|
|
63
|
+
description="Captured chunks from streaming responses. Each chunk is logged when log_chunk_fetch() is called.",
|
|
64
64
|
)
|
|
65
65
|
|
|
66
66
|
@field_validator("chunk_logs", mode="before")
|
|
@@ -6,7 +6,7 @@ import tempfile
|
|
|
6
6
|
import uuid
|
|
7
7
|
from dataclasses import dataclass, field
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import Any
|
|
9
|
+
from typing import Any
|
|
10
10
|
|
|
11
11
|
import yaml
|
|
12
12
|
|
|
@@ -53,7 +53,7 @@ def _delete_legacy_files() -> None:
|
|
|
53
53
|
logger.debug(f"Could not delete legacy file {legacy_path}: {e}")
|
|
54
54
|
|
|
55
55
|
|
|
56
|
-
def _migrate_legacy_config() ->
|
|
56
|
+
def _migrate_legacy_config() -> SDKConfig | None:
|
|
57
57
|
"""
|
|
58
58
|
Migrate from legacy file-based config to new YAML format.
|
|
59
59
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from datetime import datetime
|
|
5
|
-
from typing import Any, Dict
|
|
5
|
+
from typing import Any, Dict
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
@dataclass
|
|
@@ -12,8 +12,8 @@ class OperationMetadata:
|
|
|
12
12
|
entity: str
|
|
13
13
|
action: str
|
|
14
14
|
timestamp: datetime
|
|
15
|
-
timing_ms:
|
|
16
|
-
status_code:
|
|
17
|
-
error_type:
|
|
18
|
-
error_message:
|
|
19
|
-
params:
|
|
15
|
+
timing_ms: float | None = None
|
|
16
|
+
status_code: int | None = None
|
|
17
|
+
error_type: str | None = None
|
|
18
|
+
error_message: str | None = None
|
|
19
|
+
params: Dict[str, Any] | None = None
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
import logging
|
|
4
4
|
import uuid
|
|
5
5
|
from datetime import UTC, datetime
|
|
6
|
-
from typing import Any, Dict
|
|
6
|
+
from typing import Any, Dict
|
|
7
7
|
|
|
8
8
|
from .config import SDKConfig, load_config
|
|
9
9
|
|
|
10
10
|
logger = logging.getLogger(__name__)
|
|
11
11
|
|
|
12
12
|
# Cache the config at module level to avoid repeated reads
|
|
13
|
-
_cached_config:
|
|
13
|
+
_cached_config: SDKConfig | None = None
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def _get_config() -> SDKConfig:
|
|
@@ -39,7 +39,7 @@ def get_persistent_user_id() -> str:
|
|
|
39
39
|
return _get_config().user_id
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
def get_public_ip() ->
|
|
42
|
+
def get_public_ip() -> str | None:
|
|
43
43
|
"""
|
|
44
44
|
Fetch the public IP address of the user.
|
|
45
45
|
|
|
@@ -47,6 +47,8 @@ def get_public_ip() -> Optional[str]:
|
|
|
47
47
|
Uses httpx for a robust HTTP request to a public IP service.
|
|
48
48
|
"""
|
|
49
49
|
try:
|
|
50
|
+
# NOTE: Import here intentionally - this is a non-critical network call
|
|
51
|
+
# that may fail. Importing at module level would make httpx a hard dependency.
|
|
50
52
|
import httpx
|
|
51
53
|
|
|
52
54
|
# Use a short timeout to avoid blocking
|
|
@@ -77,9 +79,9 @@ class ObservabilitySession:
|
|
|
77
79
|
def __init__(
|
|
78
80
|
self,
|
|
79
81
|
connector_name: str,
|
|
80
|
-
connector_version:
|
|
82
|
+
connector_version: str | None = None,
|
|
81
83
|
execution_context: str = "direct",
|
|
82
|
-
session_id:
|
|
84
|
+
session_id: str | None = None,
|
|
83
85
|
):
|
|
84
86
|
self.session_id = session_id or str(uuid.uuid4())
|
|
85
87
|
self.user_id = get_persistent_user_id()
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import time
|
|
4
4
|
from contextlib import asynccontextmanager
|
|
5
|
-
from typing import Dict
|
|
5
|
+
from typing import Dict
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class PerformanceMonitor:
|
|
@@ -33,7 +33,7 @@ class PerformanceMonitor:
|
|
|
33
33
|
metrics["min"] = min(metrics["min"], duration)
|
|
34
34
|
metrics["max"] = max(metrics["max"], duration)
|
|
35
35
|
|
|
36
|
-
def get_stats(self, metric_name: str) ->
|
|
36
|
+
def get_stats(self, metric_name: str) -> Dict[str, float] | None:
|
|
37
37
|
"""Get statistics for a metric.
|
|
38
38
|
|
|
39
39
|
Args:
|
|
@@ -62,7 +62,7 @@ class PerformanceMonitor:
|
|
|
62
62
|
"""
|
|
63
63
|
return {name: self.get_stats(name) for name in self._metrics.keys()}
|
|
64
64
|
|
|
65
|
-
def reset(self, metric_name:
|
|
65
|
+
def reset(self, metric_name: str | None = None):
|
|
66
66
|
"""Reset metrics.
|
|
67
67
|
|
|
68
68
|
Args:
|
|
@@ -7,13 +7,13 @@ References:
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
from enum import StrEnum
|
|
10
|
-
from typing import Dict
|
|
10
|
+
from typing import Dict
|
|
11
11
|
from uuid import UUID
|
|
12
12
|
|
|
13
13
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
14
14
|
from pydantic_core import Url
|
|
15
15
|
|
|
16
|
-
from .extensions import RetryConfig
|
|
16
|
+
from .extensions import CacheConfig, RetryConfig
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class ExampleQuestions(BaseModel):
|
|
@@ -45,9 +45,9 @@ class Contact(BaseModel):
|
|
|
45
45
|
|
|
46
46
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
47
47
|
|
|
48
|
-
name:
|
|
49
|
-
url:
|
|
50
|
-
email:
|
|
48
|
+
name: str | None = None
|
|
49
|
+
url: str | None = None
|
|
50
|
+
email: str | None = None
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
class License(BaseModel):
|
|
@@ -60,7 +60,7 @@ class License(BaseModel):
|
|
|
60
60
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
61
61
|
|
|
62
62
|
name: str
|
|
63
|
-
url:
|
|
63
|
+
url: str | None = None
|
|
64
64
|
|
|
65
65
|
|
|
66
66
|
class DocUrlType(StrEnum):
|
|
@@ -85,7 +85,7 @@ class DocUrl(BaseModel):
|
|
|
85
85
|
|
|
86
86
|
url: str
|
|
87
87
|
type: DocUrlType
|
|
88
|
-
title:
|
|
88
|
+
title: str | None = None
|
|
89
89
|
|
|
90
90
|
@field_validator("url")
|
|
91
91
|
def validate_url(cls, v):
|
|
@@ -105,23 +105,25 @@ class Info(BaseModel):
|
|
|
105
105
|
- x-airbyte-external-documentation-urls: List of external documentation URLs (Airbyte extension)
|
|
106
106
|
- x-airbyte-retry-config: Retry configuration for transient errors (Airbyte extension)
|
|
107
107
|
- x-airbyte-example-questions: Example questions for AI connector README (Airbyte extension)
|
|
108
|
+
- x-airbyte-cache: Cache configuration for field mapping between API and cache schemas (Airbyte extension)
|
|
108
109
|
"""
|
|
109
110
|
|
|
110
111
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
111
112
|
|
|
112
113
|
title: str
|
|
113
114
|
version: str
|
|
114
|
-
description:
|
|
115
|
-
terms_of_service:
|
|
116
|
-
contact:
|
|
117
|
-
license:
|
|
115
|
+
description: str | None = None
|
|
116
|
+
terms_of_service: str | None = Field(None, alias="termsOfService")
|
|
117
|
+
contact: Contact | None = None
|
|
118
|
+
license: License | None = None
|
|
118
119
|
|
|
119
120
|
# Airbyte extension
|
|
120
|
-
x_airbyte_connector_name:
|
|
121
|
-
x_airbyte_connector_id:
|
|
121
|
+
x_airbyte_connector_name: str | None = Field(None, alias="x-airbyte-connector-name")
|
|
122
|
+
x_airbyte_connector_id: UUID | None = Field(None, alias="x-airbyte-connector-id")
|
|
122
123
|
x_airbyte_external_documentation_urls: list[DocUrl] = Field(..., alias="x-airbyte-external-documentation-urls")
|
|
123
|
-
x_airbyte_retry_config:
|
|
124
|
-
x_airbyte_example_questions:
|
|
124
|
+
x_airbyte_retry_config: RetryConfig | None = Field(None, alias="x-airbyte-retry-config")
|
|
125
|
+
x_airbyte_example_questions: ExampleQuestions | None = Field(None, alias="x-airbyte-example-questions")
|
|
126
|
+
x_airbyte_cache: CacheConfig | None = Field(None, alias="x-airbyte-cache")
|
|
125
127
|
|
|
126
128
|
|
|
127
129
|
class ServerVariable(BaseModel):
|
|
@@ -133,9 +135,9 @@ class ServerVariable(BaseModel):
|
|
|
133
135
|
|
|
134
136
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
135
137
|
|
|
136
|
-
enum:
|
|
138
|
+
enum: list[str] | None = None
|
|
137
139
|
default: str
|
|
138
|
-
description:
|
|
140
|
+
description: str | None = None
|
|
139
141
|
|
|
140
142
|
|
|
141
143
|
class Server(BaseModel):
|
|
@@ -148,8 +150,9 @@ class Server(BaseModel):
|
|
|
148
150
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
149
151
|
|
|
150
152
|
url: str
|
|
151
|
-
description:
|
|
153
|
+
description: str | None = None
|
|
152
154
|
variables: Dict[str, ServerVariable] = Field(default_factory=dict)
|
|
155
|
+
x_airbyte_replication_user_config_mapping: Dict[str, str] | None = Field(default=None, alias="x-airbyte-replication-user-config-mapping")
|
|
153
156
|
|
|
154
157
|
@field_validator("url")
|
|
155
158
|
@classmethod
|
|
@@ -7,7 +7,7 @@ References:
|
|
|
7
7
|
- https://spec.openapis.org/oas/v3.1.0#parameter-object
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
from typing import Any, Dict, List, Literal,
|
|
10
|
+
from typing import Any, Dict, List, Literal, Union
|
|
11
11
|
|
|
12
12
|
from pydantic import BaseModel, ConfigDict, Field
|
|
13
13
|
|
|
@@ -30,44 +30,44 @@ class Schema(BaseModel):
|
|
|
30
30
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
31
31
|
|
|
32
32
|
# Core JSON Schema fields
|
|
33
|
-
type:
|
|
34
|
-
format:
|
|
35
|
-
title:
|
|
36
|
-
description:
|
|
37
|
-
default:
|
|
38
|
-
example:
|
|
33
|
+
type: str | None = None
|
|
34
|
+
format: str | None = None
|
|
35
|
+
title: str | None = None
|
|
36
|
+
description: str | None = None
|
|
37
|
+
default: Any | None = None
|
|
38
|
+
example: Any | None = None
|
|
39
39
|
|
|
40
40
|
# Object properties
|
|
41
41
|
properties: Dict[str, Any] = Field(default_factory=dict) # May contain $ref
|
|
42
42
|
required: List[str] = Field(default_factory=list)
|
|
43
|
-
additional_properties:
|
|
43
|
+
additional_properties: Any | None = Field(None, alias="additionalProperties")
|
|
44
44
|
|
|
45
45
|
# Array properties
|
|
46
|
-
items:
|
|
46
|
+
items: Any | None = None # May be Schema or $ref
|
|
47
47
|
|
|
48
48
|
# Validation
|
|
49
|
-
enum:
|
|
50
|
-
min_length:
|
|
51
|
-
max_length:
|
|
52
|
-
minimum:
|
|
53
|
-
maximum:
|
|
54
|
-
pattern:
|
|
49
|
+
enum: List[Any] | None = None
|
|
50
|
+
min_length: int | None = Field(None, alias="minLength")
|
|
51
|
+
max_length: int | None = Field(None, alias="maxLength")
|
|
52
|
+
minimum: float | None = None
|
|
53
|
+
maximum: float | None = None
|
|
54
|
+
pattern: str | None = None
|
|
55
55
|
|
|
56
56
|
# Composition
|
|
57
|
-
all_of:
|
|
58
|
-
any_of:
|
|
59
|
-
one_of:
|
|
60
|
-
not_:
|
|
57
|
+
all_of: List[Any] | None = Field(None, alias="allOf")
|
|
58
|
+
any_of: List[Any] | None = Field(None, alias="anyOf")
|
|
59
|
+
one_of: List[Any] | None = Field(None, alias="oneOf")
|
|
60
|
+
not_: Any | None = Field(None, alias="not")
|
|
61
61
|
|
|
62
62
|
# Metadata
|
|
63
|
-
nullable:
|
|
64
|
-
read_only:
|
|
65
|
-
write_only:
|
|
66
|
-
deprecated:
|
|
63
|
+
nullable: bool | None = Field(None, deprecated="Use type union with null instead (OpenAPI 3.1)")
|
|
64
|
+
read_only: bool | None = Field(None, alias="readOnly")
|
|
65
|
+
write_only: bool | None = Field(None, alias="writeOnly")
|
|
66
|
+
deprecated: bool | None = None
|
|
67
67
|
|
|
68
68
|
# Airbyte extensions
|
|
69
|
-
x_airbyte_entity_name:
|
|
70
|
-
x_airbyte_stream_name:
|
|
69
|
+
x_airbyte_entity_name: str | None = Field(None, alias="x-airbyte-entity-name")
|
|
70
|
+
x_airbyte_stream_name: str | None = Field(None, alias="x-airbyte-stream-name")
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
class Parameter(BaseModel):
|
|
@@ -81,19 +81,19 @@ class Parameter(BaseModel):
|
|
|
81
81
|
|
|
82
82
|
name: str
|
|
83
83
|
in_: Literal["query", "header", "path", "cookie"] = Field(alias="in")
|
|
84
|
-
description:
|
|
85
|
-
required:
|
|
86
|
-
deprecated:
|
|
87
|
-
allow_empty_value:
|
|
84
|
+
description: str | None = None
|
|
85
|
+
required: bool | None = None
|
|
86
|
+
deprecated: bool | None = None
|
|
87
|
+
allow_empty_value: bool | None = Field(None, alias="allowEmptyValue")
|
|
88
88
|
|
|
89
89
|
# Schema can be inline or reference
|
|
90
|
-
schema_:
|
|
90
|
+
schema_: Dict[str, Any] | None = Field(None, alias="schema")
|
|
91
91
|
|
|
92
92
|
# Style and examples
|
|
93
|
-
style:
|
|
94
|
-
explode:
|
|
95
|
-
example:
|
|
96
|
-
examples:
|
|
93
|
+
style: str | None = None
|
|
94
|
+
explode: bool | None = None
|
|
95
|
+
example: Any | None = None
|
|
96
|
+
examples: Dict[str, Any] | None = None
|
|
97
97
|
|
|
98
98
|
|
|
99
99
|
class MediaType(BaseModel):
|
|
@@ -105,10 +105,10 @@ class MediaType(BaseModel):
|
|
|
105
105
|
|
|
106
106
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
107
107
|
|
|
108
|
-
schema_:
|
|
109
|
-
example:
|
|
110
|
-
examples:
|
|
111
|
-
encoding:
|
|
108
|
+
schema_: Dict[str, Any] | None = Field(None, alias="schema")
|
|
109
|
+
example: Any | None = None
|
|
110
|
+
examples: Dict[str, Any] | None = None
|
|
111
|
+
encoding: Dict[str, Any] | None = None
|
|
112
112
|
|
|
113
113
|
|
|
114
114
|
class GraphQLBodyConfig(BaseModel):
|
|
@@ -125,12 +125,12 @@ class GraphQLBodyConfig(BaseModel):
|
|
|
125
125
|
...,
|
|
126
126
|
description="GraphQL query or mutation string with optional template placeholders (e.g., {{ variable }})",
|
|
127
127
|
)
|
|
128
|
-
variables:
|
|
128
|
+
variables: Dict[str, Any] | None = Field(
|
|
129
129
|
None,
|
|
130
130
|
description="Variables to substitute in the GraphQL query using template syntax (e.g., {{ param_name }})",
|
|
131
131
|
)
|
|
132
|
-
operationName:
|
|
133
|
-
default_fields:
|
|
132
|
+
operationName: str | None = Field(None, description="Operation name for queries with multiple operations")
|
|
133
|
+
default_fields: Union[str, List[str]] | None = Field(
|
|
134
134
|
None,
|
|
135
135
|
description="Default fields to select if not provided in request parameters. Can be a string or array of field names.",
|
|
136
136
|
)
|
|
@@ -156,7 +156,7 @@ class PathOverrideConfig(BaseModel):
|
|
|
156
156
|
|
|
157
157
|
path: str = Field(
|
|
158
158
|
...,
|
|
159
|
-
description=("Actual HTTP path to use for requests (e.g., '/graphql').
|
|
159
|
+
description=("Actual HTTP path to use for requests (e.g., '/graphql'). Must start with '/'"),
|
|
160
160
|
)
|
|
161
161
|
|
|
162
162
|
|
|
@@ -173,17 +173,17 @@ class RequestBody(BaseModel):
|
|
|
173
173
|
|
|
174
174
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
175
175
|
|
|
176
|
-
description:
|
|
176
|
+
description: str | None = None
|
|
177
177
|
content: Dict[str, MediaType] = Field(default_factory=dict)
|
|
178
|
-
required:
|
|
178
|
+
required: bool | None = None
|
|
179
179
|
|
|
180
180
|
# Airbyte extensions for GraphQL support
|
|
181
181
|
# See connector_sdk.extensions for AIRBYTE_BODY_TYPE constant
|
|
182
|
-
x_airbyte_body_type:
|
|
182
|
+
x_airbyte_body_type: BodyTypeConfig | None = Field(
|
|
183
183
|
None,
|
|
184
184
|
alias="x-airbyte-body-type", # AIRBYTE_BODY_TYPE
|
|
185
185
|
description=(
|
|
186
|
-
"Body type and configuration. Contains 'type' field (e.g., 'graphql')
|
|
186
|
+
"Body type and configuration. Contains 'type' field (e.g., 'graphql') and type-specific configuration (query, variables, etc.)."
|
|
187
187
|
),
|
|
188
188
|
)
|
|
189
189
|
|
|
@@ -197,11 +197,11 @@ class Header(BaseModel):
|
|
|
197
197
|
|
|
198
198
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
199
199
|
|
|
200
|
-
description:
|
|
201
|
-
required:
|
|
202
|
-
deprecated:
|
|
203
|
-
schema_:
|
|
204
|
-
example:
|
|
200
|
+
description: str | None = None
|
|
201
|
+
required: bool | None = None
|
|
202
|
+
deprecated: bool | None = None
|
|
203
|
+
schema_: Dict[str, Any] | None = Field(None, alias="schema")
|
|
204
|
+
example: Any | None = None
|
|
205
205
|
|
|
206
206
|
|
|
207
207
|
class Response(BaseModel):
|
|
@@ -214,9 +214,9 @@ class Response(BaseModel):
|
|
|
214
214
|
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
|
215
215
|
|
|
216
216
|
description: str
|
|
217
|
-
headers:
|
|
218
|
-
content:
|
|
219
|
-
links:
|
|
217
|
+
headers: Dict[str, Header] | None = None
|
|
218
|
+
content: Dict[str, MediaType] | None = None
|
|
219
|
+
links: Dict[str, Any] | None = None
|
|
220
220
|
|
|
221
221
|
|
|
222
222
|
class Components(BaseModel):
|
|
@@ -231,9 +231,9 @@ class Components(BaseModel):
|
|
|
231
231
|
schemas: Dict[str, Schema] = Field(default_factory=dict)
|
|
232
232
|
responses: Dict[str, Response] = Field(default_factory=dict)
|
|
233
233
|
parameters: Dict[str, Parameter] = Field(default_factory=dict)
|
|
234
|
-
examples:
|
|
234
|
+
examples: Dict[str, Any] | None = None
|
|
235
235
|
request_bodies: Dict[str, RequestBody] = Field(default_factory=dict, alias="requestBodies")
|
|
236
|
-
headers:
|
|
236
|
+
headers: Dict[str, Header] | None = None
|
|
237
237
|
security_schemes: Dict[str, SecurityScheme] = Field(default_factory=dict, alias="securitySchemes")
|
|
238
|
-
links:
|
|
239
|
-
callbacks:
|
|
238
|
+
links: Dict[str, Any] | None = None
|
|
239
|
+
callbacks: Dict[str, Any] | None = None
|
|
@@ -7,6 +7,7 @@ References:
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
+
from collections.abc import Iterator
|
|
10
11
|
from typing import Any
|
|
11
12
|
|
|
12
13
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
@@ -15,7 +16,7 @@ from ..constants import OPENAPI_VERSION_PREFIX
|
|
|
15
16
|
|
|
16
17
|
from .base import Info, Server
|
|
17
18
|
from .components import Components
|
|
18
|
-
from .operations import PathItem
|
|
19
|
+
from .operations import Operation, PathItem
|
|
19
20
|
from .security import SecurityRequirement
|
|
20
21
|
|
|
21
22
|
|
|
@@ -33,6 +34,10 @@ class Tag(BaseModel):
|
|
|
33
34
|
external_docs: dict[str, Any] | None = Field(None, alias="externalDocs")
|
|
34
35
|
|
|
35
36
|
|
|
37
|
+
# HTTP methods supported by OpenAPI operations
|
|
38
|
+
HTTP_METHODS = frozenset({"get", "post", "put", "patch", "delete", "options", "head", "trace"})
|
|
39
|
+
|
|
40
|
+
|
|
36
41
|
class ExternalDocs(BaseModel):
|
|
37
42
|
"""
|
|
38
43
|
External documentation reference.
|
|
@@ -79,7 +84,7 @@ class OpenAPIConnector(BaseModel):
|
|
|
79
84
|
raise ValueError(f"OpenAPI version must be {OPENAPI_VERSION_PREFIX}x, got: {v}")
|
|
80
85
|
return v
|
|
81
86
|
|
|
82
|
-
def get_entity_operations(self, entity_name: str) -> list[tuple[str, str,
|
|
87
|
+
def get_entity_operations(self, entity_name: str) -> list[tuple[str, str, Operation]]:
|
|
83
88
|
"""
|
|
84
89
|
Get all operations for a specific entity.
|
|
85
90
|
|
|
@@ -89,22 +94,7 @@ class OpenAPIConnector(BaseModel):
|
|
|
89
94
|
Returns:
|
|
90
95
|
List of tuples: (path, method, operation)
|
|
91
96
|
"""
|
|
92
|
-
|
|
93
|
-
for path, path_item in self.paths.items():
|
|
94
|
-
for method in [
|
|
95
|
-
"get",
|
|
96
|
-
"post",
|
|
97
|
-
"put",
|
|
98
|
-
"patch",
|
|
99
|
-
"delete",
|
|
100
|
-
"options",
|
|
101
|
-
"head",
|
|
102
|
-
"trace",
|
|
103
|
-
]:
|
|
104
|
-
operation = getattr(path_item, method, None)
|
|
105
|
-
if operation and operation.x_airbyte_entity == entity_name:
|
|
106
|
-
results.append((path, method, operation))
|
|
107
|
-
return results
|
|
97
|
+
return [(path, method, op) for path, method, op in self._iter_operations() if op.x_airbyte_entity == entity_name]
|
|
108
98
|
|
|
109
99
|
def list_entities(self) -> list[str]:
|
|
110
100
|
"""
|
|
@@ -113,19 +103,18 @@ class OpenAPIConnector(BaseModel):
|
|
|
113
103
|
Returns:
|
|
114
104
|
Sorted list of unique entity names
|
|
115
105
|
"""
|
|
116
|
-
entities =
|
|
117
|
-
for path_item in self.paths.values():
|
|
118
|
-
for method in [
|
|
119
|
-
"get",
|
|
120
|
-
"post",
|
|
121
|
-
"put",
|
|
122
|
-
"patch",
|
|
123
|
-
"delete",
|
|
124
|
-
"options",
|
|
125
|
-
"head",
|
|
126
|
-
"trace",
|
|
127
|
-
]:
|
|
128
|
-
operation = getattr(path_item, method, None)
|
|
129
|
-
if operation and operation.x_airbyte_entity:
|
|
130
|
-
entities.add(operation.x_airbyte_entity)
|
|
106
|
+
entities = {op.x_airbyte_entity for _, _, op in self._iter_operations() if op.x_airbyte_entity}
|
|
131
107
|
return sorted(entities)
|
|
108
|
+
|
|
109
|
+
def _iter_operations(self) -> Iterator[tuple[str, str, Operation]]:
|
|
110
|
+
"""
|
|
111
|
+
Iterate over all operations in the spec.
|
|
112
|
+
|
|
113
|
+
Yields:
|
|
114
|
+
Tuples of (path, method, operation) for each defined operation
|
|
115
|
+
"""
|
|
116
|
+
for path, path_item in self.paths.items():
|
|
117
|
+
for method in HTTP_METHODS:
|
|
118
|
+
operation = getattr(path_item, method, None)
|
|
119
|
+
if operation:
|
|
120
|
+
yield path, method, operation
|