airbyte-source-shopify 3.0.6.dev202504252338__tar.gz → 3.0.7__tar.gz
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_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/PKG-INFO +1 -1
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/pyproject.toml +1 -1
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/spec.json +2 -4
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/streams/streams.py +17 -3
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/utils.py +38 -1
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/README.md +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/__init__.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/auth.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/config_migrations.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/http_request.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/run.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/abandoned_checkouts.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/articles.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/balance_transactions.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/blogs.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/collections.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/collects.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/countries.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/custom_collections.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/customer_address.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/customer_journey_summary.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/customers.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/discount_codes.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/disputes.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/draft_orders.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/fulfillment_orders.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/fulfillments.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/inventory_items.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/inventory_levels.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/locations.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_articles.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_blogs.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_collections.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_customers.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_draft_orders.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_locations.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_orders.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_pages.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_product_images.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_product_variants.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_products.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_shops.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_smart_collections.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/order_agreements.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/order_refunds.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/order_risks.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/orders.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/pages.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/price_rules.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/product_images.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/product_variants.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/products.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/profile_location_groups.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/shop.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/smart_collections.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/tender_transactions.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/transactions.json +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/scopes.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/__init__.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/exceptions.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/job.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/query.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/record.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/retry.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/status.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/tools.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/source.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/streams/base_streams.py +0 -0
- {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/transform.py +0 -0
|
@@ -13,8 +13,7 @@
|
|
|
13
13
|
"description": "The name of your Shopify store found in the URL. For example, if your URL was https://NAME.myshopify.com, then the name would be 'NAME' or 'NAME.myshopify.com'.",
|
|
14
14
|
"pattern": "^(?!https://)(?!https://).*",
|
|
15
15
|
"examples": ["my-store", "my-store.myshopify.com"],
|
|
16
|
-
"order": 1
|
|
17
|
-
"airbyte_hidden": true
|
|
16
|
+
"order": 1
|
|
18
17
|
},
|
|
19
18
|
"credentials": {
|
|
20
19
|
"title": "Shopify Authorization Method",
|
|
@@ -74,8 +73,7 @@
|
|
|
74
73
|
"airbyte_secret": true,
|
|
75
74
|
"order": 1
|
|
76
75
|
}
|
|
77
|
-
}
|
|
78
|
-
"airbyte_hidden": true
|
|
76
|
+
}
|
|
79
77
|
}
|
|
80
78
|
]
|
|
81
79
|
},
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
import logging
|
|
6
7
|
from typing import Any, Iterable, Mapping, MutableMapping, Optional
|
|
7
8
|
|
|
8
9
|
import requests
|
|
@@ -31,9 +32,12 @@ from source_shopify.shopify_graphql.bulk.query import (
|
|
|
31
32
|
ProfileLocationGroups,
|
|
32
33
|
Transaction,
|
|
33
34
|
)
|
|
35
|
+
from source_shopify.utils import LimitReducingErrorHandler, ShopifyNonRetryableErrors
|
|
34
36
|
|
|
35
37
|
from airbyte_cdk import HttpSubStream
|
|
36
38
|
from airbyte_cdk.sources.streams.core import package_name_from_class
|
|
39
|
+
from airbyte_cdk.sources.streams.http.error_handlers import ErrorHandler
|
|
40
|
+
from airbyte_cdk.sources.streams.http.error_handlers.default_error_mapping import DEFAULT_ERROR_MAPPING
|
|
37
41
|
from airbyte_cdk.sources.utils.schema_helpers import ResourceSchemaLoader
|
|
38
42
|
|
|
39
43
|
from .base_streams import (
|
|
@@ -84,15 +88,25 @@ class MetafieldCustomers(IncrementalShopifyGraphQlBulkStream):
|
|
|
84
88
|
class Orders(IncrementalShopifyStreamWithDeletedEvents):
|
|
85
89
|
data_field = "orders"
|
|
86
90
|
deleted_events_api_name = "Order"
|
|
91
|
+
initial_limit = 250
|
|
87
92
|
|
|
88
|
-
def
|
|
89
|
-
self
|
|
90
|
-
|
|
93
|
+
def __init__(self, config: Mapping[str, Any]):
|
|
94
|
+
self._error_handler = LimitReducingErrorHandler(
|
|
95
|
+
max_retries=5,
|
|
96
|
+
error_mapping=DEFAULT_ERROR_MAPPING | ShopifyNonRetryableErrors("orders"),
|
|
97
|
+
)
|
|
98
|
+
super().__init__(config)
|
|
99
|
+
|
|
100
|
+
def request_params(self, stream_state=None, next_page_token=None, **kwargs):
|
|
91
101
|
params = super().request_params(stream_state=stream_state, next_page_token=next_page_token, **kwargs)
|
|
102
|
+
params["limit"] = self.initial_limit # Always start with the default limit; error handler will mutate on retry
|
|
92
103
|
if not next_page_token:
|
|
93
104
|
params["status"] = "any"
|
|
94
105
|
return params
|
|
95
106
|
|
|
107
|
+
def get_error_handler(self):
|
|
108
|
+
return self._error_handler
|
|
109
|
+
|
|
96
110
|
|
|
97
111
|
class Disputes(IncrementalShopifyStream):
|
|
98
112
|
data_field = "disputes"
|
|
@@ -7,11 +7,13 @@ import enum
|
|
|
7
7
|
import logging
|
|
8
8
|
from functools import wraps
|
|
9
9
|
from time import sleep
|
|
10
|
-
from typing import Any, Callable, Dict, Final, List, Mapping, Optional
|
|
10
|
+
from typing import Any, Callable, Dict, Final, List, Mapping, Optional, Union
|
|
11
|
+
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
|
|
11
12
|
|
|
12
13
|
import requests
|
|
13
14
|
|
|
14
15
|
from airbyte_cdk.models import FailureType
|
|
16
|
+
from airbyte_cdk.sources.streams.http.error_handlers import HttpStatusErrorHandler
|
|
15
17
|
from airbyte_cdk.sources.streams.http.error_handlers.response_models import ErrorResolution, ResponseAction
|
|
16
18
|
from airbyte_cdk.utils import AirbyteTracedException
|
|
17
19
|
|
|
@@ -323,3 +325,38 @@ class EagerlyCachedStreamState:
|
|
|
323
325
|
return func(*args, **kwargs)
|
|
324
326
|
|
|
325
327
|
return decorator
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
class LimitReducingErrorHandler(HttpStatusErrorHandler):
|
|
331
|
+
"""
|
|
332
|
+
Error handler that halves the page size (limit) on each 500 error, down to 1.
|
|
333
|
+
No stream instance required; operates directly on the request URL.
|
|
334
|
+
"""
|
|
335
|
+
|
|
336
|
+
def __init__(self, max_retries: int, error_mapping: dict):
|
|
337
|
+
super().__init__(logger=None, max_retries=max_retries, error_mapping=error_mapping)
|
|
338
|
+
|
|
339
|
+
def interpret_response(self, response_or_exception: Optional[Union[requests.Response, Exception]] = None) -> ErrorResolution:
|
|
340
|
+
if isinstance(response_or_exception, requests.Response):
|
|
341
|
+
response = response_or_exception
|
|
342
|
+
if response.status_code == 500:
|
|
343
|
+
# Extract current limit from the URL, default to 250 if not present
|
|
344
|
+
parsed = urlparse(response.request.url)
|
|
345
|
+
query = parse_qs(parsed.query)
|
|
346
|
+
current_limit = int(query.get("limit", ["250"])[0])
|
|
347
|
+
if current_limit > 1:
|
|
348
|
+
new_limit = max(1, current_limit // 2)
|
|
349
|
+
query["limit"] = [str(new_limit)]
|
|
350
|
+
new_query = urlencode(query, doseq=True)
|
|
351
|
+
response.request.url = urlunparse(parsed._replace(query=new_query))
|
|
352
|
+
return ErrorResolution(
|
|
353
|
+
response_action=ResponseAction.RETRY,
|
|
354
|
+
failure_type=FailureType.transient_error,
|
|
355
|
+
error_message=f"Server error 500: Reduced limit to {new_limit} and updating request URL",
|
|
356
|
+
)
|
|
357
|
+
return ErrorResolution(
|
|
358
|
+
response_action=ResponseAction.FAIL,
|
|
359
|
+
failure_type=FailureType.transient_error,
|
|
360
|
+
error_message="Persistent 500 error after reducing limit to 1",
|
|
361
|
+
)
|
|
362
|
+
return super().interpret_response(response_or_exception)
|
|
File without changes
|
|
File without changes
|
{airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/auth.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/run.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|