airbyte-cdk 6.33.3__py3-none-any.whl → 6.33.5__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.
@@ -6,6 +6,7 @@ import abc
6
6
  import dataclasses
7
7
  import datetime
8
8
  import logging
9
+ import re
9
10
  import time
10
11
  from datetime import timedelta
11
12
  from threading import RLock
@@ -25,6 +26,7 @@ else:
25
26
  MIXIN_BASE = object
26
27
 
27
28
  logger = logging.getLogger("airbyte")
29
+ logging.getLogger("pyrate_limiter").setLevel(logging.WARNING)
28
30
 
29
31
 
30
32
  @dataclasses.dataclass
@@ -98,7 +100,7 @@ class RequestMatcher(abc.ABC):
98
100
 
99
101
 
100
102
  class HttpRequestMatcher(RequestMatcher):
101
- """Simple implementation of RequestMatcher for http requests case"""
103
+ """Simple implementation of RequestMatcher for HTTP requests using HttpRequestRegexMatcher under the hood."""
102
104
 
103
105
  def __init__(
104
106
  self,
@@ -109,32 +111,94 @@ class HttpRequestMatcher(RequestMatcher):
109
111
  ):
110
112
  """Constructor
111
113
 
112
- :param method:
113
- :param url:
114
- :param params:
115
- :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.
116
118
  """
117
- self._method = method
118
- self._url = url
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
+ )
136
+
137
+ def __call__(self, request: Any) -> bool:
138
+ """
139
+ :param request: A requests.Request or requests.PreparedRequest instance.
140
+ :return: True if the request matches all provided criteria; False otherwise.
141
+ """
142
+ return self._regex_matcher(request)
143
+
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
+ )
150
+
151
+
152
+ class HttpRequestRegexMatcher(RequestMatcher):
153
+ """
154
+ Extended RequestMatcher for HTTP requests that supports matching on:
155
+ - HTTP method (case-insensitive)
156
+ - URL base (scheme + netloc) optionally
157
+ - URL path pattern (a regex applied to the path portion of the URL)
158
+ - Query parameters (must be present)
159
+ - Headers (header names compared case-insensitively)
160
+ """
161
+
162
+ def __init__(
163
+ self,
164
+ method: Optional[str] = None,
165
+ url_base: Optional[str] = None,
166
+ url_path_pattern: Optional[str] = None,
167
+ params: Optional[Mapping[str, Any]] = None,
168
+ headers: Optional[Mapping[str, Any]] = None,
169
+ ):
170
+ """
171
+ :param method: HTTP method (e.g. "GET", "POST"); compared case-insensitively.
172
+ :param url_base: Base URL (scheme://host) that must match.
173
+ :param url_path_pattern: A regex pattern that will be applied to the path portion of the URL.
174
+ :param params: Dictionary of query parameters that must be present in the request.
175
+ :param headers: Dictionary of headers that must be present (header keys are compared case-insensitively).
176
+ """
177
+ self._method = method.upper() if method else None
178
+
179
+ # Normalize the url_base if provided: remove trailing slash.
180
+ self._url_base = url_base.rstrip("/") if url_base else None
181
+
182
+ # Compile the URL path pattern if provided.
183
+ self._url_path_pattern = re.compile(url_path_pattern) if url_path_pattern else None
184
+
185
+ # Normalize query parameters to strings.
119
186
  self._params = {str(k): str(v) for k, v in (params or {}).items()}
120
- self._headers = {str(k): str(v) for k, v in (headers or {}).items()}
187
+
188
+ # Normalize header keys to lowercase.
189
+ self._headers = {str(k).lower(): str(v) for k, v in (headers or {}).items()}
121
190
 
122
191
  @staticmethod
123
192
  def _match_dict(obj: Mapping[str, Any], pattern: Mapping[str, Any]) -> bool:
124
- """Check that all elements from pattern dict present and have the same values in obj dict
125
-
126
- :param obj:
127
- :param pattern:
128
- :return:
129
- """
193
+ """Check that every key/value in the pattern exists in the object."""
130
194
  return pattern.items() <= obj.items()
