airbyte-cdk 6.33.2.dev1__py3-none-any.whl → 6.33.4__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_cdk/sources/declarative/auth/oauth.py +6 -1
- airbyte_cdk/sources/declarative/concurrent_declarative_source.py +15 -1
- airbyte_cdk/sources/declarative/declarative_component_schema.yaml +30 -129
- airbyte_cdk/sources/declarative/decoders/__init__.py +0 -4
- airbyte_cdk/sources/declarative/decoders/composite_raw_decoder.py +7 -2
- airbyte_cdk/sources/declarative/decoders/json_decoder.py +12 -58
- airbyte_cdk/sources/declarative/extractors/record_selector.py +12 -3
- airbyte_cdk/sources/declarative/incremental/concurrent_partition_cursor.py +6 -11
- airbyte_cdk/sources/declarative/models/declarative_component_schema.py +22 -84
- airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py +66 -86
- airbyte_cdk/sources/streams/call_rate.py +148 -86
- airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py +3 -0
- {airbyte_cdk-6.33.2.dev1.dist-info → airbyte_cdk-6.33.4.dist-info}/METADATA +1 -1
- {airbyte_cdk-6.33.2.dev1.dist-info → airbyte_cdk-6.33.4.dist-info}/RECORD +18 -18
- {airbyte_cdk-6.33.2.dev1.dist-info → airbyte_cdk-6.33.4.dist-info}/LICENSE.txt +0 -0
- {airbyte_cdk-6.33.2.dev1.dist-info → airbyte_cdk-6.33.4.dist-info}/LICENSE_SHORT +0 -0
- {airbyte_cdk-6.33.2.dev1.dist-info → airbyte_cdk-6.33.4.dist-info}/WHEEL +0 -0
- {airbyte_cdk-6.33.2.dev1.dist-info → airbyte_cdk-6.33.4.dist-info}/entry_points.txt +0 -0
@@ -8,10 +8,9 @@ import datetime
|
|
8
8
|
import logging
|
9
9
|
import re
|
10
10
|
import time
|
11
|
-
from dataclasses import InitVar, dataclass, field
|
12
11
|
from datetime import timedelta
|
13
12
|
from threading import RLock
|
14
|
-
from typing import TYPE_CHECKING, Any, Mapping, Optional
|
13
|
+
from typing import TYPE_CHECKING, Any, Mapping, Optional
|
15
14
|
from urllib import parse
|
16
15
|
|
17
16
|
import requests
|
@@ -27,6 +26,7 @@ else:
|
|
27
26
|
MIXIN_BASE = object
|
28
27
|
|
29
28
|
logger = logging.getLogger("airbyte")
|
29
|
+
logging.getLogger("pyrate_limiter").setLevel(logging.WARNING)
|
30
30
|
|
31
31
|
|
32
32
|
@dataclasses.dataclass
|
@@ -100,7 +100,7 @@ class RequestMatcher(abc.ABC):
|
|
100
100
|
|
101
101
|
|
102
102
|
class HttpRequestMatcher(RequestMatcher):
|
103
|
-
"""Simple implementation of RequestMatcher for
|
103
|
+
"""Simple implementation of RequestMatcher for HTTP requests using HttpRequestRegexMatcher under the hood."""
|
104
104
|
|
105
105
|
def __init__(
|
106
106
|
self,
|
@@ -111,55 +111,42 @@ class HttpRequestMatcher(RequestMatcher):
|
|
111
111
|
):
|
112
112
|
"""Constructor
|
113
113
|
|
114
|
-
:param method:
|
115
|
-
:param url:
|
116
|
-
:param params:
|
117
|
-
:param headers:
|
114
|
+
:param method: HTTP method (e.g., "GET", "POST").
|
115
|
+
:param url: Full URL to match.
|
116
|
+
:param params: Dictionary of query parameters to match.
|
117
|
+
:param headers: Dictionary of headers to match.
|
118
118
|
"""
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
119
|
+
# Parse the URL to extract the base and path
|
120
|
+
if url:
|
121
|
+
parsed_url = parse.urlsplit(url)
|
122
|
+
url_base = f"{parsed_url.scheme}://{parsed_url.netloc}"
|
123
|
+
url_path = parsed_url.path if parsed_url.path != "/" else None
|
124
|
+
else:
|
125
|
+
url_base = None
|
126
|
+
url_path = None
|
127
|
+
|
128
|
+
# Use HttpRequestRegexMatcher under the hood
|
129
|
+
self._regex_matcher = HttpRequestRegexMatcher(
|
130
|
+
method=method,
|
131
|
+
url_base=url_base,
|
132
|
+
url_path_pattern=re.escape(url_path) if url_path else None,
|
133
|
+
params=params,
|
134
|
+
headers=headers,
|
135
|
+
)
|
133
136
|
|
134
137
|
def __call__(self, request: Any) -> bool:
|
135
138
|
"""
|
136
|
-
|
137
|
-
:
|
138
|
-
:return: True if matches the provided request object, False - otherwise
|
139
|
+
:param request: A requests.Request or requests.PreparedRequest instance.
|
140
|
+
:return: True if the request matches all provided criteria; False otherwise.
|
139
141
|
"""
|
140
|
-
|
141
|
-
prepared_request = request.prepare()
|
142
|
-
elif isinstance(request, requests.PreparedRequest):
|
143
|
-
prepared_request = request
|
144
|
-
else:
|
145
|
-
return False
|
142
|
+
return self._regex_matcher(request)
|
146
143
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
return False
|
154
|
-
if self._params is not None:
|
155
|
-
parsed_url = parse.urlsplit(prepared_request.url)
|
156
|
-
params = dict(parse.parse_qsl(str(parsed_url.query)))
|
157
|
-
if not self._match_dict(params, self._params):
|
158
|
-
return False
|
159
|
-
if self._headers is not None:
|
160
|
-
if not self._match_dict(prepared_request.headers, self._headers):
|
161
|
-
return False
|
162
|
-
return True
|
144
|
+
def __str__(self) -> str:
|
145
|
+
return (
|
146
|
+
f"HttpRequestMatcher(method={self._regex_matcher._method}, "
|
147
|
+
f"url={self._regex_matcher._url_base}{self._regex_matcher._url_path_pattern.pattern if self._regex_matcher._url_path_pattern else ''}, "
|
148
|
+
f"params={self._regex_matcher._params}, headers={self._regex_matcher._headers})"
|
149
|
+
)
|
163
150
|
|
164
151
|
|
165
152
|
class HttpRequestRegexMatcher(RequestMatcher):
|
@@ -220,8 +207,8 @@ class HttpRequestRegexMatcher(RequestMatcher):
|
|
220
207
|
return False
|
221
208
|
|
222
209
|
# Check HTTP method.
|
223
|
-
if self._method is not None
|
224
|
-
if prepared_request.method
|
210
|
+
if self._method is not None:
|
211
|
+
if prepared_request.method != self._method:
|
225
212
|
return False
|
226
213
|
|
227
214
|
# Parse the URL.
|
@@ -255,6 +242,13 @@ class HttpRequestRegexMatcher(RequestMatcher):
|
|
255
242
|
|
256
243
|
return True
|
257
244
|
|
245
|
+
def __str__(self) -> str:
|
246
|
+
regex = self._url_path_pattern.pattern if self._url_path_pattern else None
|
247
|
+
return (
|
248
|
+
f"HttpRequestRegexMatcher(method={self._method}, url_base={self._url_base}, "
|
249
|
+
f"url_path_pattern={regex}, params={self._params}, headers={self._headers})"
|
250
|
+
)
|
251
|
+
|
258
252
|
|
259
253
|
class BaseCallRatePolicy(AbstractCallRatePolicy, abc.ABC):
|
260
254
|
def __init__(self, matchers: list[RequestMatcher]):
|
@@ -353,6 +347,14 @@ class FixedWindowCallRatePolicy(BaseCallRatePolicy):
|
|
353
347
|
|
354
348
|
self._calls_num += weight
|
355
349
|
|
350
|
+
def __str__(self) -> str:
|
351
|
+
matcher_str = ", ".join(f"{matcher}" for matcher in self._matchers)
|
352
|
+
return (
|
353
|
+
f"FixedWindowCallRatePolicy(call_limit={self._call_limit}, period={self._offset}, "
|
354
|
+
f"calls_used={self._calls_num}, next_reset={self._next_reset_ts}, "
|
355
|
+
f"matchers=[{matcher_str}])"
|
356
|
+
)
|
357
|
+
|
356
358
|
def update(
|
357
359
|
self, available_calls: Optional[int], call_reset_ts: Optional[datetime.datetime]
|
358
360
|
) -> None:
|
@@ -459,6 +461,19 @@ class MovingWindowCallRatePolicy(BaseCallRatePolicy):
|
|
459
461
|
# if available_calls is not None and call_reset_ts is not None:
|
460
462
|
# ts = call_reset_ts.timestamp()
|
461
463
|
|
464
|
+
def __str__(self) -> str:
|
465
|
+
"""Return a human-friendly description of the moving window rate policy for logging purposes."""
|
466
|
+
rates_info = ", ".join(
|
467
|
+
f"{rate.limit} per {timedelta(milliseconds=rate.interval)}"
|
468
|
+
for rate in self._bucket.rates
|
469
|
+
)
|
470
|
+
current_bucket_count = self._bucket.count()
|
471
|
+
matcher_str = ", ".join(f"{matcher}" for matcher in self._matchers)
|
472
|
+
return (
|
473
|
+
f"MovingWindowCallRatePolicy(rates=[{rates_info}], current_bucket_count={current_bucket_count}, "
|
474
|
+
f"matchers=[{matcher_str}])"
|
475
|
+
)
|
476
|
+
|
462
477
|
|
463
478
|
class AbstractAPIBudget(abc.ABC):
|
464
479
|
"""Interface to some API where a client allowed to have N calls per T interval.
|
@@ -495,17 +510,41 @@ class AbstractAPIBudget(abc.ABC):
|
|
495
510
|
"""
|
496
511
|
|
497
512
|
|
498
|
-
@dataclass
|
499
513
|
class APIBudget(AbstractAPIBudget):
|
500
|
-
"""
|
501
|
-
|
502
|
-
|
514
|
+
"""Default APIBudget implementation"""
|
515
|
+
|
516
|
+
def __init__(
|
517
|
+
self, policies: list[AbstractCallRatePolicy], maximum_attempts_to_acquire: int = 100000
|
518
|
+
) -> None:
|
519
|
+
"""Constructor
|
503
520
|
|
504
|
-
|
505
|
-
|
521
|
+
:param policies: list of policies in this budget
|
522
|
+
:param maximum_attempts_to_acquire: number of attempts before throwing hit ratelimit exception, we put some big number here
|
523
|
+
to avoid situations when many threads compete with each other for a few lots over a significant amount of time
|
524
|
+
"""
|
525
|
+
|
526
|
+
self._policies = policies
|
527
|
+
self._maximum_attempts_to_acquire = maximum_attempts_to_acquire
|
528
|
+
|
529
|
+
def _extract_endpoint(self, request: Any) -> str:
|
530
|
+
"""Extract the endpoint URL from the request if available."""
|
531
|
+
endpoint = None
|
532
|
+
try:
|
533
|
+
# If the request is already a PreparedRequest, it should have a URL.
|
534
|
+
if isinstance(request, requests.PreparedRequest):
|
535
|
+
endpoint = request.url
|
536
|
+
# If it's a requests.Request, we call prepare() to extract the URL.
|
537
|
+
elif isinstance(request, requests.Request):
|
538
|
+
prepared = request.prepare()
|
539
|
+
endpoint = prepared.url
|
540
|
+
except Exception as e:
|
541
|
+
logger.debug(f"Error extracting endpoint: {e}")
|
542
|
+
if endpoint:
|
543
|
+
return endpoint
|
544
|
+
return "unknown endpoint"
|
506
545
|
|
507
546
|
def get_matching_policy(self, request: Any) -> Optional[AbstractCallRatePolicy]:
|
508
|
-
for policy in self.
|
547
|
+
for policy in self._policies:
|
509
548
|
if policy.matches(request):
|
510
549
|
return policy
|
511
550
|
return None
|
@@ -517,20 +556,24 @@ class APIBudget(AbstractAPIBudget):
|
|
517
556
|
Matchers will be called sequentially in the same order they were added.
|
518
557
|
The first matcher that returns True will
|
519
558
|
|
520
|
-
:param request:
|
521
|
-
:param block: when
|
522
|
-
:param timeout: if provided
|
523
|
-
:raises: CallRateLimitHit
|
559
|
+
:param request: the API request
|
560
|
+
:param block: when True (default) will block until a call credit is available
|
561
|
+
:param timeout: if provided, limits maximum waiting time; otherwise, waits indefinitely
|
562
|
+
:raises: CallRateLimitHit if the call credit cannot be acquired within the timeout
|
524
563
|
"""
|
525
564
|
|
526
565
|
policy = self.get_matching_policy(request)
|
566
|
+
endpoint = self._extract_endpoint(request)
|
527
567
|
if policy:
|
568
|
+
logger.debug(f"Acquiring call for endpoint {endpoint} using policy: {policy}")
|
528
569
|
self._do_acquire(request=request, policy=policy, block=block, timeout=timeout)
|
529
|
-
elif self.
|
530
|
-
logger.
|
570
|
+
elif self._policies:
|
571
|
+
logger.debug(
|
572
|
+
f"No policies matched for endpoint {endpoint} (request: {request}). Allowing call by default."
|
573
|
+
)
|
531
574
|
|
532
575
|
def update_from_response(self, request: Any, response: Any) -> None:
|
533
|
-
"""Update budget information based on
|
576
|
+
"""Update budget information based on the API response.
|
534
577
|
|
535
578
|
:param request: the initial request that triggered this response
|
536
579
|
:param response: response from the API
|
@@ -540,16 +583,18 @@ class APIBudget(AbstractAPIBudget):
|
|
540
583
|
def _do_acquire(
|
541
584
|
self, request: Any, policy: AbstractCallRatePolicy, block: bool, timeout: Optional[float]
|
542
585
|
) -> None:
|
543
|
-
"""Internal method to try to acquire a call credit
|
586
|
+
"""Internal method to try to acquire a call credit.
|
544
587
|
|
545
|
-
:param request:
|
546
|
-
:param policy:
|
547
|
-
:param block:
|
548
|
-
:param timeout:
|
588
|
+
:param request: the API request
|
589
|
+
:param policy: the matching rate-limiting policy
|
590
|
+
:param block: indicates whether to block until a call credit is available
|
591
|
+
:param timeout: maximum time to wait if blocking
|
592
|
+
:raises: CallRateLimitHit if unable to acquire a call credit
|
549
593
|
"""
|
550
594
|
last_exception = None
|
551
|
-
|
552
|
-
|
595
|
+
endpoint = self._extract_endpoint(request)
|
596
|
+
# sometimes we spend all budget before a second attempt, so we have a few more attempts
|
597
|
+
for attempt in range(1, self._maximum_attempts_to_acquire):
|
553
598
|
try:
|
554
599
|
policy.try_acquire(request, weight=1)
|
555
600
|
return
|
@@ -560,31 +605,48 @@ class APIBudget(AbstractAPIBudget):
|
|
560
605
|
time_to_wait = min(timedelta(seconds=timeout), exc.time_to_wait)
|
561
606
|
else:
|
562
607
|
time_to_wait = exc.time_to_wait
|
563
|
-
|
564
|
-
time_to_wait = max(
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
"reached call limit %s. going to sleep for %s", exc.rate, time_to_wait
|
608
|
+
# Ensure we never sleep for a negative duration.
|
609
|
+
time_to_wait = max(timedelta(0), time_to_wait)
|
610
|
+
logger.debug(
|
611
|
+
f"Policy {policy} reached call limit for endpoint {endpoint} ({exc.rate}). "
|
612
|
+
f"Sleeping for {time_to_wait} on attempt {attempt}."
|
569
613
|
)
|
570
614
|
time.sleep(time_to_wait.total_seconds())
|
571
615
|
else:
|
616
|
+
logger.debug(
|
617
|
+
f"Policy {policy} reached call limit for endpoint {endpoint} ({exc.rate}) "
|
618
|
+
f"and blocking is disabled."
|
619
|
+
)
|
572
620
|
raise
|
573
621
|
|
574
622
|
if last_exception:
|
575
|
-
logger.
|
576
|
-
"
|
623
|
+
logger.debug(
|
624
|
+
f"Exhausted all {self._maximum_attempts_to_acquire} attempts to acquire a call for endpoint {endpoint} "
|
625
|
+
f"using policy: {policy}"
|
577
626
|
)
|
578
627
|
raise last_exception
|
579
628
|
|
580
629
|
|
581
|
-
@dataclass
|
582
630
|
class HttpAPIBudget(APIBudget):
|
583
631
|
"""Implementation of AbstractAPIBudget for HTTP"""
|
584
632
|
|
585
|
-
|
586
|
-
|
587
|
-
|
633
|
+
def __init__(
|
634
|
+
self,
|
635
|
+
ratelimit_reset_header: str = "ratelimit-reset",
|
636
|
+
ratelimit_remaining_header: str = "ratelimit-remaining",
|
637
|
+
status_codes_for_ratelimit_hit: list[int] = [429],
|
638
|
+
**kwargs: Any,
|
639
|
+
):
|
640
|
+
"""Constructor
|
641
|
+
|
642
|
+
:param ratelimit_reset_header: name of the header that has a timestamp of the next reset of call budget
|
643
|
+
:param ratelimit_remaining_header: name of the header that has the number of calls left
|
644
|
+
:param status_codes_for_ratelimit_hit: list of HTTP status codes that signal about rate limit being hit
|
645
|
+
"""
|
646
|
+
self._ratelimit_reset_header = ratelimit_reset_header
|
647
|
+
self._ratelimit_remaining_header = ratelimit_remaining_header
|
648
|
+
self._status_codes_for_ratelimit_hit = status_codes_for_ratelimit_hit
|
649
|
+
super().__init__(**kwargs)
|
588
650
|
|
589
651
|
def update_from_response(self, request: Any, response: Any) -> None:
|
590
652
|
policy = self.get_matching_policy(request)
|
@@ -599,17 +661,17 @@ class HttpAPIBudget(APIBudget):
|
|
599
661
|
def get_reset_ts_from_response(
|
600
662
|
self, response: requests.Response
|
601
663
|
) -> Optional[datetime.datetime]:
|
602
|
-
if response.headers.get(self.
|
664
|
+
if response.headers.get(self._ratelimit_reset_header):
|
603
665
|
return datetime.datetime.fromtimestamp(
|
604
|
-
int(response.headers[self.
|
666
|
+
int(response.headers[self._ratelimit_reset_header])
|
605
667
|
)
|
606
668
|
return None
|
607
669
|
|
608
670
|
def get_calls_left_from_response(self, response: requests.Response) -> Optional[int]:
|
609
|
-
if response.headers.get(self.
|
610
|
-
return int(response.headers[self.
|
671
|
+
if response.headers.get(self._ratelimit_remaining_header):
|
672
|
+
return int(response.headers[self._ratelimit_remaining_header])
|
611
673
|
|
612
|
-
if response.status_code in self.
|
674
|
+
if response.status_code in self._status_codes_for_ratelimit_hit:
|
613
675
|
return 0
|
614
676
|
|
615
677
|
return None
|
@@ -261,6 +261,9 @@ class AbstractOauth2Authenticator(AuthBase):
|
|
261
261
|
|
262
262
|
:return: expiration datetime
|
263
263
|
"""
|
264
|
+
if not value and not self.token_has_expired():
|
265
|
+
# No expiry token was provided but the previous one is not expired so it's fine
|
266
|
+
return self.get_token_expiry_date()
|
264
267
|
|
265
268
|
if self.token_expiry_is_time_of_expiration:
|
266
269
|
if not self.token_expiry_date_format:
|
@@ -53,7 +53,7 @@ airbyte_cdk/sources/declarative/async_job/timer.py,sha256=Fb8P72CQ7jIzJyzMSSNuBf
|
|
53
53
|
airbyte_cdk/sources/declarative/auth/__init__.py,sha256=e2CRrcBWGhz3sQu3Oh34d1riEIwXipGS8hrSB1pu0Oo,284
|
54
54
|
airbyte_cdk/sources/declarative/auth/declarative_authenticator.py,sha256=nf-OmRUHYG4ORBwyb5CANzuHEssE-oNmL-Lccn41Td8,1099
|
55
55
|
airbyte_cdk/sources/declarative/auth/jwt.py,sha256=SICqNsN2Cn_EgKadIgWuZpQxuMHyzrMZD_2-Uwy10rY,8539
|
56
|
-
airbyte_cdk/sources/declarative/auth/oauth.py,sha256=
|
56
|
+
airbyte_cdk/sources/declarative/auth/oauth.py,sha256=SUfib1oSzlyRRnOSg8Bui73mfyrcyr9OssdchbKdu4s,14162
|
57
57
|
airbyte_cdk/sources/declarative/auth/selective_authenticator.py,sha256=qGwC6YsCldr1bIeKG6Qo-A9a5cTdHw-vcOn3OtQrS4c,1540
|
58
58
|
airbyte_cdk/sources/declarative/auth/token.py,sha256=2EnE78EhBOY9hbeZnQJ9AuFaM-G7dccU-oKo_LThRQk,11070
|
59
59
|
airbyte_cdk/sources/declarative/auth/token_provider.py,sha256=9CuSsmOoHkvlc4k-oZ3Jx5luAgfTMm1I_5HOZxw7wMU,3075
|
@@ -63,17 +63,17 @@ airbyte_cdk/sources/declarative/checks/check_stream.py,sha256=dAA-UhmMj0WLXCkRQr
|
|
63
63
|
airbyte_cdk/sources/declarative/checks/connection_checker.py,sha256=MBRJo6WJlZQHpIfOGaNOkkHUmgUl_4wDM6VPo41z5Ss,1383
|
64
64
|
airbyte_cdk/sources/declarative/concurrency_level/__init__.py,sha256=5XUqrmlstYlMM0j6crktlKQwALek0uiz2D3WdM46MyA,191
|
65
65
|
airbyte_cdk/sources/declarative/concurrency_level/concurrency_level.py,sha256=YIwCTCpOr_QSNW4ltQK0yUGWInI8PKNY216HOOegYLk,2101
|
66
|
-
airbyte_cdk/sources/declarative/concurrent_declarative_source.py,sha256=
|
66
|
+
airbyte_cdk/sources/declarative/concurrent_declarative_source.py,sha256=ThOqmaaqPykS2gTDKnlLSPy0p7djjV1Svazes58Rmic,28844
|
67
67
|
airbyte_cdk/sources/declarative/datetime/__init__.py,sha256=l9LG7Qm6e5r_qgqfVKnx3mXYtg1I9MmMjomVIPfU4XA,177
|
68
68
|
airbyte_cdk/sources/declarative/datetime/datetime_parser.py,sha256=SX9JjdesN1edN2WVUVMzU_ptqp2QB1OnsnjZ4mwcX7w,2579
|
69
69
|
airbyte_cdk/sources/declarative/datetime/min_max_datetime.py,sha256=0BHBtDNQZfvwM45-tY5pNlTcKAFSGGNxemoi0Jic-0E,5785
|
70
|
-
airbyte_cdk/sources/declarative/declarative_component_schema.yaml,sha256=
|
70
|
+
airbyte_cdk/sources/declarative/declarative_component_schema.yaml,sha256=LExB78FzoQ1ueR5GRyEO-r4HqdghiywvvfyVUXhvU4I,144561
|
71
71
|
airbyte_cdk/sources/declarative/declarative_source.py,sha256=nF7wBqFd3AQmEKAm4CnIo29CJoQL562cJGSCeL8U8bA,1531
|
72
72
|
airbyte_cdk/sources/declarative/declarative_stream.py,sha256=venZjfpvtqr3oFSuvMBWtn4h9ayLhD4L65ACuXCDZ64,10445
|
73
|
-
airbyte_cdk/sources/declarative/decoders/__init__.py,sha256=
|
74
|
-
airbyte_cdk/sources/declarative/decoders/composite_raw_decoder.py,sha256=
|
73
|
+
airbyte_cdk/sources/declarative/decoders/__init__.py,sha256=JHb_0d3SE6kNY10mxA5YBEKPeSbsWYjByq1gUQxepoE,953
|
74
|
+
airbyte_cdk/sources/declarative/decoders/composite_raw_decoder.py,sha256=kg5_kNlhXj8p9GZFztlbG16pk1XcMtP9ezqulq1VNg4,4545
|
75
75
|
airbyte_cdk/sources/declarative/decoders/decoder.py,sha256=sl-Gt8lXi7yD2Q-sD8je5QS2PbgrgsYjxRLWsay7DMc,826
|
76
|
-
airbyte_cdk/sources/declarative/decoders/json_decoder.py,sha256=
|
76
|
+
airbyte_cdk/sources/declarative/decoders/json_decoder.py,sha256=BdWpXXPhEGf_zknggJmhojLosmxuw51RBVTS0jvdCPc,2080
|
77
77
|
airbyte_cdk/sources/declarative/decoders/noop_decoder.py,sha256=iZh0yKY_JzgBnJWiubEusf5c0o6Khd-8EWFWT-8EgFo,542
|
78
78
|
airbyte_cdk/sources/declarative/decoders/pagination_decoder_decorator.py,sha256=ZVBZhAOl0I0MymXN5CKTC-kIXG4GuUQAEyn0XpUDuSE,1081
|
79
79
|
airbyte_cdk/sources/declarative/decoders/xml_decoder.py,sha256=EU-7t-5vIGRHZ14h-f0GUE4V5-eTM9Flux-A8xgI1Rc,3117
|
@@ -84,11 +84,11 @@ airbyte_cdk/sources/declarative/extractors/dpath_extractor.py,sha256=wR4Ol4MG2lt
|
|
84
84
|
airbyte_cdk/sources/declarative/extractors/http_selector.py,sha256=2zWZ4ewTqQC8VwkjS0xD_u350Km3SiYP7hpOOgiLg5o,1169
|
85
85
|
airbyte_cdk/sources/declarative/extractors/record_extractor.py,sha256=XJELMjahAsaomlvQgN2zrNO0DJX0G0fr9r682gUz7Pg,691
|
86
86
|
airbyte_cdk/sources/declarative/extractors/record_filter.py,sha256=yTdEkyDUSW2KbFkEwJJMlS963C955LgCCOVfTmmScpQ,3367
|
87
|
-
airbyte_cdk/sources/declarative/extractors/record_selector.py,sha256=
|
87
|
+
airbyte_cdk/sources/declarative/extractors/record_selector.py,sha256=HCqx7IyENM_aRF4it2zJN26_vDu6WeP8XgCxQWHUvcY,6934
|
88
88
|
airbyte_cdk/sources/declarative/extractors/response_to_file_extractor.py,sha256=LhqGDfX06_dDYLKsIVnwQ_nAWCln-v8PV7Wgt_QVeTI,6533
|
89
89
|
airbyte_cdk/sources/declarative/extractors/type_transformer.py,sha256=d6Y2Rfg8pMVEEnHllfVksWZdNVOU55yk34O03dP9muY,1626
|
90
90
|
airbyte_cdk/sources/declarative/incremental/__init__.py,sha256=U1oZKtBaEC6IACmvziY9Wzg7Z8EgF4ZuR7NwvjlB_Sk,1255
|
91
|
-
airbyte_cdk/sources/declarative/incremental/concurrent_partition_cursor.py,sha256=
|
91
|
+
airbyte_cdk/sources/declarative/incremental/concurrent_partition_cursor.py,sha256=5dbO47TFmC5Oz8TZ8DKXwXeZElz70xy2v2HJlZr5qVs,17751
|
92
92
|
airbyte_cdk/sources/declarative/incremental/datetime_based_cursor.py,sha256=5Bl_2EeA4as0e3J23Yxp8Q8BXzh0nJ2NcGSgj3V0h2o,21954
|
93
93
|
airbyte_cdk/sources/declarative/incremental/declarative_cursor.py,sha256=5Bhw9VRPyIuCaD0wmmq_L3DZsa-rJgtKSEUzSd8YYD0,536
|
94
94
|
airbyte_cdk/sources/declarative/incremental/global_substream_cursor.py,sha256=9HO-QbL9akvjq2NP7l498RwLA4iQZlBMQW1tZbt34I8,15943
|
@@ -109,13 +109,13 @@ airbyte_cdk/sources/declarative/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW
|
|
109
109
|
airbyte_cdk/sources/declarative/migrations/legacy_to_per_partition_state_migration.py,sha256=iemy3fKLczcU0-Aor7tx5jcT6DRedKMqyK7kCOp01hg,3924
|
110
110
|
airbyte_cdk/sources/declarative/migrations/state_migration.py,sha256=KWPjealMLKSMtajXgkdGgKg7EmTLR-CqqD7UIh0-eDU,794
|
111
111
|
airbyte_cdk/sources/declarative/models/__init__.py,sha256=nUFxNCiKeYRVXuZEKA7GD-lTHxsiKcQ8FitZjKhPIvE,100
|
112
|
-
airbyte_cdk/sources/declarative/models/declarative_component_schema.py,sha256=
|
112
|
+
airbyte_cdk/sources/declarative/models/declarative_component_schema.py,sha256=peEl_gQUK6Lu98BntStmtVh0BoBI7OBTUNg9ftMGhEA,101946
|
113
113
|
airbyte_cdk/sources/declarative/parsers/__init__.py,sha256=ZnqYNxHsKCgO38IwB34RQyRMXTs4GTvlRi3ImKnIioo,61
|
114
114
|
airbyte_cdk/sources/declarative/parsers/custom_code_compiler.py,sha256=958MMX6_ZOJUlDDdNr9Krosgi2bCKGx2Z765M2Woz18,5505
|
115
115
|
airbyte_cdk/sources/declarative/parsers/custom_exceptions.py,sha256=Rir9_z3Kcd5Es0-LChrzk-0qubAsiK_RSEnLmK2OXm8,553
|
116
116
|
airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py,sha256=CXwTfD3wSQq3okcqwigpprbHhSURUokh4GK2OmOyKC8,9132
|
117
117
|
airbyte_cdk/sources/declarative/parsers/manifest_reference_resolver.py,sha256=IWUOdF03o-aQn0Occo1BJCxU0Pz-QILk5L67nzw2thw,6803
|
118
|
-
airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py,sha256=
|
118
|
+
airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py,sha256=YAM05AejFafdtx2deEuxEjU3GtebyYVr-MnsIY8eiZU,133750
|
119
119
|
airbyte_cdk/sources/declarative/partition_routers/__init__.py,sha256=HJ-Syp3p7RpyR_OK0X_a2kSyISfu3W-PKrRI16iY0a8,957
|
120
120
|
airbyte_cdk/sources/declarative/partition_routers/async_job_partition_router.py,sha256=VelO7zKqKtzMJ35jyFeg0ypJLQC0plqqIBNXoBW1G2E,3001
|
121
121
|
airbyte_cdk/sources/declarative/partition_routers/cartesian_product_stream_slicer.py,sha256=c5cuVFM6NFkuQqG8Z5IwkBuwDrvXZN1CunUOM_L0ezg,6892
|
@@ -249,7 +249,7 @@ airbyte_cdk/sources/message/repository.py,sha256=SG7avgti_-dj8FcRHTTrhgLLGJbElv1
|
|
249
249
|
airbyte_cdk/sources/source.py,sha256=KIBBH5VLEb8BZ8B9aROlfaI6OLoJqKDPMJ10jkAR7nk,3611
|
250
250
|
airbyte_cdk/sources/streams/__init__.py,sha256=8fzTKpRTnSx5PggXgQPKJzHNZUV2BCA40N-dI6JM1xI,256
|
251
251
|
airbyte_cdk/sources/streams/availability_strategy.py,sha256=_RU4JITrxMEN36g1RDHMu0iSw0I_3yWGfo5N8_YRvOg,3247
|
252
|
-
airbyte_cdk/sources/streams/call_rate.py,sha256=
|
252
|
+
airbyte_cdk/sources/streams/call_rate.py,sha256=jRsGp1PDZBCDQNxzcGVnVmVzLk0wLHxS1JnJwMAgy9U,27568
|
253
253
|
airbyte_cdk/sources/streams/checkpoint/__init__.py,sha256=3oy7Hd4ivVWTZlN6dKAf4Fv_G7U5iZrvhO9hT871UIo,712
|
254
254
|
airbyte_cdk/sources/streams/checkpoint/checkpoint_reader.py,sha256=6HMT2NI-FQuaW0nt95NcyWrt5rZN4gF-Arx0sxdgbv4,15221
|
255
255
|
airbyte_cdk/sources/streams/checkpoint/cursor.py,sha256=3e-3c-54k8U7Awno7DMmAD9ndbnl9OM48EnbEgeDUO0,3499
|
@@ -295,7 +295,7 @@ airbyte_cdk/sources/streams/http/http.py,sha256=0uariNq8OFnlX7iqOHwBhecxA-Hfd5hS
|
|
295
295
|
airbyte_cdk/sources/streams/http/http_client.py,sha256=tDE0ROtxjGMVphvsw8INvGMtZ97hIF-v47pZ3jIyiwc,23011
|
296
296
|
airbyte_cdk/sources/streams/http/rate_limiting.py,sha256=IwdjrHKUnU97XO4qONgYRv4YYW51xQ8SJm4WLafXDB8,6351
|
297
297
|
airbyte_cdk/sources/streams/http/requests_native_auth/__init__.py,sha256=RN0D3nOX1xLgwEwKWu6pkGy3XqBFzKSNZ8Lf6umU2eY,413
|
298
|
-
airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py,sha256=
|
298
|
+
airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py,sha256=cM5CM1mnbTEMiY6gKHblGXr9KTS5VEziGoc-TXC302k,18791
|
299
299
|
airbyte_cdk/sources/streams/http/requests_native_auth/abstract_token.py,sha256=Y3n7J-sk5yGjv_OxtY6Z6k0PEsFZmtIRi-x0KCbaHdA,1010
|
300
300
|
airbyte_cdk/sources/streams/http/requests_native_auth/oauth.py,sha256=C2j2uVfi9d-3KgHO3NGxIiFdfASjHOtsd6g_LWPYOAs,20311
|
301
301
|
airbyte_cdk/sources/streams/http/requests_native_auth/token.py,sha256=h5PTzcdH-RQLeCg7xZ45w_484OPUDSwNWl_iMJQmZoI,2526
|
@@ -351,9 +351,9 @@ airbyte_cdk/utils/slice_hasher.py,sha256=EDxgROHDbfG-QKQb59m7h_7crN1tRiawdf5uU7G
|
|
351
351
|
airbyte_cdk/utils/spec_schema_transformations.py,sha256=-5HTuNsnDBAhj-oLeQXwpTGA0HdcjFOf2zTEMUTTg_Y,816
|
352
352
|
airbyte_cdk/utils/stream_status_utils.py,sha256=ZmBoiy5HVbUEHAMrUONxZvxnvfV9CesmQJLDTAIWnWw,1171
|
353
353
|
airbyte_cdk/utils/traced_exception.py,sha256=C8uIBuCL_E4WnBAOPSxBicD06JAldoN9fGsQDp463OY,6292
|
354
|
-
airbyte_cdk-6.33.
|
355
|
-
airbyte_cdk-6.33.
|
356
|
-
airbyte_cdk-6.33.
|
357
|
-
airbyte_cdk-6.33.
|
358
|
-
airbyte_cdk-6.33.
|
359
|
-
airbyte_cdk-6.33.
|
354
|
+
airbyte_cdk-6.33.4.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
|
355
|
+
airbyte_cdk-6.33.4.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
|
356
|
+
airbyte_cdk-6.33.4.dist-info/METADATA,sha256=BaGO6g_mK2f56Ml6vx3sNcRzZIZrGgcyDATQ0TQsXps,6010
|
357
|
+
airbyte_cdk-6.33.4.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
358
|
+
airbyte_cdk-6.33.4.dist-info/entry_points.txt,sha256=fj-e3PAQvsxsQzyyq8UkG1k8spunWnD4BAH2AwlR6NM,95
|
359
|
+
airbyte_cdk-6.33.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|