lib-shopify-graphql 2.0.0__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.
Files changed (63) hide show
  1. lib_shopify_graphql/__init__.py +356 -0
  2. lib_shopify_graphql/__init__conf__.py +74 -0
  3. lib_shopify_graphql/__main__.py +113 -0
  4. lib_shopify_graphql/_compat.py +32 -0
  5. lib_shopify_graphql/adapters/__init__.py +68 -0
  6. lib_shopify_graphql/adapters/cache_json.py +331 -0
  7. lib_shopify_graphql/adapters/cache_mysql.py +530 -0
  8. lib_shopify_graphql/adapters/constants.py +165 -0
  9. lib_shopify_graphql/adapters/location_resolver.py +165 -0
  10. lib_shopify_graphql/adapters/mutations.py +604 -0
  11. lib_shopify_graphql/adapters/parsers.py +1112 -0
  12. lib_shopify_graphql/adapters/queries.py +439 -0
  13. lib_shopify_graphql/adapters/shopify_sdk.py +317 -0
  14. lib_shopify_graphql/adapters/sku_resolver.py +492 -0
  15. lib_shopify_graphql/adapters/token_cache.py +250 -0
  16. lib_shopify_graphql/application/__init__.py +29 -0
  17. lib_shopify_graphql/application/ports.py +322 -0
  18. lib_shopify_graphql/cli/__init__.py +231 -0
  19. lib_shopify_graphql/cli/_cache.py +566 -0
  20. lib_shopify_graphql/cli/_common.py +384 -0
  21. lib_shopify_graphql/cli/_config.py +192 -0
  22. lib_shopify_graphql/cli/_health.py +332 -0
  23. lib_shopify_graphql/cli/_images.py +362 -0
  24. lib_shopify_graphql/cli/_products.py +751 -0
  25. lib_shopify_graphql/cli/_test_limits.py +355 -0
  26. lib_shopify_graphql/composition.py +482 -0
  27. lib_shopify_graphql/config.py +119 -0
  28. lib_shopify_graphql/config_deploy.py +112 -0
  29. lib_shopify_graphql/config_show.py +124 -0
  30. lib_shopify_graphql/defaultconfig.d/10-logging.toml +417 -0
  31. lib_shopify_graphql/defaultconfig.d/20-shopify.toml +47 -0
  32. lib_shopify_graphql/defaultconfig.d/30-mysql.toml +84 -0
  33. lib_shopify_graphql/defaultconfig.d/40-token-cache.toml +66 -0
  34. lib_shopify_graphql/defaultconfig.d/50-sku-cache.toml +69 -0
  35. lib_shopify_graphql/defaultconfig.d/60-graphql.toml +118 -0
  36. lib_shopify_graphql/defaultconfig.toml +56 -0
  37. lib_shopify_graphql/domain/__init__.py +22 -0
  38. lib_shopify_graphql/enums.py +70 -0
  39. lib_shopify_graphql/exceptions.py +327 -0
  40. lib_shopify_graphql/logging_setup.py +96 -0
  41. lib_shopify_graphql/models/__init__.py +150 -0
  42. lib_shopify_graphql/models/_entities.py +440 -0
  43. lib_shopify_graphql/models/_enums.py +285 -0
  44. lib_shopify_graphql/models/_images.py +277 -0
  45. lib_shopify_graphql/models/_internal.py +114 -0
  46. lib_shopify_graphql/models/_mutations.py +294 -0
  47. lib_shopify_graphql/models/_operations.py +752 -0
  48. lib_shopify_graphql/py.typed +0 -0
  49. lib_shopify_graphql/shopify_client/__init__.py +113 -0
  50. lib_shopify_graphql/shopify_client/_cache.py +297 -0
  51. lib_shopify_graphql/shopify_client/_common.py +208 -0
  52. lib_shopify_graphql/shopify_client/_images.py +726 -0
  53. lib_shopify_graphql/shopify_client/_inventory.py +292 -0
  54. lib_shopify_graphql/shopify_client/_metafields.py +308 -0
  55. lib_shopify_graphql/shopify_client/_products.py +903 -0
  56. lib_shopify_graphql/shopify_client/_session.py +349 -0
  57. lib_shopify_graphql/shopify_client/_variants.py +253 -0
  58. lib_shopify_graphql/shopify_client/_variants_bulk.py +235 -0
  59. lib_shopify_graphql-2.0.0.dist-info/METADATA +321 -0
  60. lib_shopify_graphql-2.0.0.dist-info/RECORD +63 -0
  61. lib_shopify_graphql-2.0.0.dist-info/WHEEL +4 -0
  62. lib_shopify_graphql-2.0.0.dist-info/entry_points.txt +3 -0
  63. lib_shopify_graphql-2.0.0.dist-info/licenses/LICENSE +22 -0