131
195
 
132
196
  def __call__(self, request: Any) -> bool:
133
197
  """
134
-
135
- :param request:
136
- :return: True if matches the provided request object, False - otherwise
198
+ :param request: A requests.Request or requests.PreparedRequest instance.
199
+ :return: True if the request matches all provided criteria; False otherwise.
137
200
  """
201
+ # Prepare the request (if needed) and extract the URL details.
138
202
  if isinstance(request, requests.Request):
139
203
  prepared_request = request.prepare()
140
204
  elif isinstance(request, requests.PreparedRequest):
@@ -142,23 +206,49 @@ class HttpRequestMatcher(RequestMatcher):
142
206
  else:
143
207
  return False
144
208
 
209
+ # Check HTTP method.
145
210
  if self._method is not None:
146
211
  if prepared_request.method != self._method:
147
212
  return False
148
- if self._url is not None and prepared_request.url is not None:
149
- url_without_params = prepared_request.url.split("?")[0]
150
- if url_without_params != self._url:
213
+
214
+ # Parse the URL.
215
+ parsed_url = parse.urlsplit(prepared_request.url)
216
+ # Reconstruct the base: scheme://netloc
217
+ request_url_base = f"{str(parsed_url.scheme)}://{str(parsed_url.netloc)}"
218
+ # The path (without query parameters)
219
+ request_path = str(parsed_url.path).rstrip("/")
220
+
221
+ # If a base URL is provided, check that it matches.
222
+ if self._url_base is not None:
223
+ if request_url_base != self._url_base:
224
+ return False
225
+
226
+ # If a URL path pattern is provided, ensure the path matches the regex.
227
+ if self._url_path_pattern is not None:
228
+ if not self._url_path_pattern.search(request_path):
151
229
  return False
152
- if self._params is not None:
153
- parsed_url = parse.urlsplit(prepared_request.url)
154
- params = dict(parse.parse_qsl(str(parsed_url.query)))
155
- if not self._match_dict(params, self._params):
230
+
231
+ # Check query parameters.
232
+ if self._params:
233
+ query_params = dict(parse.parse_qsl(str(parsed_url.query)))
234
+ if not self._match_dict(query_params, self._params):
156
235
  return False
157
- if self._headers is not None:
158
- if not self._match_dict(prepared_request.headers, self._headers):
236
+
237
+ # Check headers (normalize keys to lower-case).
238
+ if self._headers:
239
+ req_headers = {k.lower(): v for k, v in prepared_request.headers.items()}
240
+ if not self._match_dict(req_headers, self._headers):
159
241
  return False
242
+
160
243
  return True
161
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
+
162
252
 
163
253
  class BaseCallRatePolicy(AbstractCallRatePolicy, abc.ABC):
164
254
  def __init__(self, matchers: list[RequestMatcher]):
@@ -257,6 +347,14 @@ class FixedWindowCallRatePolicy(BaseCallRatePolicy):
257
347
 
258
348
  self._calls_num += weight
259
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
+
260
358
  def update(
261
359
  self, available_calls: Optional[int], call_reset_ts: Optional[datetime.datetime]
262
360
  ) -> None:
@@ -363,6 +461,19 @@ class MovingWindowCallRatePolicy(BaseCallRatePolicy):
363
461
  # if available_calls is not None and call_reset_ts is not None:
364
462
  # ts = call_reset_ts.timestamp()
365
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
+
366
477
 
367
478
  class AbstractAPIBudget(abc.ABC):
368
479
  """Interface to some API where a client allowed to have N calls per T interval.
@@ -415,6 +526,23 @@ class APIBudget(AbstractAPIBudget):
415
526
  self._policies = policies
416
527
  self._maximum_attempts_to_acquire = maximum_attempts_to_acquire
417
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"
545
+
418
546
  def get_matching_policy(self, request: Any) -> Optional[AbstractCallRatePolicy]:
419
547
  for policy in self._policies:
420
548
  if policy.matches(request):
@@ -428,20 +556,24 @@ class APIBudget(AbstractAPIBudget):
428
556
  Matchers will be called sequentially in the same order they were added.
429
557
  The first matcher that returns True will
430
558
 
431
- :param request:
432
- :param block: when true (default) will block the current thread until call credit is available
433
- :param timeout: if provided will limit maximum time in block, otherwise will wait until credit is available
434
- :raises: CallRateLimitHit - when no calls left and if timeout was set the waiting time exceed the timeout
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
435
563
  """
