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.
@@ -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, Union
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 http requests case"""
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
- self._method = method
120
- self._url = url
121
- self._params = {str(k): str(v) for k, v in (params or {}).items()}
122
- self._headers = {str(k): str(v) for k, v in (headers or {}).items()}
123
-
124
- @staticmethod
125
- def _match_dict(obj: Mapping[str, Any], pattern: Mapping[str, Any]) -> bool:
126
- """Check that all elements from pattern dict present and have the same values in obj dict
127
-
128
- :param obj:
129
- :param pattern:
130
- :return:
131
- """
132
- return pattern.items() <= obj.items()
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
- :param request:
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
- if isinstance(request, requests.Request):
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
- if self._method is not None:
148
- if prepared_request.method != self._method:
149
- return False
150
- if self._url is not None and prepared_request.url is not None:
151
- url_without_params = prepared_request.url.split("?")[0]
152
- if url_without_params != self._url:
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 and prepared_request.method is not None:
224
- if prepared_request.method.upper() != self._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
- Default APIBudget implementation.
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
- policies: list[AbstractCallRatePolicy]
505
- maximum_attempts_to_acquire: int = 100000
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.policies:
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 true (default) will block the current thread until call credit is available
522
- :param timeout: if provided will limit maximum time in block, otherwise will wait until credit is available
523
- :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
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.policies:
530
- logger.info("no policies matched with requests, allow call by default")
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 response from API
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
- # sometimes we spend all budget before a second attempt, so we have few more here
552
- for attempt in range(1, self.maximum_attempts_to_acquire):
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
- timedelta(0), time_to_wait
566
- ) # sometimes we get negative duration
567
- logger.info(
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.info(
576
- "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}"
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
- ratelimit_reset_header: str = "ratelimit-reset"
586
- ratelimit_remaining_header: str = "ratelimit-remaining"
587
- status_codes_for_ratelimit_hit: Union[tuple[int], list[int]] = (429,)
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.ratelimit_reset_header):
664
+ if response.headers.get(self._ratelimit_reset_header):
603
665
  return datetime.datetime.fromtimestamp(
604
- int(response.headers[self.ratelimit_reset_header])
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.ratelimit_remaining_header):
610
- return int(response.headers[self.ratelimit_remaining_header])
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.status_codes_for_ratelimit_hit:
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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: airbyte-cdk
3
- Version: 6.33.2.dev1
3
+ Version: 6.33.4
4
4
  Summary: A framework for writing Airbyte Connectors.
5
5
  Home-page: https://airbyte.com
6
6
  License: MIT
@@ -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=fibXa-dqtM54jIUscWbz7DEA5uY6F2o1LfARjEeGRy0,13926
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=7uqf_zQd2T08AYdMDJ80Zt0W1QHqZd-dvltXC-3g8W4,28136
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=_pL5eEPf9N7U5kyzfB6YJG2xUHAPNTrJSApLYlQS9vw,147556
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=KSpQetKGqPCv-38QgcVJ5kzM5nzbFldTSsYDCS3Xf0Y,1035
74
- airbyte_cdk/sources/declarative/decoders/composite_raw_decoder.py,sha256=kQfUVMVhChKe5OngwIQrs0F9KGnRUN-CKVFakCU23DQ,4354
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=qdbjeR6RffKaah_iWvMsOcDolYuxJY5DaI3b9AMTZXg,3327
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=tjNwcURmlyD-TGCScXvW95ThNKyPGcx2SiWbG1-H-sc,6552
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=Kq65fkrRpdrMzve0mfzGbrmTuAAd0wgJ8IsVS9_2xxs,18027
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=4C2CQ3IkDI39X0Pkf5j-X5pfKUVTrfwjy6wAJoaI6cE,104148
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=xbGhVLZZGnXA2-W6ajv1v8pJl-L-5RdLcRQI77gF4CQ,134141
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=WHMJ0-8xf0w_DiI0RkhPA8KEaPzaojNb23AEnKfcuS4,23939
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=n-jlPNcUtZkDv3hQEGqTzqVFuF0hbWHkru-po3ResFU,18596
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.2.dev1.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
355
- airbyte_cdk-6.33.2.dev1.dist-info/LICENSE_SHORT,sha256=aqF6D1NcESmpn-cqsxBtszTEnHKnlsp8L4x9wAh3Nxg,55
356
- airbyte_cdk-6.33.2.dev1.dist-info/METADATA,sha256=qvK3tE9g4JSrvCgeYU_YtD-sLXK1P-dlhgatt7U7sCA,6015
357
- airbyte_cdk-6.33.2.dev1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
358
- airbyte_cdk-6.33.2.dev1.dist-info/entry_points.txt,sha256=fj-e3PAQvsxsQzyyq8UkG1k8spunWnD4BAH2AwlR6NM,95
359
- airbyte_cdk-6.33.2.dev1.dist-info/RECORD,,
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,,