airbyte-source-shopify 4.3.0__tar.gz → 4.3.2__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-4.3.0 → airbyte_source_shopify-4.3.2}/PKG-INFO +1 -1
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/pyproject.toml +1 -1
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/http_request.py +22 -1
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/source.py +16 -4
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/streams/streams.py +1 -1
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/utils.py +1 -1
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/.airbyte-pypi-readme.md +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/__init__.py +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/auth.py +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/config_migrations.py +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/run.py +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/abandoned_checkouts.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/articles.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/balance_transactions.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/blogs.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/collection_products.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/collections.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/collects.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/countries.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/custom_collections.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/customer_address.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/customer_journey_summary.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/customers.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/deleted_products.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/discount_codes.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/discount_codes_sync.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/disputes.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/draft_orders.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/fulfillment_orders.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/fulfillments.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/inventory_items.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/inventory_levels.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/locations.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/market_countries.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/metafield_articles.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/metafield_blogs.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/metafield_collections.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/metafield_customers.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/metafield_draft_orders.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/metafield_locations.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/metafield_orders.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/metafield_pages.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/metafield_product_images.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/metafield_product_variants.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/metafield_products.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/metafield_shops.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/metafield_smart_collections.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/order_agreements.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/order_refunds.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/order_risks.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/orders.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/pages.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/price_rules.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/product_images.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/product_variants.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/products.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/profile_location_groups.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/shop.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/smart_collections.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/tender_transactions.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/transactions.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/scopes.py +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/shopify_graphql/bulk/__init__.py +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/shopify_graphql/bulk/exceptions.py +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/shopify_graphql/bulk/external_sort.py +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/shopify_graphql/bulk/job.py +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/shopify_graphql/bulk/query.py +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/shopify_graphql/bulk/record.py +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/shopify_graphql/bulk/retry.py +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/shopify_graphql/bulk/status.py +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/shopify_graphql/bulk/tools.py +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/spec.json +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/streams/base_streams.py +0 -0
- {airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/transform.py +0 -0
|
@@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
|
|
|
3
3
|
build-backend = "poetry.core.masonry.api"
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
|
-
version = "4.3.
|
|
6
|
+
version = "4.3.2"
|
|
7
7
|
name = "airbyte-source-shopify"
|
|
8
8
|
description = "Source CDK implementation for Shopify."
|
|
9
9
|
authors = [ "Airbyte <contact@airbyte.io>",]
|
{airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/http_request.py
RENAMED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
|
|
2
2
|
|
|
3
|
+
import re
|
|
3
4
|
from typing import Optional, Union
|
|
4
5
|
|
|
5
6
|
import requests
|
|
6
7
|
from requests import exceptions
|
|
7
8
|
|
|
8
9
|
from airbyte_cdk.models import FailureType
|
|
9
|
-
from airbyte_cdk.sources.streams.http.error_handlers import ErrorHandler, ErrorResolution, ResponseAction
|
|
10
|
+
from airbyte_cdk.sources.streams.http.error_handlers import ErrorHandler, ErrorResolution, HttpStatusErrorHandler, ResponseAction
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
RESPONSE_CONSUMPTION_EXCEPTIONS = (
|
|
@@ -26,6 +27,26 @@ TRANSIENT_EXCEPTIONS = (
|
|
|
26
27
|
_NO_ERROR_RESOLUTION = ErrorResolution(ResponseAction.SUCCESS, None, None)
|
|
27
28
|
|
|
28
29
|
|
|
30
|
+
class ShopifyConnectionCheckErrorHandler(HttpStatusErrorHandler):
|
|
31
|
+
def interpret_response(self, response: Optional[Union[requests.Response, Exception]]) -> ErrorResolution:
|
|
32
|
+
if isinstance(response, requests.Response):
|
|
33
|
+
if response.status_code == 401:
|
|
34
|
+
return ErrorResolution(
|
|
35
|
+
ResponseAction.FAIL,
|
|
36
|
+
FailureType.config_error,
|
|
37
|
+
"Shopify authentication failed: the access token is invalid or revoked. Re-authenticate the source or regenerate the Admin API access token.",
|
|
38
|
+
)
|
|
39
|
+
if response.status_code == 403:
|
|
40
|
+
scopes = sorted(set(re.findall(r"\b(?:read|write)_[a-z_]+\b", response.text)))
|
|
41
|
+
required = f" ({', '.join(scopes)})" if scopes else ""
|
|
42
|
+
return ErrorResolution(
|
|
43
|
+
ResponseAction.FAIL,
|
|
44
|
+
FailureType.config_error,
|
|
45
|
+
f"Shopify access is denied. Grant the app the required access scopes{required}, then re-authorize the source or regenerate the Admin API access token.",
|
|
46
|
+
)
|
|
47
|
+
return super().interpret_response(response)
|
|
48
|
+
|
|
49
|
+
|
|
29
50
|
class ShopifyErrorHandler(ErrorHandler):
|
|
30
51
|
def __init__(self, stream_name: str = "<no specified stream>") -> None:
|
|
31
52
|
self._stream_name = stream_name
|
|
@@ -13,10 +13,12 @@ from requests.exceptions import ConnectionError, RequestException, SSLError
|
|
|
13
13
|
from airbyte_cdk.models import FailureType, SyncMode
|
|
14
14
|
from airbyte_cdk.sources import AbstractSource
|
|
15
15
|
from airbyte_cdk.sources.streams import Stream
|
|
16
|
+
from airbyte_cdk.sources.streams.http.error_handlers.default_error_mapping import DEFAULT_ERROR_MAPPING
|
|
16
17
|
from airbyte_cdk.sources.streams.http.exceptions import BaseBackoffException
|
|
17
18
|
from airbyte_cdk.utils import AirbyteTracedException
|
|
18
19
|
|
|
19
20
|
from .auth import MissingAccessTokenError, ShopifyAuthenticator
|
|
21
|
+
from .http_request import ShopifyConnectionCheckErrorHandler
|
|
20
22
|
from .scopes import ShopifyScopes
|
|
21
23
|
from .streams.streams import (
|
|
22
24
|
AbandonedCheckouts,
|
|
@@ -71,7 +73,7 @@ from .streams.streams import (
|
|
|
71
73
|
Transactions,
|
|
72
74
|
TransactionsGraphql,
|
|
73
75
|
)
|
|
74
|
-
from .utils import ShopifyWrongShopNameError
|
|
76
|
+
from .utils import ShopifyNonRetryableErrors, ShopifyWrongShopNameError
|
|
75
77
|
|
|
76
78
|
|
|
77
79
|
class ConnectionCheckTest:
|
|
@@ -79,6 +81,9 @@ class ConnectionCheckTest:
|
|
|
79
81
|
self.config = config
|
|
80
82
|
# use `Shop` as a test stream for connection check
|
|
81
83
|
self.test_stream = Shop(self.config)
|
|
84
|
+
self.test_stream._http_client._error_handler = ShopifyConnectionCheckErrorHandler(
|
|
85
|
+
self.test_stream.logger, error_mapping=DEFAULT_ERROR_MAPPING | ShopifyNonRetryableErrors(self.test_stream.name)
|
|
86
|
+
)
|
|
82
87
|
# setting `max_retries` to 0 for the stage of `check connection`,
|
|
83
88
|
# because it keeps retrying for wrong shop names,
|
|
84
89
|
# but it should stop immediately
|
|
@@ -115,7 +120,11 @@ class ConnectionCheckTest:
|
|
|
115
120
|
return False, self.describe_error("index_error", shop_name, response)
|
|
116
121
|
except MissingAccessTokenError:
|
|
117
122
|
return False, self.describe_error("missing_token_error")
|
|
118
|
-
except
|
|
123
|
+
except AirbyteTracedException as error:
|
|
124
|
+
if error.failure_type == FailureType.config_error:
|
|
125
|
+
raise
|
|
126
|
+
return False, self.describe_error("connection_error", shop_name)
|
|
127
|
+
except BaseBackoffException as error:
|
|
119
128
|
return False, self.describe_error("connection_error", shop_name) or str(error)
|
|
120
129
|
|
|
121
130
|
def get_shop_id(self) -> str:
|
|
@@ -161,9 +170,12 @@ class SourceShopify(AbstractSource):
|
|
|
161
170
|
# If a scheme is present, parse out the host; urlparse only fills netloc
|
|
162
171
|
# when "://" is present.
|
|
163
172
|
if "://" in value:
|
|
164
|
-
|
|
173
|
+
try:
|
|
174
|
+
parsed = urlparse(value)
|
|
175
|
+
except ValueError:
|
|
176
|
+
raise ShopifyWrongShopNameError(raw)
|
|
165
177
|
host = parsed.netloc
|
|
166
|
-
if parsed.path not in ("", "/") or parsed.params or parsed.query or parsed.fragment:
|
|
178
|
+
if parsed.scheme not in ("http", "https") or parsed.path not in ("", "/") or parsed.params or parsed.query or parsed.fragment:
|
|
167
179
|
raise ShopifyWrongShopNameError(raw)
|
|
168
180
|
else:
|
|
169
181
|
host, _, path = value.partition("/")
|
{airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/streams/streams.py
RENAMED
|
@@ -238,7 +238,7 @@ class DeletedProducts(IncrementalShopifyStream):
|
|
|
238
238
|
query_filter = "action:destroy AND subject_type:Product"
|
|
239
239
|
if stream_state and stream_state.get(self.cursor_field):
|
|
240
240
|
state_value = stream_state[self.cursor_field]
|
|
241
|
-
query_filter += f" AND created_at
|
|
241
|
+
query_filter += f" AND created_at:>='{state_value}'"
|
|
242
242
|
|
|
243
243
|
variables = {
|
|
244
244
|
"first": 250,
|
|
@@ -81,7 +81,7 @@ class ShopifyWrongShopNameError(AirbyteTracedException):
|
|
|
81
81
|
"""Raises the error when `Shopify Store` name is incorrect or couldn't be verified by the Shopify"""
|
|
82
82
|
|
|
83
83
|
def __init__(self, url, **kwargs) -> None:
|
|
84
|
-
self.message =
|
|
84
|
+
self.message = "The Shopify Store name is invalid or missing. Enter the store handle or its myshopify.com domain, without paths, credentials, query strings, or fragments."
|
|
85
85
|
super().__init__(message=self.message, internal_message=self.message, failure_type=FailureType.config_error, **kwargs)
|
|
86
86
|
|
|
87
87
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/config_migrations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/articles.json
RENAMED
|
File without changes
|
|
File without changes
|
{airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/blogs.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/collects.json
RENAMED
|
File without changes
|
{airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/countries.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/customers.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/disputes.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/locations.json
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
|
{airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/orders.json
RENAMED
|
File without changes
|
{airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/pages.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/products.json
RENAMED
|
File without changes
|
|
File without changes
|
{airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/schemas/shop.json
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
|
{airbyte_source_shopify-4.3.0 → airbyte_source_shopify-4.3.2}/source_shopify/streams/base_streams.py
RENAMED
|
File without changes
|
|
File without changes
|