436
564
 
437
565
  policy = self.get_matching_policy(request)
566
+ endpoint = self._extract_endpoint(request)
438
567
  if policy:
568
+ logger.debug(f"Acquiring call for endpoint {endpoint} using policy: {policy}")
439
569
  self._do_acquire(request=request, policy=policy, block=block, timeout=timeout)
440
570
  elif self._policies:
441
- logger.info("no policies matched with requests, allow call by default")
571
+ logger.debug(
572
+ f"No policies matched for endpoint {endpoint} (request: {request}). Allowing call by default."
573
+ )
442
574
 
443
575
  def update_from_response(self, request: Any, response: Any) -> None:
444
- """Update budget information based on response from API
576
+ """Update budget information based on the API response.
445
577
 
446
578
  :param request: the initial request that triggered this response
447
579
  :param response: response from the API
@@ -451,15 +583,17 @@ class APIBudget(AbstractAPIBudget):
451
583
  def _do_acquire(
452
584
  self, request: Any, policy: AbstractCallRatePolicy, block: bool, timeout: Optional[float]
453
585
  ) -> None:
454
- """Internal method to try to acquire a call credit
586
+ """Internal method to try to acquire a call credit.
455
587
 
456
- :param request:
457
- :param policy:
458
- :param block:
459
- :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
460
593
  """
461
594
  last_exception = None
462
- # sometimes we spend all budget before a second attempt, so we have few more here
595
+ endpoint = self._extract_endpoint(request)
596
+ # sometimes we spend all budget before a second attempt, so we have a few more attempts
463
597
  for attempt in range(1, self._maximum_attempts_to_acquire):
464
598
  try:
465
599
  policy.try_acquire(request, weight=1)
@@ -471,20 +605,24 @@ class APIBudget(AbstractAPIBudget):
471
605
  time_to_wait = min(timedelta(seconds=timeout), exc.time_to_wait)
472
606
  else:
473
607
  time_to_wait = exc.time_to_wait
474
-
475
- time_to_wait = max(
476
- timedelta(0), time_to_wait
477
- ) # sometimes we get negative duration
478
- logger.info(
479
- "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}."
480
613
  )
481
614
  time.sleep(time_to_wait.total_seconds())
482
615
  else:
616
+ logger.debug(
617
+ f"Policy {policy} reached call limit for endpoint {endpoint} ({exc.rate}) "
618
+ f"and blocking is disabled."
619
+ )
483
620
  raise
484
621
 
485
622
  if last_exception:
486
- logger.info(
487
- "we used all %s attempts to acquire and failed", self._maximum_attempts_to_acquire
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}"
488
626
  )
489
627
  raise last_exception
490
628
 
@@ -496,7 +634,7 @@ class HttpAPIBudget(APIBudget):
496
634
  self,
497
635
  ratelimit_reset_header: str = "ratelimit-reset",
498
636
  ratelimit_remaining_header: str = "ratelimit-remaining",
499
- status_codes_for_ratelimit_hit: tuple[int] = (429,),
637
+ status_codes_for_ratelimit_hit: list[int] = [429],
500
638
  **kwargs: Any,
501
639
  ):
502
640
  """Constructor
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: airbyte-cdk
3
- Version: 6.33.3
3
+ Version: 6.33.5
4
4
  Summary: A framework for writing Airbyte Connectors.
5
5
  Home-page: https://airbyte.com
6
6
  License: MIT
@@ -7,10 +7,14 @@ airbyte_cdk/config_observation.py,sha256=7SSPxtN0nXPkm4euGNcTTr1iLbwUL01jy-24V1H
7
7
  airbyte_cdk/connector.py,sha256=bO23kdGRkl8XKFytOgrrWFc_VagteTHVEF6IsbizVkM,4224
