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.
Files changed (69) hide show
  1. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/PKG-INFO +1 -1
  2. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/pyproject.toml +1 -1
  3. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/spec.json +2 -4
  4. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/streams/streams.py +17 -3
  5. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/utils.py +38 -1
  6. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/README.md +0 -0
  7. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/__init__.py +0 -0
  8. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/auth.py +0 -0
  9. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/config_migrations.py +0 -0
  10. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/http_request.py +0 -0
  11. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/run.py +0 -0
  12. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/abandoned_checkouts.json +0 -0
  13. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/articles.json +0 -0
  14. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/balance_transactions.json +0 -0
  15. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/blogs.json +0 -0
  16. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/collections.json +0 -0
  17. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/collects.json +0 -0
  18. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/countries.json +0 -0
  19. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/custom_collections.json +0 -0
  20. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/customer_address.json +0 -0
  21. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/customer_journey_summary.json +0 -0
  22. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/customers.json +0 -0
  23. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/discount_codes.json +0 -0
  24. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/disputes.json +0 -0
  25. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/draft_orders.json +0 -0
  26. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/fulfillment_orders.json +0 -0
  27. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/fulfillments.json +0 -0
  28. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/inventory_items.json +0 -0
  29. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/inventory_levels.json +0 -0
  30. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/locations.json +0 -0
  31. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_articles.json +0 -0
  32. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_blogs.json +0 -0
  33. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_collections.json +0 -0
  34. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_customers.json +0 -0
  35. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_draft_orders.json +0 -0
  36. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_locations.json +0 -0
  37. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_orders.json +0 -0
  38. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_pages.json +0 -0
  39. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_product_images.json +0 -0
  40. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_product_variants.json +0 -0
  41. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_products.json +0 -0
  42. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_shops.json +0 -0
  43. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/metafield_smart_collections.json +0 -0
  44. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/order_agreements.json +0 -0
  45. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/order_refunds.json +0 -0
  46. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/order_risks.json +0 -0
  47. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/orders.json +0 -0
  48. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/pages.json +0 -0
  49. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/price_rules.json +0 -0
  50. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/product_images.json +0 -0
  51. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/product_variants.json +0 -0
  52. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/products.json +0 -0
  53. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/profile_location_groups.json +0 -0
  54. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/shop.json +0 -0
  55. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/smart_collections.json +0 -0
  56. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/tender_transactions.json +0 -0
  57. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/schemas/transactions.json +0 -0
  58. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/scopes.py +0 -0
  59. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/__init__.py +0 -0
  60. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/exceptions.py +0 -0
  61. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/job.py +0 -0
  62. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/query.py +0 -0
  63. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/record.py +0 -0
  64. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/retry.py +0 -0
  65. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/status.py +0 -0
  66. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/shopify_graphql/bulk/tools.py +0 -0
  67. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/source.py +0 -0
  68. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/streams/base_streams.py +0 -0
  69. {airbyte_source_shopify-3.0.6.dev202504252338 → airbyte_source_shopify-3.0.7}/source_shopify/transform.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: airbyte-source-shopify
3
- Version: 3.0.6.dev202504252338
3
+ Version: 3.0.7
4
4
  Summary: Source CDK implementation for Shopify.
5
5
  License: ELv2
6
6
  Author: Airbyte
@@ -5,7 +5,7 @@ requires = [
5
5
  build-backend = "poetry.core.masonry.api"
6
6
 
7
7
  [tool.poetry]
8
- version = "3.0.6.dev202504252338"
8
+ version = "3.0.7"
9
9
  name = "airbyte-source-shopify"
10
10
  description = "Source CDK implementation for Shopify."
11
11
  authors = [
@@ -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 request_params(
89
- self, stream_state: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None, **kwargs
90
- ) -> MutableMapping[str, Any]:
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)