@@ -0,0 +1,356 @@
1
+ """Public package surface for lib_shopify_graphql.
2
+
3
+ This package provides a Python interface for the Shopify GraphQL Admin API.
4
+
5
+ Architecture:
6
+ This library follows Clean Architecture principles:
7
+ - **Domain**: Pure exceptions and business rules
8
+ - **Application**: Use cases and ports (Protocol interfaces)
9
+ - **Adapters**: Shopify SDK implementations
10
+ - **Composition**: Wiring adapters to ports
11
+
12
+ Core API:
13
+ - :func:`login`: Authenticate with Shopify using client credentials grant.
14
+ - :func:`logout`: Terminate an active Shopify session.
15
+ - :func:`get_product_by_id`: Retrieve full product information.
16
+ - :func:`create_product`: Create a new product.
17
+ - :func:`duplicate_product`: Duplicate an existing product.
18
+ - :func:`delete_product`: Delete a product permanently.
19
+ - :func:`update_product`: Update product fields (partial update).
20
+ - :func:`update_variant`: Update variant fields (partial update).
21
+ - :func:`update_variants_bulk`: Bulk update multiple variants.
22
+ - :func:`set_inventory`: Set absolute inventory quantity.
23
+ - :func:`adjust_inventory`: Adjust inventory by delta.
24
+ - :func:`delete_metafield`: Delete a single metafield.
25
+ - :func:`delete_metafields`: Delete multiple metafields.
26
+ - :func:`tokencache_clear`: Clear cached OAuth tokens.
27
+ - :func:`skucache_clear`: Clear cached SKU-to-GID mappings.
28
+ - :func:`cache_clear_all`: Clear all caches (tokens and SKU mappings).
29
+
30
+ Models:
31
+ - :class:`ShopifyCredentials`: Credentials for authentication.
32
+ - :class:`ShopifySession`: Active session wrapper.
33
+ - :class:`Product`: Full product data.
34
+ - :class:`ProductVariant`: Product variant data.
35
+ - :class:`ProductImage`: Product image data.
36
+ - :class:`ProductOption`: Product option definition.
37
+ - :class:`Money`: Monetary value with currency.
38
+ - :class:`PriceRange`: Min/max price range.
39
+ - :class:`SEO`: Search engine optimization data.
40
+ - :class:`Metafield`: Custom metadata attached to resources.
41
+
42
+ Product Creation Model:
43
+ - :class:`ProductCreate`: Input model for creating a new product.
44
+
45
+ Product Lifecycle Results:
46
+ - :class:`DuplicateProductResult`: Result of duplicating a product.
47
+ - :class:`DeleteProductResult`: Result of deleting a product.
48
+
49
+ Partial Update Models:
50
+ - :data:`UNSET`: Sentinel indicating field should not be updated.
51
+ - :class:`ProductUpdate`: Partial update for product fields.
52
+ - :class:`VariantUpdate`: Partial update for variant fields.
53
+ - :class:`VariantUpdateRequest`: Update request with flexible identifier.
54
+ - :class:`BulkUpdateResult`: Result of bulk update operations.
55
+ - :class:`InventoryLevel`: Inventory level at a location.
56
+
57
+ Metafield Deletion Models:
58
+ - :class:`MetafieldIdentifier`: Identifies a metafield for deletion.
59
+ - :class:`MetafieldDeleteResult`: Result of metafield deletion.
60
+ - :class:`MetafieldDeleteFailure`: A failed metafield deletion.
61
+
62
+ Exceptions:
63
+ - :class:`ShopifyError`: Base exception for all Shopify operations.
64
+ - :class:`AuthenticationError`: Authentication failed.
65
+ - :class:`ProductNotFoundError`: Product not found.
66
+ - :class:`VariantNotFoundError`: Variant not found.
67
+ - :class:`AmbiguousSKUError`: SKU matches multiple variants.
68
+ - :class:`SessionNotActiveError`: Session not active.
69
+ - :class:`GraphQLError`: GraphQL query errors.
70
+
71
+ Ports (for dependency injection):
72
+ - :class:`TokenProviderPort`: OAuth token provider interface.
73
+ - :class:`GraphQLClientPort`: GraphQL client interface.
74
+ - :class:`SessionManagerPort`: Session manager interface.
75
+ - :class:`CachePort`: Key-value cache interface.
76
+ - :class:`SKUResolverPort`: SKU to GID resolver interface.
77
+ - :class:`LocationResolverPort`: Location resolver interface.
78
+
79
+ Adapters:
80
+ - :class:`JsonFileCacheAdapter`: JSON file cache with filelock.
81
+ - :class:`MySQLCacheAdapter`: MySQL-based cache.
82
+ - :class:`CachedSKUResolver`: Cached SKU resolver implementation.
83
+ - :class:`LocationResolver`: Location resolver with fallback.
84
+
85
+ Utilities:
86
+ - :func:`get_config`: Load layered configuration.
87
+ - :func:`print_info`: Display package metadata.
88
+ - :func:`create_adapters`: Create adapter bundle for DI.
89
+ """
90
+
91
+ from __future__ import annotations
92
+
93
+ # Package metadata
94
+ from .__init__conf__ import print_info
95
+
96
+ # Adapters
97
+ from .adapters import (
98
+ DEFAULT_GRAPHQL_TIMEOUT_SECONDS,
99
+ PYMYSQL_AVAILABLE,
100
+ CachedSKUResolver,
101
+ CachedTokenProvider,
102
+ JsonFileCacheAdapter,
103
+ LocationResolver,
104
+ MySQLCacheAdapter,
105
+ )
106
+
107
+ # Application ports (for dependency injection)
108
+ from .application.ports import (
109
+ CachePort,
110
+ GraphQLClientPort,
111
+ LocationResolverPort,
112
+ SessionManagerPort,
113
+ SKUResolverPort,
114
+ TokenProviderPort,
115
+ )
116
+
117
+ # Composition root
118
+ from .composition import (
119
+ AdapterBundle,
120
+ create_adapters,
121
+ create_cached_token_provider,
122
+ get_default_adapters,
123
+ )
124
+
125
+ # Configuration
126
+ from .config import get_config
127
+
128
+ # Domain exceptions
129
+ from .exceptions import (
130
+ AmbiguousSKUError,
131
+ AuthenticationError,
132
+ GraphQLError,
133
+ GraphQLErrorEntry,
134
+ GraphQLErrorLocation,
135
+ GraphQLTimeoutError,
136
+ ImageNotFoundError,
137
+ ImageUploadError,
138
+ ProductNotFoundError,
139
+ SessionNotActiveError,
140
+ ShopifyError,
141
+ VariantNotFoundError,
142
+ )
143
+
144
+ # Data models
145
+ from .models import (
146
+ SEO,
147
+ UNSET,
148
+ BulkUpdateResult,
149
+ DeleteProductResult,
150
+ DuplicateProductResult,
151
+ ImageCreateFailure,
152
+ ImageCreateResult,
153
+ ImageCreateSuccess,
154
+ ImageDeleteResult,
155
+ ImageReorderResult,
156
+ ImageSource,
157
+ ImageUpdate,
158
+ InventoryLevel,
159
+ InventoryPolicy,
160
+ InventoryQuantityName,
161
+ InventoryReason,
162
+ MediaStatus,
163
+ Metafield,
164
+ MetafieldDeleteFailure,
165
+ MetafieldDeleteResult,
166
+ MetafieldIdentifier,
167
+ MetafieldInput,
168
+ MetafieldType,
169
+ Money,
170
+ PageInfo,
171
+ PriceRange,
172
+ Product,
173
+ ProductConnection,
174
+ ProductCreate,
175
+ ProductImage,
176
+ ProductOption,
177
+ ProductStatus,
178
+ ProductUpdate,
179
+ ProductVariant,
180
+ SelectedOption,
181
+ ShopifyCredentials,
182
+ ShopifySessionInfo,
183
+ StagedUploadTarget,
184
+ UnsetType,
185
+ UpdateFailure,
186
+ UpdateSuccess,
187
+ VariantUpdate,
188
+ VariantUpdateRequest,
189
+ WeightUnit,
190
+ )
191
+
192
+ # Shopify client API
193
+ from .shopify_client import (
194
+ CacheCheckResult,
195
+ CacheMismatch,
196
+ ShopifySession,
197
+ adjust_inventory,
198
+ cache_clear_all,
199
+ create_image,
200
+ create_images,
201
+ create_product,
202
+ delete_image,
203
+ delete_images,
204
+ delete_metafield,
205
+ delete_metafields,
206
+ delete_product,
207
+ duplicate_product,
208
+ get_product_by_id,
209
+ get_product_by_sku,
210
+ get_product_id_from_sku,
211
+ iter_products,
212
+ list_products,
213
+ list_products_paginated,
214
+ login,
215
+ logout,
216
+ reorder_images,
217
+ set_inventory,
218
+ skucache_check,
219
+ skucache_clear,
220
+ skucache_rebuild,
221
+ tokencache_clear,
222
+ update_image,
223
+ update_product,
224
+ update_variant,
225
+ update_variants_bulk,
226
+ )
227
+
228
+ __all__ = [
229
+ # Shopify API - Session
230
+ "login",
231
+ "logout",
232
+ "ShopifySession",
233
+ # Shopify API - Create
234
+ "create_product",
235
+ # Shopify API - Read
236
+ "get_product_by_id",
237
+ "get_product_by_sku",
238
+ "get_product_id_from_sku",
239
+ "iter_products",
240
+ "list_products",
241
+ "list_products_paginated",
242
+ # Shopify API - Duplicate
243
+ "duplicate_product",
244
+ # Shopify API - Update
245
+ "update_product",
246
+ "update_variant",
247
+ "update_variants_bulk",
248
+ "set_inventory",
249
+ "adjust_inventory",
250
+ # Shopify API - Delete
251
+ "delete_image",
252
+ "delete_images",
253
+ "delete_metafield",
254
+ "delete_metafields",
255
+ "delete_product",
256
+ # Shopify API - Images
257
+ "create_image",
258
+ "create_images",
259
+ "reorder_images",
260
+ "update_image",
261
+ # Shopify API - Cache
262
+ "CacheCheckResult",
263
+ "CacheMismatch",
264
+ "cache_clear_all",
265
+ "skucache_check",
266
+ "skucache_clear",
267
+ "skucache_rebuild",
268
+ "tokencache_clear",
269
+ # Models - Read
270
+ "ShopifyCredentials",
271
+ "ShopifySessionInfo",
272
+ "Product",
273
+ "ProductVariant",
274
+ "ProductImage",
275
+ "ProductOption",
276
+ "Money",
277
+ "PriceRange",
278
+ "SEO",
279
+ "Metafield",
280
+ "MetafieldType",
281
+ "MediaStatus",
282
+ "ProductStatus",
283
+ "InventoryPolicy",
284
+ "InventoryQuantityName",
285
+ "InventoryReason",
286
+ "SelectedOption",
287
+ "WeightUnit",
288
+ "InventoryLevel",
289
+ # Models - Pagination
290
+ "PageInfo",
291
+ "ProductConnection",
292
+ # Models - Create
293
+ "ProductCreate",
294
+ # Models - Partial Update
295
+ "UNSET",
296
+ "UnsetType",
297
+ "ProductUpdate",
298
+ "VariantUpdate",
299
+ "MetafieldInput",
300
+ "VariantUpdateRequest",
301
+ "BulkUpdateResult",
302
+ "UpdateSuccess",
303
+ "UpdateFailure",
304
+ # Models - Metafield Deletion
305
+ "MetafieldIdentifier",
306
+ "MetafieldDeleteResult",
307
+ "MetafieldDeleteFailure",
308
+ # Models - Product Lifecycle
309
+ "DeleteProductResult",
310
+ "DuplicateProductResult",
311
+ # Models - Image Management
312
+ "ImageCreateFailure",
313
+ "ImageCreateResult",
314
+ "ImageCreateSuccess",
315
+ "ImageDeleteResult",
316
+ "ImageReorderResult",
317
+ "ImageSource",
318
+ "ImageUpdate",
319
+ "StagedUploadTarget",
320
+ # Exceptions
321
+ "ShopifyError",
322
+ "AuthenticationError",
323
+ "ProductNotFoundError",
324
+ "VariantNotFoundError",
325
+ "ImageNotFoundError",
326
+ "ImageUploadError",
327
+ "AmbiguousSKUError",
328
+ "SessionNotActiveError",
329
+ "GraphQLError",
330
+ "GraphQLErrorEntry",
331
+ "GraphQLErrorLocation",
332
+ "GraphQLTimeoutError",
333
+ # Configuration
334
+ "get_config",
335
+ "print_info",
336
+ # Application ports (for dependency injection)
337
+ "TokenProviderPort",
338
+ "GraphQLClientPort",
339
+ "SessionManagerPort",
340
+ "CachePort",
341
+ "SKUResolverPort",
342
+ "LocationResolverPort",
343
+ # Adapters
344
+ "JsonFileCacheAdapter",
345
+ "MySQLCacheAdapter",
346
+ "CachedSKUResolver",
347
+ "CachedTokenProvider",
348
+ "LocationResolver",
349
+ "PYMYSQL_AVAILABLE",
350
+ "DEFAULT_GRAPHQL_TIMEOUT_SECONDS",
351
+ # Composition
352
+ "AdapterBundle",
353
+ "create_adapters",
354
+ "create_cached_token_provider",
355
+ "get_default_adapters",
356
+ ]
@@ -0,0 +1,74 @@
1
+ """Static package metadata surfaced to CLI commands and documentation.
2
+
3
+ Purpose
4
+ -------
5
+ Expose the current project metadata as simple constants. These values are kept
6
+ in sync with ``pyproject.toml`` by development automation (tests, push
7
+ pipelines), so runtime code does not query packaging metadata.
8
+
9
+ Contents
10
+ --------
11
+ * Module-level constants describing the published package.
12
+ * :func:`print_info` rendering the constants for the CLI ``info`` command.
13
+
14
+ System Role
15
+ -----------
16
+ Lives in the adapters/platform layer; CLI transports import these constants to
17
+ present authoritative project information without invoking packaging APIs.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ #: Distribution name declared in ``pyproject.toml``.
23
+ name = "lib_shopify_graphql"
24
+ #: Human-readable summary shown in CLI help output.
25
+ title = "Python library for Shopify GraphQL API interactions"
26
+ #: Current release version pulled from ``pyproject.toml`` by automation.
27
+ version = "2.0.0"
28
+ #: Repository homepage presented to users.
29
+ homepage = "https://github.com/bitranox/lib_shopify_graphql"
30
+ #: Author attribution surfaced in CLI output.
31
+ author = "bitranox"
32
+ #: Contact email surfaced in CLI output.
33
+ author_email = "bitranox@gmail.com"
34
+ #: Console-script name published by the package.
35
+ shell_command = "lib-shopify-graphql"
36
+
37
+ #: Vendor identifier for lib_layered_config paths (macOS/Windows)
38
+ LAYEREDCONF_VENDOR: str = "bitranox"
39
+ #: Application display name for lib_layered_config paths (macOS/Windows)
40
+ LAYEREDCONF_APP: str = "Lib Shopify Graphql"
41
+ #: Configuration slug for lib_layered_config Linux paths and environment variables
42
+ LAYEREDCONF_SLUG: str = "lib-shopify-graphql"
43
+
44
+
45
+ def print_info() -> None:
46
+ """Print the summarised metadata block used by the CLI ``info`` command.
47
+
48
+ Why
49
+ Provides a single, auditable rendering function so documentation and
50
+ CLI output always match the system design reference.
51
+
52
+ Side Effects
53
+ Writes to ``stdout``.
54
+
55
+ Examples
56
+ --------
57
+ >>> print_info() # doctest: +ELLIPSIS
58
+ Info for lib_shopify_graphql:
59
+ ...
60
+ """
61
+
62
+ fields = [
63
+ ("name", name),
64
+ ("title", title),
65
+ ("version", version),
66
+ ("homepage", homepage),
67
+ ("author", author),
68
+ ("author_email", author_email),
69
+ ("shell_command", shell_command),
70
+ ]
71
+ pad = max(len(label) for label, _ in fields)
72
+ lines = [f"Info for {name}:", ""]
73
+ lines.extend(f" {label.ljust(pad)} = {value}" for label, value in fields)
74
+ print("\n".join(lines))
@@ -0,0 +1,113 @@
1
+ """Module entry point ensuring SystemExit semantics match project standards.
2
+
3
+ Provides the ``python -m lib_shopify_graphql`` path mandated by the
4
+ project's packaging guidelines. The wrapper delegates to
5
+ :func:`lib_shopify_graphql.cli.main` so that module execution mirrors the
6
+ installed console script, including traceback handling and exit-code mapping.
7
+
8
+ This module contains:
9
+ - :func:`_open_cli_session`: wires ``cli_session`` with the agreed limits.
10
+ - :func:`_command_to_run` / :func:`_command_name`: expose the command and label
11
+ used by the module entry.
12
+ - :func:`_module_main`: drives execution and returns the exit code.
13
+
14
+ Note:
15
+ Lives in the adapters layer. It bridges CPython's module execution entry point
16
+ to the shared CLI helper while reusing the same ``cli_session`` orchestration
17
+ documented in ``docs/systemdesign/module_reference.md``.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import logging
23
+ from collections.abc import Callable
24
+ from contextlib import AbstractContextManager
25
+ from typing import Final
26
+
27
+ import lib_log_rich.runtime
28
+ import rich_click as click
29
+ from lib_cli_exit_tools import cli_session
30
+
31
+ from . import __init__conf__, cli
32
+
33
+ # Match the CLI defaults so truncation behaviour stays consistent across entry
34
+ # points regardless of whether users call the console script or ``python -m``.
35
+ #: Character budget for truncated tracebacks when running via module entry.
36
+ TRACEBACK_SUMMARY_LIMIT: Final[int] = cli.TRACEBACK_SUMMARY_LIMIT
37
+ #: Character budget for verbose tracebacks when running via module entry.
38
+ TRACEBACK_VERBOSE_LIMIT: Final[int] = cli.TRACEBACK_VERBOSE_LIMIT
39
+
40
+
41
+ CommandRunner = Callable[..., int]
42
+ logger = logging.getLogger(__name__)
43
+
44
+
45
+ def _open_cli_session() -> AbstractContextManager[CommandRunner]:
46
+ """Return the configured ``cli_session`` context manager.
47
+
48
+ ``cli_session`` wires ``lib_cli_exit_tools`` with the tracing limits we
49
+ want for module execution. Wrapping it keeps the configuration in a
50
+ single place.
51
+
52
+ Returns:
53
+ Context manager that yields the callable responsible for invoking
54
+ the Click command.
55
+ """
56
+ return cli_session(
57
+ summary_limit=TRACEBACK_SUMMARY_LIMIT,
58
+ verbose_limit=TRACEBACK_VERBOSE_LIMIT,
59
+ )
60
+
61
+
62
+ def _command_to_run() -> click.Command:
63
+ """Expose the click command that powers the module entry.
64
+
65
+ Keeps the module entry explicit about which command is being executed
66
+ while remaining easy to stub in tests.
67
+
68
+ Returns:
69
+ Reference to the root CLI command group.
70
+ """
71
+ return cli.cli
72
+
73
+
74
+ def _command_name() -> str:
75
+ """Return the shell-friendly name announced by the session.
76
+
77
+ ``lib_cli_exit_tools`` uses this value when presenting help and error
78
+ messages; we centralise the derivation so tests can assert against it.
79
+
80
+ Returns:
81
+ Name of the console script as published through entry points.
82
+ """
83
+ return __init__conf__.shell_command
84
+
85
+
86
+ def _module_main() -> int:
87
+ """Execute the CLI entry point and return a normalised exit code.
88
+
89
+ Implements ``python -m lib_shopify_graphql`` by delegating to the
90
+ shared CLI composition while respecting the configured traceback
91
+ budgets.
92
+
93
+ Returns:
94
+ Exit code reported by the CLI run.
95
+
96
+ Note:
97
+ Logging initialization is deferred to cli() to support profile-specific
98
+ configuration. Shuts down lib_log_rich runtime on exit only if it was
99
+ initialized (e.g., --help exits before initialization).
100
+ """
101
+ try:
102
+ with _open_cli_session() as run:
103
+ return run(
104
+ _command_to_run(),
105
+ prog_name=_command_name(),
106
+ )
107
+ finally:
108
+ if lib_log_rich.runtime.is_initialised():
109
+ lib_log_rich.runtime.shutdown()
110
+
111
+
112
+ if __name__ == "__main__":
113
+ raise SystemExit(_module_main())
@@ -0,0 +1,32 @@
1
+ """Python version compatibility utilities.
2
+
3
+ This module provides backports for features not available in all supported
4
+ Python versions. The library supports Python 3.10+, but some standard library
5
+ features (like StrEnum) were added in Python 3.11.
6
+
7
+ Note:
8
+ This is the ONLY place compatibility shims should be defined.
9
+ All modules should import from here, not define their own shims.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import sys
15
+
16
+ if sys.version_info >= (3, 11): # noqa: UP036 - intentional, we support Python 3.10
17
+ from enum import StrEnum
18
+ else:
19
+ from enum import Enum
20
+
21
+ class StrEnum(str, Enum):
22
+ """Backport of StrEnum for Python 3.10.
23
+
24
+ StrEnum was added in Python 3.11. This provides equivalent
25
+ functionality for Python 3.10 users.
26
+ """
27
+
28
+ def __str__(self) -> str:
29
+ return str(self.value)
30
+
31
+
32
+ __all__ = ["StrEnum"]
@@ -0,0 +1,68 @@
1
+ """Adapters layer - implementations of application ports.
2
+
3
+ This layer contains concrete implementations that interface with
4
+ external systems:
5
+ - Shopify SDK adapter for API communication
6
+ - GraphQL query and mutation definitions
7
+ - Cache adapters (JSON file, MySQL)
8
+ - SKU and location resolvers
9
+
10
+ Adapters implement the ports defined in the application layer
11
+ and are wired at the composition root.
12
+
13
+ Note:
14
+ GraphQL queries, mutations, limits, and query builders are internal
15
+ implementation details and not exported in the public API. Import them
16
+ directly from their submodules if needed:
17
+
18
+ from lib_shopify_graphql.adapters.queries import (
19
+ GraphQLLimits, build_product_query, get_limits_from_config,
20
+ )
21
+ from lib_shopify_graphql.adapters.mutations import (
22
+ PRODUCT_UPDATE_MUTATION, ...
23
+ )
24
+ from lib_shopify_graphql.adapters.parsers import (
25
+ parse_product, ...
26
+ )
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ from .cache_json import JsonFileCacheAdapter
32
+ from .cache_mysql import PYMYSQL_AVAILABLE, MySQLCacheAdapter
33
+ from .constants import (
34
+ DEFAULT_GRAPHQL_TIMEOUT_SECONDS,
35
+ get_default_cache_dir,
36
+ get_default_sku_cache_path,
37
+ get_default_token_cache_path,
38
+ )
39
+ from .location_resolver import LocationResolver
40
+ from .shopify_sdk import (
41
+ ShopifyGraphQLClient,
42
+ ShopifySessionManager,
43
+ ShopifyTokenProvider,
44
+ )
45
+ from .sku_resolver import CachedSKUResolver
46
+ from .token_cache import CachedTokenProvider
47
+
48
+ __all__ = [
49
+ # Public constants
50
+ "DEFAULT_GRAPHQL_TIMEOUT_SECONDS",
51
+ "PYMYSQL_AVAILABLE",
52
+ # Cache path helpers
53
+ "get_default_cache_dir",
54
+ "get_default_sku_cache_path",
55
+ "get_default_token_cache_path",
56
+ # Shopify SDK adapters
57
+ "ShopifyGraphQLClient",
58
+ "ShopifySessionManager",
59
+ "ShopifyTokenProvider",
60
+ # Cache adapters
61
+ "JsonFileCacheAdapter",
62
+ "MySQLCacheAdapter",
63
+ # Token caching
64
+ "CachedTokenProvider",
65
+ # Resolvers
66
+ "CachedSKUResolver",
67
+ "LocationResolver",
68
+ ]