8
8
  airbyte_cdk/connector_builder/README.md,sha256=Hw3wvVewuHG9-QgsAq1jDiKuLlStDxKBz52ftyNRnBw,1665
9
9
  airbyte_cdk/connector_builder/__init__.py,sha256=4Hw-PX1-VgESLF16cDdvuYCzGJtHntThLF4qIiULWeo,61
10
- airbyte_cdk/connector_builder/connector_builder_handler.py,sha256=CZX1tdWYLdPE_2XtH2KnFNsHrqvWNxsotzTsKii0vrQ,4285
10
+ airbyte_cdk/connector_builder/connector_builder_handler.py,sha256=BntqkP63RBPvGCtB3CrLLtYplfSlBR42kwXyyk4YGas,4268
11
11
  airbyte_cdk/connector_builder/main.py,sha256=ubAPE0Oo5gjZOa-KMtLLJQkc8_inUpFR3sIb2DEh2No,3722
12
- airbyte_cdk/connector_builder/message_grouper.py,sha256=Xckskpqe9kbUByaKVmPsfTKxuyI2FHt8k4NZ4p8xo_I,19813
13
12
  airbyte_cdk/connector_builder/models.py,sha256=uCHpOdJx2PyZtIqk-mt9eSVuFMQoEqrW-9sjCz0Z-AQ,1500
13
+ airbyte_cdk/connector_builder/test_reader/__init__.py,sha256=iTwBMoI9vaJotEgpqZbFjlxRcbxXYypSVJ9YxeHk7wc,120
14
+ airbyte_cdk/connector_builder/test_reader/helpers.py,sha256=niu_EhzwVXnvtzj2Rf_unrxqLRC4Twbe-t17HyNoRJY,23662
15
+ airbyte_cdk/connector_builder/test_reader/message_grouper.py,sha256=L0xKpWQhfRecKblI3uYO9twPTPJYJzlOhK2P8zHWXRU,6487
16
+ airbyte_cdk/connector_builder/test_reader/reader.py,sha256=GurMB4ITO_PntvhIHSJkXbhynLilI4DObY5A2axavXo,20667
17
+ airbyte_cdk/connector_builder/test_reader/types.py,sha256=jP28aOlCS8Q6V7jMksfJKsuAJ-m2dNYiXaUjYvb0DBA,2404
14
18
  airbyte_cdk/destinations/__init__.py,sha256=FyDp28PT_YceJD5HDFhA-mrGfX9AONIyMQ4d68CHNxQ,213
15
19
  airbyte_cdk/destinations/destination.py,sha256=CIq-yb8C_0QvcKCtmStaHfiqn53GEfRAIGGCkJhKP1Q,5880
16
20
  airbyte_cdk/destinations/vector_db_based/README.md,sha256=QAe8c_1Afme4r2TCE10cTSaxUE3zgCBuArSuRQqK8tA,2115
@@ -67,7 +71,7 @@ airbyte_cdk/sources/declarative/concurrent_declarative_source.py,sha256=ThOqmaaq
67
71
  airbyte_cdk/sources/declarative/datetime/__init__.py,sha256=l9LG7Qm6e5r_qgqfVKnx3mXYtg1I9MmMjomVIPfU4XA,177
68
72
  airbyte_cdk/sources/declarative/datetime/datetime_parser.py,sha256=SX9JjdesN1edN2WVUVMzU_ptqp2QB1OnsnjZ4mwcX7w,2579
69
73
  airbyte_cdk/sources/declarative/datetime/min_max_datetime.py,sha256=0BHBtDNQZfvwM45-tY5pNlTcKAFSGGNxemoi0Jic-0E,5785
