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.
- lib_shopify_graphql/__init__.py +356 -0
- lib_shopify_graphql/__init__conf__.py +74 -0
- lib_shopify_graphql/__main__.py +113 -0
- lib_shopify_graphql/_compat.py +32 -0
- lib_shopify_graphql/adapters/__init__.py +68 -0
- lib_shopify_graphql/adapters/cache_json.py +331 -0
- lib_shopify_graphql/adapters/cache_mysql.py +530 -0
- lib_shopify_graphql/adapters/constants.py +165 -0
- lib_shopify_graphql/adapters/location_resolver.py +165 -0
- lib_shopify_graphql/adapters/mutations.py +604 -0
- lib_shopify_graphql/adapters/parsers.py +1112 -0
- lib_shopify_graphql/adapters/queries.py +439 -0
- lib_shopify_graphql/adapters/shopify_sdk.py +317 -0
- lib_shopify_graphql/adapters/sku_resolver.py +492 -0
- lib_shopify_graphql/adapters/token_cache.py +250 -0
- lib_shopify_graphql/application/__init__.py +29 -0
- lib_shopify_graphql/application/ports.py +322 -0
- lib_shopify_graphql/cli/__init__.py +231 -0
- lib_shopify_graphql/cli/_cache.py +566 -0
- lib_shopify_graphql/cli/_common.py +384 -0
- lib_shopify_graphql/cli/_config.py +192 -0
- lib_shopify_graphql/cli/_health.py +332 -0
- lib_shopify_graphql/cli/_images.py +362 -0
- lib_shopify_graphql/cli/_products.py +751 -0
- lib_shopify_graphql/cli/_test_limits.py +355 -0
- lib_shopify_graphql/composition.py +482 -0
- lib_shopify_graphql/config.py +119 -0
- lib_shopify_graphql/config_deploy.py +112 -0
- lib_shopify_graphql/config_show.py +124 -0
- lib_shopify_graphql/defaultconfig.d/10-logging.toml +417 -0
- lib_shopify_graphql/defaultconfig.d/20-shopify.toml +47 -0
- lib_shopify_graphql/defaultconfig.d/30-mysql.toml +84 -0
- lib_shopify_graphql/defaultconfig.d/40-token-cache.toml +66 -0
- lib_shopify_graphql/defaultconfig.d/50-sku-cache.toml +69 -0
- lib_shopify_graphql/defaultconfig.d/60-graphql.toml +118 -0
- lib_shopify_graphql/defaultconfig.toml +56 -0
- lib_shopify_graphql/domain/__init__.py +22 -0
- lib_shopify_graphql/enums.py +70 -0
- lib_shopify_graphql/exceptions.py +327 -0
- lib_shopify_graphql/logging_setup.py +96 -0
- lib_shopify_graphql/models/__init__.py +150 -0
- lib_shopify_graphql/models/_entities.py +440 -0
- lib_shopify_graphql/models/_enums.py +285 -0
- lib_shopify_graphql/models/_images.py +277 -0
- lib_shopify_graphql/models/_internal.py +114 -0
- lib_shopify_graphql/models/_mutations.py +294 -0
- lib_shopify_graphql/models/_operations.py +752 -0
- lib_shopify_graphql/py.typed +0 -0
- lib_shopify_graphql/shopify_client/__init__.py +113 -0
- lib_shopify_graphql/shopify_client/_cache.py +297 -0
- lib_shopify_graphql/shopify_client/_common.py +208 -0
- lib_shopify_graphql/shopify_client/_images.py +726 -0
- lib_shopify_graphql/shopify_client/_inventory.py +292 -0
- lib_shopify_graphql/shopify_client/_metafields.py +308 -0
- lib_shopify_graphql/shopify_client/_products.py +903 -0
- lib_shopify_graphql/shopify_client/_session.py +349 -0
- lib_shopify_graphql/shopify_client/_variants.py +253 -0
- lib_shopify_graphql/shopify_client/_variants_bulk.py +235 -0
- lib_shopify_graphql-2.0.0.dist-info/METADATA +321 -0
- lib_shopify_graphql-2.0.0.dist-info/RECORD +63 -0
- lib_shopify_graphql-2.0.0.dist-info/WHEEL +4 -0
- lib_shopify_graphql-2.0.0.dist-info/entry_points.txt +3 -0
- 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
|
+
]
|