70
- airbyte_cdk/sources/declarative/declarative_component_schema.yaml,sha256=wmw4ZN8WF_QOWpe7bkzu31VHW-OjKIZ3g7z9nBoDdTo,138922
74
+ airbyte_cdk/sources/declarative/declarative_component_schema.yaml,sha256=LExB78FzoQ1ueR5GRyEO-r4HqdghiywvvfyVUXhvU4I,144561
71
75
  airbyte_cdk/sources/declarative/declarative_source.py,sha256=nF7wBqFd3AQmEKAm4CnIo29CJoQL562cJGSCeL8U8bA,1531
72
76
  airbyte_cdk/sources/declarative/declarative_stream.py,sha256=venZjfpvtqr3oFSuvMBWtn4h9ayLhD4L65ACuXCDZ64,10445
73
77
  airbyte_cdk/sources/declarative/decoders/__init__.py,sha256=JHb_0d3SE6kNY10mxA5YBEKPeSbsWYjByq1gUQxepoE,953
@@ -84,7 +88,7 @@ airbyte_cdk/sources/declarative/extractors/dpath_extractor.py,sha256=wR4Ol4MG2lt
84
88
  airbyte_cdk/sources/declarative/extractors/http_selector.py,sha256=2zWZ4ewTqQC8VwkjS0xD_u350Km3SiYP7hpOOgiLg5o,1169
85
89
  airbyte_cdk/sources/declarative/extractors/record_extractor.py,sha256=XJELMjahAsaomlvQgN2zrNO0DJX0G0fr9r682gUz7Pg,691
86
90
  airbyte_cdk/sources/declarative/extractors/record_filter.py,sha256=yTdEkyDUSW2KbFkEwJJMlS963C955LgCCOVfTmmScpQ,3367
87
- airbyte_cdk/sources/declarative/extractors/record_selector.py,sha256=tjNwcURmlyD-TGCScXvW95ThNKyPGcx2SiWbG1-H-sc,6552
91
+ airbyte_cdk/sources/declarative/extractors/record_selector.py,sha256=HCqx7IyENM_aRF4it2zJN26_vDu6WeP8XgCxQWHUvcY,6934
88
92
  airbyte_cdk/sources/declarative/extractors/response_to_file_extractor.py,sha256=LhqGDfX06_dDYLKsIVnwQ_nAWCln-v8PV7Wgt_QVeTI,6533
89
93
  airbyte_cdk/sources/declarative/extractors/type_transformer.py,sha256=d6Y2Rfg8pMVEEnHllfVksWZdNVOU55yk34O03dP9muY,1626
90
94
  airbyte_cdk/sources/declarative/incremental/__init__.py,sha256=U1oZKtBaEC6IACmvziY9Wzg7Z8EgF4ZuR7NwvjlB_Sk,1255
@@ -104,18 +108,18 @@ airbyte_cdk/sources/declarative/interpolation/interpolated_string.py,sha256=LYEZ
104
108
  airbyte_cdk/sources/declarative/interpolation/interpolation.py,sha256=-V5UddGm69UKEB6o_O1EIES9kfY8FV_X4Ji8w1yOuSA,981
105
109
  airbyte_cdk/sources/declarative/interpolation/jinja.py,sha256=BtsY_jtT4MihFqeQgc05HXj3Ndt-e2ESQgGwbg3Sdxc,6430
106
110
  airbyte_cdk/sources/declarative/interpolation/macros.py,sha256=Y5AWYxbJTUtJ_Jm7DV9qrZDiymFR9LST7fBt4piT2-U,4585
107
- airbyte_cdk/sources/declarative/manifest_declarative_source.py,sha256=26qMXRugdPAd3zyYRH6YpNi--TorGZVOtxzY5O6muL0,16912
111
+ airbyte_cdk/sources/declarative/manifest_declarative_source.py,sha256=TN6GCgLXaWDONTaJwQ3A5ELqC-sxwKz-UYSraJYB-dI,17078
108
112
  airbyte_cdk/sources/declarative/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
109
113
  airbyte_cdk/sources/declarative/migrations/legacy_to_per_partition_state_migration.py,sha256=iemy3fKLczcU0-Aor7tx5jcT6DRedKMqyK7kCOp01hg,3924
110
114
  airbyte_cdk/sources/declarative/migrations/state_migration.py,sha256=KWPjealMLKSMtajXgkdGgKg7EmTLR-CqqD7UIh0-eDU,794
111
115
  airbyte_cdk/sources/declarative/models/__init__.py,sha256=nUFxNCiKeYRVXuZEKA7GD-lTHxsiKcQ8FitZjKhPIvE,100
112
- airbyte_cdk/sources/declarative/models/declarative_component_schema.py,sha256=had38ukkEWp1ShNoGphnYu2dSbxZP6BAymO2Po-ZAvU,98100
116
+ airbyte_cdk/sources/declarative/models/declarative_component_schema.py,sha256=peEl_gQUK6Lu98BntStmtVh0BoBI7OBTUNg9ftMGhEA,101946
113
117
  airbyte_cdk/sources/declarative/parsers/__init__.py,sha256=ZnqYNxHsKCgO38IwB34RQyRMXTs4GTvlRi3ImKnIioo,61
114
118
  airbyte_cdk/sources/declarative/parsers/custom_code_compiler.py,sha256=958MMX6_ZOJUlDDdNr9Krosgi2bCKGx2Z765M2Woz18,5505
115
119
  airbyte_cdk/sources/declarative/parsers/custom_exceptions.py,sha256=Rir9_z3Kcd5Es0-LChrzk-0qubAsiK_RSEnLmK2OXm8,553
116
120
  airbyte_cdk/sources/declarative/parsers/manifest_component_transformer.py,sha256=CXwTfD3wSQq3okcqwigpprbHhSURUokh4GK2OmOyKC8,9132
117
121
  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=rzWM5R9CBwS2Gg-f0Umkk1kq-QBfvXv9NaUHXMLKPKg,128859
122
+ airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py,sha256=YAM05AejFafdtx2deEuxEjU3GtebyYVr-MnsIY8eiZU,133750
119
123
  airbyte_cdk/sources/declarative/partition_routers/__init__.py,sha256=HJ-Syp3p7RpyR_OK0X_a2kSyISfu3W-PKrRI16iY0a8,957
120
124
  airbyte_cdk/sources/declarative/partition_routers/async_job_partition_router.py,sha256=VelO7zKqKtzMJ35jyFeg0ypJLQC0plqqIBNXoBW1G2E,3001
121
125
  airbyte_cdk/sources/declarative/partition_routers/cartesian_product_stream_slicer.py,sha256=c5cuVFM6NFkuQqG8Z5IwkBuwDrvXZN1CunUOM_L0ezg,6892
@@ -139,7 +143,7 @@ airbyte_cdk/sources/declarative/requesters/error_handlers/default_http_response_
139
143
  airbyte_cdk/sources/declarative/requesters/error_handlers/error_handler.py,sha256=Tan66odx8VHzfdyyXMQkXz2pJYksllGqvxmpoajgcK4,669
140
144
  airbyte_cdk/sources/declarative/requesters/error_handlers/http_response_filter.py,sha256=E-fQbt4ShfxZVoqfnmOx69C6FUPWZz8BIqI3DN9Kcjs,7935
141
145
  airbyte_cdk/sources/declarative/requesters/http_job_repository.py,sha256=3GtOefPH08evlSUxaILkiKLTHbIspFY4qd5B3ZqNE60,10063
142
- airbyte_cdk/sources/declarative/requesters/http_requester.py,sha256=C6YT7t4UZMfarFeQ9fc362R5TbQ2jNSew8ESP-9yuZQ,14851
146
+ airbyte_cdk/sources/declarative/requesters/http_requester.py,sha256=Ek5hS60-CYjvEaFD-bI7qA-bPgbOPb9hTbMBU4n5zNs,14994
143
147
  airbyte_cdk/sources/declarative/requesters/paginators/__init__.py,sha256=uArbKs9JKNCt7t9tZoeWwjDpyI1HoPp29FNW0JzvaEM,644
144
148
  airbyte_cdk/sources/declarative/requesters/paginators/default_paginator.py,sha256=dSm_pKGOZjzvg-X_Vif-MjrnlUG23fCa69bocq8dVIs,11693
145
149
  airbyte_cdk/sources/declarative/requesters/paginators/no_pagination.py,sha256=j6j9QRPaTbKQ2N661RFVKthhkWiodEp6ut0tKeEd0Ng,2019
@@ -249,7 +253,7 @@ airbyte_cdk/sources/message/repository.py,sha256=SG7avgti_-dj8FcRHTTrhgLLGJbElv1
249
253
  airbyte_cdk/sources/source.py,sha256=KIBBH5VLEb8BZ8B9aROlfaI6OLoJqKDPMJ10jkAR7nk,3611
250
254
  airbyte_cdk/sources/streams/__init__.py,sha256=8fzTKpRTnSx5PggXgQPKJzHNZUV2BCA40N-dI6JM1xI,256
251
255
  airbyte_cdk/sources/streams/availability_strategy.py,sha256=_RU4JITrxMEN36g1RDHMu0iSw0I_3yWGfo5N8_YRvOg,3247
252
- airbyte_cdk/sources/streams/call_rate.py,sha256=Um_Ny8R7WZ2B0PWoxr-wrWPsgc5we7HrHalaMcozuVs,21052
256
+ airbyte_cdk/sources/streams/call_rate.py,sha256=jRsGp1PDZBCDQNxzcGVnVmVzLk0wLHxS1JnJwMAgy9U,27568
253
257
  airbyte_cdk/sources/streams/checkpoint/__init__.py,sha256=3oy7Hd4ivVWTZlN6dKAf4Fv_G7U5iZrvhO9hT871UIo,712
254
258
  airbyte_cdk/sources/streams/checkpoint/checkpoint_reader.py,sha256=6HMT2NI-FQuaW0nt95NcyWrt5rZN4gF-Arx0sxdgbv4,15221
255
259
  airbyte_cdk/sources/streams/checkpoint/cursor.py,sha256=3e-3c-54k8U7Awno7DMmAD9ndbnl9OM48EnbEgeDUO0,3499
@@ -351,9 +355,9 @@ airbyte_cdk/utils/slice_hasher.py,sha256=EDxgROHDbfG-QKQb59m7h_7crN1tRiawdf5uU7G
351
355
  airbyte_cdk/utils/spec_schema_transformations.py,sha256=-5HTuNsnDBAhj-oLeQXwpTGA0HdcjFOf2zTEMUTTg_Y,816
352
356
  airbyte_cdk/utils/stream_status_utils.py,sha256=ZmBoiy5HVbUEHAMrUONxZvxnvfV9CesmQJLDTAIWnWw,1171
353
357
  airbyte_cdk/utils/traced_exception.py,sha256=C8uIBuCL_E4WnBAOPSxBicD06JAldoN9fGsQDp463OY,6292
354
- airbyte_cdk-6.33.3.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
355
- airbyte_cdk-6.33.3.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
356
- airbyte_cdk-6.33.3.dist-info/METADATA,sha256=9HhcwQNXxm0uygxeyX-dbdTPECBMbnDvXEM561ZP6fQ,6010
357
- airbyte_cdk-6.33.3.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
358
- airbyte_cdk-6.33.3.dist-info/entry_points.txt,sha256=fj-e3PAQvsxsQzyyq8UkG1k8spunWnD4BAH2AwlR6NM,95
359
- airbyte_cdk-6.33.3.dist-info/RECORD,,
358
+ airbyte_cdk-6.33.5.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
359
+ airbyte_cdk-6.33.5.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
360
+ airbyte_cdk-6.33.5.dist-info/METADATA,sha256=sJVXKnOvbWXpBdzmMLW3FiKHhQKlnAbvFF91iwim9lo,6010
361
+ airbyte_cdk-6.33.5.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
362
+ airbyte_cdk-6.33.5.dist-info/entry_points.txt,sha256=fj-e3PAQvsxsQzyyq8UkG1k8spunWnD4BAH2AwlR6NM,95
363
+ airbyte_cdk-6.33.5.dist-info/RECORD,,