lib-shopify-graphql 2.0.0__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 (132) hide show
  1. lib_shopify_graphql-2.0.0/.data_arch_violations.json +131 -0
  2. lib_shopify_graphql-2.0.0/.env.example +192 -0
  3. lib_shopify_graphql-2.0.0/.github/dependabot.yml +22 -0
  4. lib_shopify_graphql-2.0.0/.github/workflows/ci.yml +210 -0
  5. lib_shopify_graphql-2.0.0/.github/workflows/codeql.yml +39 -0
  6. lib_shopify_graphql-2.0.0/.github/workflows/integrationtest.yml +59 -0
  7. lib_shopify_graphql-2.0.0/.github/workflows/release.yml +50 -0
  8. lib_shopify_graphql-2.0.0/.gitignore +190 -0
  9. lib_shopify_graphql-2.0.0/.qlty/qlty.toml +2 -0
  10. lib_shopify_graphql-2.0.0/.snyk +5 -0
  11. lib_shopify_graphql-2.0.0/CHANGELOG.md +82 -0
  12. lib_shopify_graphql-2.0.0/CONTRIBUTING.md +48 -0
  13. lib_shopify_graphql-2.0.0/DEVELOPMENT.md +217 -0
  14. lib_shopify_graphql-2.0.0/INSTALL.md +193 -0
  15. lib_shopify_graphql-2.0.0/LICENSE +22 -0
  16. lib_shopify_graphql-2.0.0/Makefile +63 -0
  17. lib_shopify_graphql-2.0.0/PKG-INFO +321 -0
  18. lib_shopify_graphql-2.0.0/README.md +274 -0
  19. lib_shopify_graphql-2.0.0/codecov.yml +28 -0
  20. lib_shopify_graphql-2.0.0/docs/api_reference.md +1971 -0
  21. lib_shopify_graphql-2.0.0/docs/caching.md +303 -0
  22. lib_shopify_graphql-2.0.0/docs/cli.md +266 -0
  23. lib_shopify_graphql-2.0.0/docs/shopify_setup.md +95 -0
  24. lib_shopify_graphql-2.0.0/docs/sync_implementation.md +298 -0
  25. lib_shopify_graphql-2.0.0/docs/systemdesign/module_reference.md +985 -0
  26. lib_shopify_graphql-2.0.0/notebooks/Quickstart.ipynb +165 -0
  27. lib_shopify_graphql-2.0.0/pyproject.toml +233 -0
  28. lib_shopify_graphql-2.0.0/reset_git_history.sh +54 -0
  29. lib_shopify_graphql-2.0.0/scripts/__init__.py +9 -0
  30. lib_shopify_graphql-2.0.0/scripts/__main__.py +8 -0
  31. lib_shopify_graphql-2.0.0/scripts/_utils.py +768 -0
  32. lib_shopify_graphql-2.0.0/scripts/build.py +53 -0
  33. lib_shopify_graphql-2.0.0/scripts/bump.py +33 -0
  34. lib_shopify_graphql-2.0.0/scripts/bump_major.py +21 -0
  35. lib_shopify_graphql-2.0.0/scripts/bump_minor.py +21 -0
  36. lib_shopify_graphql-2.0.0/scripts/bump_patch.py +21 -0
  37. lib_shopify_graphql-2.0.0/scripts/bump_version.py +85 -0
  38. lib_shopify_graphql-2.0.0/scripts/clean.py +71 -0
  39. lib_shopify_graphql-2.0.0/scripts/cli.py +236 -0
  40. lib_shopify_graphql-2.0.0/scripts/dependencies.py +586 -0
  41. lib_shopify_graphql-2.0.0/scripts/dev.py +20 -0
  42. lib_shopify_graphql-2.0.0/scripts/help.py +38 -0
  43. lib_shopify_graphql-2.0.0/scripts/install.py +20 -0
  44. lib_shopify_graphql-2.0.0/scripts/menu.py +608 -0
  45. lib_shopify_graphql-2.0.0/scripts/push.py +310 -0
  46. lib_shopify_graphql-2.0.0/scripts/release.py +95 -0
  47. lib_shopify_graphql-2.0.0/scripts/run_cli.py +147 -0
  48. lib_shopify_graphql-2.0.0/scripts/target_metadata.py +206 -0
  49. lib_shopify_graphql-2.0.0/scripts/test.py +1147 -0
  50. lib_shopify_graphql-2.0.0/scripts/toml_config.py +433 -0
  51. lib_shopify_graphql-2.0.0/scripts/version_current.py +21 -0
  52. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/__init__.py +356 -0
  53. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/__init__conf__.py +74 -0
  54. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/__main__.py +113 -0
  55. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/_compat.py +32 -0
  56. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/adapters/__init__.py +68 -0
  57. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/adapters/cache_json.py +331 -0
  58. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/adapters/cache_mysql.py +530 -0
  59. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/adapters/constants.py +165 -0
  60. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/adapters/location_resolver.py +165 -0
  61. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/adapters/mutations.py +604 -0
  62. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/adapters/parsers.py +1112 -0
  63. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/adapters/queries.py +439 -0
  64. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/adapters/shopify_sdk.py +317 -0
  65. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/adapters/sku_resolver.py +492 -0
  66. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/adapters/token_cache.py +250 -0
  67. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/application/__init__.py +29 -0
  68. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/application/ports.py +322 -0
  69. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/cli/__init__.py +231 -0
  70. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/cli/_cache.py +566 -0
  71. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/cli/_common.py +384 -0
  72. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/cli/_config.py +192 -0
  73. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/cli/_health.py +332 -0
  74. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/cli/_images.py +362 -0
  75. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/cli/_products.py +751 -0
  76. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/cli/_test_limits.py +355 -0
  77. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/composition.py +482 -0
  78. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/config.py +119 -0
  79. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/config_deploy.py +112 -0
  80. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/config_show.py +124 -0
  81. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/defaultconfig.d/10-logging.toml +417 -0
  82. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/defaultconfig.d/20-shopify.toml +47 -0
  83. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/defaultconfig.d/30-mysql.toml +84 -0
  84. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/defaultconfig.d/40-token-cache.toml +66 -0
  85. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/defaultconfig.d/50-sku-cache.toml +69 -0
  86. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/defaultconfig.d/60-graphql.toml +118 -0
  87. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/defaultconfig.toml +56 -0
  88. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/domain/__init__.py +22 -0
  89. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/enums.py +70 -0
  90. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/exceptions.py +327 -0
  91. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/logging_setup.py +96 -0
  92. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/models/__init__.py +150 -0
  93. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/models/_entities.py +440 -0
  94. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/models/_enums.py +285 -0
  95. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/models/_images.py +277 -0
  96. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/models/_internal.py +114 -0
  97. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/models/_mutations.py +294 -0
  98. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/models/_operations.py +752 -0
  99. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/py.typed +0 -0
  100. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/shopify_client/__init__.py +113 -0
  101. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/shopify_client/_cache.py +297 -0
  102. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/shopify_client/_common.py +208 -0
  103. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/shopify_client/_images.py +726 -0
  104. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/shopify_client/_inventory.py +292 -0
  105. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/shopify_client/_metafields.py +308 -0
  106. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/shopify_client/_products.py +903 -0
  107. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/shopify_client/_session.py +349 -0
  108. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/shopify_client/_variants.py +253 -0
  109. lib_shopify_graphql-2.0.0/src/lib_shopify_graphql/shopify_client/_variants_bulk.py +235 -0
  110. lib_shopify_graphql-2.0.0/tests/conftest.py +1206 -0
  111. lib_shopify_graphql-2.0.0/tests/test_cache.py +863 -0
  112. lib_shopify_graphql-2.0.0/tests/test_cli.py +3797 -0
  113. lib_shopify_graphql-2.0.0/tests/test_composition.py +852 -0
  114. lib_shopify_graphql-2.0.0/tests/test_config.py +169 -0
  115. lib_shopify_graphql-2.0.0/tests/test_config_deploy.py +224 -0
  116. lib_shopify_graphql-2.0.0/tests/test_config_show.py +267 -0
  117. lib_shopify_graphql-2.0.0/tests/test_constants.py +231 -0
  118. lib_shopify_graphql-2.0.0/tests/test_enums.py +193 -0
  119. lib_shopify_graphql-2.0.0/tests/test_images.py +590 -0
  120. lib_shopify_graphql-2.0.0/tests/test_integration.py +1831 -0
  121. lib_shopify_graphql-2.0.0/tests/test_integration_mysql.py +412 -0
  122. lib_shopify_graphql-2.0.0/tests/test_location_resolver.py +294 -0
  123. lib_shopify_graphql-2.0.0/tests/test_metadata.py +190 -0
  124. lib_shopify_graphql-2.0.0/tests/test_models.py +1144 -0
  125. lib_shopify_graphql-2.0.0/tests/test_module_entry.py +203 -0
  126. lib_shopify_graphql-2.0.0/tests/test_parsers.py +1206 -0
  127. lib_shopify_graphql-2.0.0/tests/test_scripts.py +266 -0
  128. lib_shopify_graphql-2.0.0/tests/test_shopify_client.py +3194 -0
  129. lib_shopify_graphql-2.0.0/tests/test_sku_resolver.py +549 -0
  130. lib_shopify_graphql-2.0.0/tests/test_token_cache.py +469 -0
  131. lib_shopify_graphql-2.0.0/tests/test_update_models.py +622 -0
  132. lib_shopify_graphql-2.0.0/tests/zpool_list_ok_sample.json +81 -0
@@ -0,0 +1,131 @@
1
+ {
2
+ "pass": 2,
3
+ "status": "complete",
4
+ "files": {
5
+ "models/_entities.py": {"violations": [], "status": "clean"},
6
+ "models/_operations.py": {
7
+ "violations": [],
8
+ "status": "fixed",
9
+ "fixes_applied": [
10
+ "Created GraphQLErrorLocation Pydantic model",
11
+ "Created GraphQLErrorExtensions Pydantic model with extra='allow'",
12
+ "Created ProductUpdateMutationProduct model",
13
+ "Created ProductUpdateResponseData wrapper model",
14
+ "Created SelectedOptionData model for variant options",
15
+ "Created VariantMutationResult typed model",
16
+ "Created VariantsBulkUpdateMutationData model",
17
+ "Created VariantsBulkUpdateResponseData wrapper model",
18
+ "Created VariantsBulkUpdateResponse typed response model",
19
+ "Created TruncationInfo, TruncationFields, FieldTruncationInfo models"
20
+ ]
21
+ },
22
+ "models/_mutations.py": {
23
+ "violations": [],
24
+ "status": "fixed",
25
+ "fixes_applied": [
26
+ "Added is_field_set() method for typed field access",
27
+ "Added get_field_value() method for typed field access",
28
+ "Kept get_set_fields() for boundary conversion to GraphQL input"
29
+ ]
30
+ },
31
+ "models/_enums.py": {
32
+ "violations": [],
33
+ "status": "fixed",
34
+ "fixes_applied": [
35
+ "Removed local StrEnum shim",
36
+ "Now imports StrEnum from shared _compat.py module"
37
+ ]
38
+ },
39
+ "models/_images.py": {
40
+ "violations": [],
41
+ "status": "fixed",
42
+ "fixes_applied": [
43
+ "Created StagedUploadParameter model for typed parameters",
44
+ "Changed StagedUploadTarget.parameters from dict to list[StagedUploadParameter]",
45
+ "Added get_parameters_dict() method for boundary conversion"
46
+ ]
47
+ },
48
+ "models/_internal.py": {"violations": [], "status": "clean"},
49
+ "adapters/parsers.py": {
50
+ "violations": [],
51
+ "status": "fixed",
52
+ "fixes_applied": [
53
+ "Updated parse_variant_from_mutation to accept VariantMutationResult model",
54
+ "Updated parse_staged_upload_target to return StagedUploadTarget model",
55
+ "Updated get_truncation_info to return TruncationInfo model"
56
+ ]
57
+ },
58
+ "adapters/shopify_sdk.py": {"violations": [], "status": "clean"},
59
+ "shopify_client/_products.py": {
60
+ "violations": [],
61
+ "status": "acceptable",
62
+ "notes": "dict params are for raw GraphQL response validation at adapter boundary"
63
+ },
64
+ "shopify_client/_variants.py": {
65
+ "violations": [],
66
+ "status": "fixed",
67
+ "fixes_applied": [
68
+ "Updated _convert_graphql_error_data_to_entry to use typed model attributes",
69
+ "Changed loc.get() to loc.line and loc.column access",
70
+ "Changed extensions dict conversion to use model_dump()"
71
+ ]
72
+ },
73
+ "shopify_client/_common.py": {
74
+ "violations": [],
75
+ "status": "fixed",
76
+ "fixes_applied": [
77
+ "Created _AdaptersCache TypedDict for type-safe adapter storage",
78
+ "Replaced dict[str, Any] cache with typed _AdaptersCache",
79
+ "Removed cast() calls - TypedDict provides proper typing",
80
+ "Created _ensure_adapters_cache() helper that returns typed cache"
81
+ ]
82
+ },
83
+ "application/ports.py": {"violations": [], "status": "clean"},
84
+ "exceptions.py": {
85
+ "violations": [],
86
+ "status": "acceptable",
87
+ "notes": "GraphQLErrorEntry.extensions uses dict[str, object] for exception error data at boundary"
88
+ },
89
+ "enums.py": {
90
+ "violations": [],
91
+ "status": "fixed",
92
+ "fixes_applied": [
93
+ "Removed local StrEnum shim",
94
+ "Now imports StrEnum from shared _compat.py module"
95
+ ]
96
+ },
97
+ "_compat.py": {
98
+ "violations": [],
99
+ "status": "new",
100
+ "notes": "Consolidated StrEnum compatibility shim for Python 3.10 support"
101
+ },
102
+ "cli/_test_limits.py": {
103
+ "violations": [],
104
+ "status": "fixed",
105
+ "fixes_applied": [
106
+ "Updated to use TruncationInfo typed model instead of dict",
107
+ "Changed all dict access to model attribute access"
108
+ ]
109
+ }
110
+ },
111
+ "total_violations_fixed": 36,
112
+ "remaining_violations": 0,
113
+ "last_updated": "2026-01-13",
114
+ "summary": {
115
+ "key_changes": [
116
+ "Consolidated StrEnum compatibility shim to single _compat.py module",
117
+ "Replaced dict[str, Any] with typed Pydantic models throughout",
118
+ "Created typed models for GraphQL mutation responses",
119
+ "Created typed models for truncation analysis",
120
+ "Created TypedDict for adapter cache storage",
121
+ "Updated parsers to return typed models instead of dicts",
122
+ "Updated consumers to use model attributes instead of dict access"
123
+ ],
124
+ "patterns_applied": [
125
+ "Pydantic at boundaries (input/output)",
126
+ "No internal dicts for structured data",
127
+ "Single conversion at boundary",
128
+ "TypedDict for typed dictionary patterns"
129
+ ]
130
+ }
131
+ }
@@ -0,0 +1,192 @@
1
+ # Copy to .env and fill values as needed.
2
+ # IMPORTANT: Never commit .env files containing secrets to version control!
3
+ #
4
+ # Naming Convention for .env files (no prefix needed):
5
+ # Format: SECTION__KEY=value
6
+ # Uses double underscore (__) to create nested structures.
7
+ #
8
+ # For environment variables (require prefix):
9
+ # Format: LIB_SHOPIFY_GRAPHQL___SECTION__KEY=value
10
+ # Uses triple underscore (___) to separate prefix from section.
11
+
12
+ # ==============================================================================
13
+ # CI/CD Tokens (for development and release workflows)
14
+ # ==============================================================================
15
+
16
+ # Codecov upload token (required for private repos; optional for public repos)
17
+ # Get from: https://app.codecov.io/gh/<org>/<repo>/settings
18
+ CODECOV_TOKEN=
19
+
20
+ # PyPI API token for release workflow (.github/workflows/release.yml)
21
+ # Get from: https://pypi.org/manage/account/token/
22
+ # Format: pypi-AgENdGVzdC5weXBpLm9yZwIk...
23
+ PYPI_API_TOKEN=
24
+
25
+ # GitHub token for API-limited tasks (e.g., gh CLI, API calls)
26
+ # Get from: https://github.com/settings/tokens
27
+ GITHUB_TOKEN=
28
+
29
+ # ==============================================================================
30
+ # Shopify API Credentials
31
+ # ==============================================================================
32
+ # This library supports two authentication methods:
33
+ #
34
+ # METHOD 1: Direct Access Token (Custom Apps in Shopify Admin)
35
+ # ----------------------------------------------------------------
36
+ # For Custom Apps created in Shopify Admin (Settings > Apps and sales channels
37
+ # > Develop apps), you get a static Admin API access token that starts with
38
+ # "shpat_". This token doesn't expire and is shown only once when installing.
39
+ #
40
+ # Set SHOPIFY__ACCESS_TOKEN and leave CLIENT_ID/CLIENT_SECRET empty.
41
+ #
42
+ # METHOD 2: Client Credentials Grant (Partner Apps via Dev Dashboard)
43
+ # ----------------------------------------------------------------
44
+ # For apps created via https://dev.shopify.com/dashboard, use OAuth 2.0
45
+ # Client Credentials Grant. These tokens are valid for 24 hours.
46
+ #
47
+ # Set SHOPIFY__CLIENT_ID and SHOPIFY__CLIENT_SECRET, leave ACCESS_TOKEN empty.
48
+ #
49
+ # See README.md for detailed setup instructions.
50
+
51
+ # Store URL (without https://)
52
+ # Supports both .myshopify.com domains and custom domains
53
+ # Required for both methods
54
+ SHOPIFY__SHOP_URL=mystore.myshopify.com
55
+
56
+ # ----- Method 1: Direct Access Token (Custom Apps) -----
57
+ # Admin API access token from Custom App (starts with "shpat_")
58
+ # NEVER commit this value!
59
+ #SHOPIFY__ACCESS_TOKEN=shpat_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
60
+
61
+ # ----- Method 2: Client Credentials Grant (Partner Apps) -----
62
+ # OAuth Client ID (from Dev Dashboard)
63
+ #SHOPIFY__CLIENT_ID=your_client_id_here
64
+
65
+ # OAuth Client Secret (from Dev Dashboard)
66
+ # NEVER commit this value!
67
+ #SHOPIFY__CLIENT_SECRET=your_client_secret_here
68
+
69
+ # Shopify API version (format: YYYY-MM)
70
+ # Default: 2026-01
71
+ #SHOPIFY__API_VERSION=2026-01
72
+
73
+ # Default location for inventory operations
74
+ # If not set, uses shop's primary location (auto-fetched)
75
+ # Format: GID ("gid://shopify/Location/123") or numeric ID ("123")
76
+ # Default: "" (auto-fetch)
77
+ #SHOPIFY__DEFAULT_LOCATION_ID=gid://shopify/Location/123456789
78
+
79
+ # Default currency code (ISO 4217) for monetary operations
80
+ # Common codes: USD, EUR, GBP, CAD, AUD, JPY
81
+ # Default: USD
82
+ #SHOPIFY__DEFAULT_CURRENCY=USD
83
+
84
+ # ==============================================================================
85
+ # MySQL Database Configuration (for distributed caching)
86
+ # ==============================================================================
87
+ # Used when cache backend is set to "mysql".
88
+ # Database and tables are created automatically on first use.
89
+ #
90
+ # Connection string format: mysql://user:password@host:port/database
91
+ # Examples:
92
+ # mysql://shopify_app:secret@localhost:3306/shopify_cache
93
+ # mysql://root@127.0.0.1/cache
94
+
95
+ # MySQL connection string (shared by token and SKU caches)
96
+ # No default - required when using mysql backend
97
+ #SHOPIFY__MYSQL__CONNECTION=mysql://user:password@localhost:3306/shopify_cache
98
+
99
+ # Auto-create database if it doesn't exist
100
+ # Default: true
101
+ #SHOPIFY__MYSQL__AUTO_CREATE_DATABASE=true
102
+
103
+ # Connection timeout in seconds
104
+ # Default: 10
105
+ #SHOPIFY__MYSQL__CONNECT_TIMEOUT=10
106
+
107
+ # ==============================================================================
108
+ # Token Cache Configuration
109
+ # ==============================================================================
110
+ # Cache OAuth access tokens to reduce authentication requests.
111
+ # Tokens are valid for 24 hours.
112
+
113
+ # Enable token caching
114
+ # Default: false
115
+ #SHOPIFY__TOKEN_CACHE__ENABLED=true
116
+
117
+ # Cache backend: "json" or "mysql"
118
+ # Default: json
119
+ #SHOPIFY__TOKEN_CACHE__BACKEND=json
120
+
121
+ # Refresh margin - refresh token this many seconds before expiration
122
+ # Default: 300 (5 minutes)
123
+ #SHOPIFY__TOKEN_CACHE__REFRESH_MARGIN=300
124
+
125
+ # --- JSON Backend ---
126
+
127
+ # Path to the JSON cache file (directory created automatically)
128
+ # No default - required when using json backend with token caching enabled
129
+ #SHOPIFY__TOKEN_CACHE__JSON_PATH=/var/cache/shopify/token_cache.json
130
+
131
+ # Lock timeout in seconds for filelock
132
+ # Default: 10.0
133
+ #SHOPIFY__TOKEN_CACHE__LOCK_TIMEOUT=10.0
134
+
135
+ # --- MySQL Backend ---
136
+
137
+ # Override shared MySQL connection for token cache only
138
+ # Default: uses SHOPIFY__MYSQL__CONNECTION
139
+ #SHOPIFY__TOKEN_CACHE__MYSQL_CONNECTION=mysql://user:password@localhost:3306/shopify_cache
140
+
141
+ # Table name for token cache
142
+ # Default: token_cache
143
+ #SHOPIFY__TOKEN_CACHE__MYSQL_TABLE=token_cache
144
+
145
+ # ==============================================================================
146
+ # SKU Cache Configuration
147
+ # ==============================================================================
148
+ # Cache SKU-to-GID mappings to reduce API calls when updating by SKU.
149
+
150
+ # Cache backend: "json" or "mysql"
151
+ # Default: json
152
+ #SHOPIFY__SKU_CACHE__BACKEND=json
153
+
154
+ # Cache TTL in seconds
155
+ # Default: 2592000 (30 days)
156
+ #SHOPIFY__SKU_CACHE__TTL=2592000
157
+
158
+ # --- JSON Backend ---
159
+
160
+ # Path to the JSON cache file (directory created automatically)
161
+ # No default - required when using json backend
162
+ #SHOPIFY__SKU_CACHE__JSON_PATH=/var/cache/shopify/sku_cache.json
163
+
164
+ # Lock timeout in seconds for filelock
165
+ # Default: 10.0
166
+ #SHOPIFY__SKU_CACHE__LOCK_TIMEOUT=10.0
167
+
168
+ # --- MySQL Backend ---
169
+
170
+ # Override shared MySQL connection for SKU cache only
171
+ # Default: uses SHOPIFY__MYSQL__CONNECTION
172
+ #SHOPIFY__SKU_CACHE__MYSQL_CONNECTION=mysql://user:password@localhost:3306/shopify_cache
173
+
174
+ # Table name for SKU cache
175
+ # Default: sku_cache
176
+ #SHOPIFY__SKU_CACHE__MYSQL_TABLE=sku_cache
177
+
178
+ # ==============================================================================
179
+ # Logging Configuration (lib_log_rich)
180
+ # ==============================================================================
181
+ # Full documentation: https://github.com/bitranox/lib_log_rich
182
+ # See defaultconfig.d/10-logging.toml for all available options.
183
+
184
+ # Minimum severity level for console output
185
+ # Values: DEBUG, INFO, WARNING, ERROR, CRITICAL
186
+ # Default: INFO
187
+ #LIB_LOG_RICH__CONSOLE_LEVEL=INFO
188
+
189
+ # Console layout preset
190
+ # Values: full, short, full_loc, short_loc
191
+ # Default: full
192
+ #LIB_LOG_RICH__CONSOLE_FORMAT_PRESET=full
@@ -0,0 +1,22 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "pip"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ allow:
8
+ - dependency-type: "direct"
9
+ labels:
10
+ - "dependencies"
11
+ commit-message:
12
+ prefix: "deps"
13
+ include: "scope"
14
+ - package-ecosystem: "github-actions"
15
+ directory: "/"
16
+ schedule:
17
+ interval: "weekly"
18
+ labels:
19
+ - "dependencies"
20
+ commit-message:
21
+ prefix: "deps"
22
+ include: "scope"
@@ -0,0 +1,210 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, master ]
6
+ pull_request:
7
+ branches: [ main, master ]
8
+ schedule:
9
+ # Run daily at 3:17 AM UTC (off-peak hours, odd minute to avoid congestion)
10
+ - cron: '17 3 * * *'
11
+
12
+ jobs:
13
+ test:
14
+ name: Tests (Python ${{ matrix.python }}, ${{ matrix.os }})
15
+ runs-on: ${{ matrix.os }}
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ os: [ubuntu-latest, macos-latest, windows-latest]
20
+ # Test against Python 3.10 through 3.13
21
+ python: ["3.10", "3.11", "3.12", "3.13"]
22
+ env:
23
+ PYO3_USE_ABI3_FORWARD_COMPATIBILITY: "1"
24
+ PYTHONIOENCODING: "utf-8"
25
+ steps:
26
+ - uses: actions/checkout@v6
27
+ - uses: actions/setup-python@v6
28
+ with:
29
+ python-version: ${{ matrix.python }}
30
+ cache: 'pip'
31
+ cache-dependency-path: 'pyproject.toml'
32
+ - name: Install uv
33
+ uses: astral-sh/setup-uv@v7
34
+ with:
35
+ enable-cache: true
36
+ - name: Install rtoml for metadata extraction
37
+ shell: bash
38
+ run: pip install rtoml
39
+ - name: Extract project metadata
40
+ shell: python
41
+ run: |
42
+ import os
43
+ import rtoml
44
+ from pathlib import Path
45
+
46
+ data = rtoml.loads(Path('pyproject.toml').read_text('utf-8'))
47
+ project = data['project']['name']
48
+ module = project.replace('-', '_')
49
+ dash = project.replace('_', '-')
50
+ scripts = list(data['project'].get('scripts', {}).keys())
51
+ cli_bin = scripts[0] if scripts else dash
52
+
53
+ with open(os.environ['GITHUB_ENV'], 'a', encoding='utf-8') as env:
54
+ env.write(f"PROJECT_NAME={project}\n")
55
+ env.write(f"PACKAGE_MODULE={module}\n")
56
+ env.write(f"CLI_BIN={cli_bin}\n")
57
+ - name: Install make on Windows
58
+ if: runner.os == 'Windows'
59
+ shell: pwsh
60
+ run: |
61
+ choco install -y make
62
+ echo "C:\\ProgramData\\chocolatey\\bin" >> $env:GITHUB_PATH
63
+ - name: Install journald prerequisites
64
+ if: runner.os == 'Linux'
65
+ shell: bash
66
+ run: |
67
+ sudo apt-get update
68
+ sudo apt-get install -y python3-systemd
69
+
70
+ - name: Upgrade pip
71
+ shell: bash
72
+ run: python -m pip install --upgrade pip
73
+
74
+ - name: Install dev deps
75
+ shell: bash
76
+ run: |
77
+ uv pip install -e .[dev] --system
78
+
79
+ - name: Install Windows Event Log prerequisites
80
+ if: runner.os == 'Windows'
81
+ shell: bash
82
+ run: |
83
+ uv pip install pywin32 --system
84
+ - name: Cache ruff
85
+ uses: actions/cache@v5
86
+ with:
87
+ path: .ruff_cache
88
+ key: ruff-${{ runner.os }}-${{ github.sha }}
89
+ restore-keys: |
90
+ ruff-${{ runner.os }}-
91
+ - name: Cache pyright
92
+ uses: actions/cache@v5
93
+ with:
94
+ path: .pyright
95
+ key: pyright-${{ runner.os }}-py${{ matrix.python }}-${{ github.sha }}
96
+ restore-keys: |
97
+ pyright-${{ runner.os }}-py${{ matrix.python }}-
98
+ pyright-${{ runner.os }}-
99
+ - name: Run full test suite (lint, types, tests, coverage, codecov)
100
+ shell: bash
101
+ env:
102
+ TEST_VERBOSE: "1"
103
+ run: make test
104
+ - name: Build wheel/sdist
105
+ shell: bash
106
+ run: python -m build
107
+ - name: Verify wheel install in clean env
108
+ shell: bash
109
+ run: |
110
+ python -m venv .venv_wheel
111
+ . .venv_wheel/bin/activate 2>/dev/null || . .venv_wheel/Scripts/activate 2>/dev/null
112
+ pip install dist/*.whl
113
+ "$CLI_BIN" --version 2>/dev/null || python -m "$PACKAGE_MODULE" --version
114
+
115
+ pipx-uv:
116
+ name: pipx/uv verification (ubuntu)
117
+ runs-on: ubuntu-latest
118
+ steps:
119
+ - uses: actions/checkout@v6
120
+ - uses: actions/setup-python@v6
121
+ with:
122
+ python-version: "3.13"
123
+ cache: 'pip'
124
+ cache-dependency-path: 'pyproject.toml'
125
+ - name: Install rtoml for metadata extraction
126
+ shell: bash
127
+ run: pip install rtoml
128
+ - name: Extract project metadata
129
+ shell: python
130
+ run: |
131
+ import os
132
+ import rtoml
133
+ from pathlib import Path
134
+
135
+ data = rtoml.loads(Path('pyproject.toml').read_text('utf-8'))
136
+ project = data['project']['name']
137
+ module = project.replace('-', '_')
138
+ dash = project.replace('_', '-')
139
+ scripts = list(data['project'].get('scripts', {}).keys())
140
+ cli_bin = scripts[0] if scripts else dash
141
+
142
+ with open(os.environ['GITHUB_ENV'], 'a', encoding='utf-8') as env:
143
+ env.write(f"PROJECT_NAME={project}\n")
144
+ env.write(f"PACKAGE_MODULE={module}\n")
145
+ env.write(f"CLI_BIN={cli_bin}\n")
146
+ - name: Build wheel
147
+ run: |
148
+ python -m pip install --upgrade pip build
149
+ python -m build
150
+ - name: pipx install from wheel
151
+ run: |
152
+ python -m pip install pipx
153
+ pipx install dist/*.whl
154
+ # pipx installs to ~/.local/bin, ensure it's in PATH
155
+ export PATH="$HOME/.local/bin:$PATH"
156
+ "$CLI_BIN" --version
157
+ - name: Install uv
158
+ uses: astral-sh/setup-uv@v7
159
+ with:
160
+ enable-cache: true
161
+ - name: uv tool install
162
+ run: |
163
+ uv tool install .
164
+ # uv installs to ~/.local/bin, ensure it's in PATH
165
+ export PATH="$HOME/.local/bin:$PATH"
166
+ "$CLI_BIN" --version
167
+
168
+ notebooks:
169
+ name: Execute notebooks (ubuntu, Python 3.13)
170
+ runs-on: ubuntu-latest
171
+ steps:
172
+ - uses: actions/checkout@v6
173
+ - uses: actions/setup-python@v6
174
+ with:
175
+ python-version: "3.13"
176
+ cache: 'pip'
177
+ cache-dependency-path: 'pyproject.toml'
178
+ - name: Install notebook runner deps
179
+ run: |
180
+ python -m pip install --upgrade pip
181
+ pip install nbclient nbformat ipykernel jupyter_client
182
+ python -m ipykernel install --user --name python3 --display-name "Python 3"
183
+ - name: Execute Quickstart notebook
184
+ env:
185
+ PIP_DISABLE_PIP_VERSION_CHECK: "1"
186
+ PIP_NO_INPUT: "1"
187
+ run: |
188
+ python - << 'PY'
189
+ from pathlib import Path
190
+
191
+ import nbformat
192
+ from nbclient import NotebookClient
193
+
194
+ nb_path = Path('notebooks/Quickstart.ipynb')
195
+ if not nb_path.exists():
196
+ raise SystemExit(f"Notebook not found: {nb_path}")
197
+
198
+ notebook = nbformat.read(nb_path, as_version=4)
199
+ client = NotebookClient(
200
+ notebook,
201
+ timeout=900,
202
+ kernel_name='python3',
203
+ allow_errors=False,
204
+ )
205
+ client.execute()
206
+
207
+ out_path = Path('notebooks/Quickstart-executed.ipynb')
208
+ nbformat.write(notebook, out_path)
209
+ print(f"Executed notebook written to: {out_path}")
210
+ PY
@@ -0,0 +1,39 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, master ]
6
+ pull_request:
7
+ branches: [ main, master ]
8
+ schedule:
9
+ - cron: '0 8 * * 1'
10
+
11
+ jobs:
12
+ analyze:
13
+ name: CodeQL Analyze
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ actions: read
17
+ contents: read
18
+ security-events: write
19
+ strategy:
20
+ fail-fast: false
21
+ matrix:
22
+ language: [ 'python' ]
23
+
24
+ steps:
25
+ - name: Checkout repository
26
+ uses: actions/checkout@v6
27
+
28
+ - name: Initialize CodeQL
29
+ uses: github/codeql-action/init@v4
30
+ with:
31
+ languages: ${{ matrix.language }}
32
+
33
+ - name: Autobuild
34
+ uses: github/codeql-action/autobuild@v4
35
+
36
+ - name: Perform CodeQL Analysis
37
+ uses: github/codeql-action/analyze@v4
38
+ with:
39
+ category: "/language:${{ matrix.language }}"
@@ -0,0 +1,59 @@
1
+ name: Integration Tests
2
+
3
+ on:
4
+ workflow_dispatch: # Manual trigger only (requires real Shopify credentials)
5
+ schedule:
6
+ # Run weekly on Sunday at 4:17 AM UTC
7
+ - cron: '17 4 * * 0'
8
+
9
+ jobs:
10
+ integration:
11
+ name: Integration Tests (Python 3.14, Linux)
12
+ runs-on: ubuntu-latest
13
+ env:
14
+ PYTHONIOENCODING: "utf-8"
15
+ # Shopify credentials from repository secrets
16
+ # Format: LIB_SHOPIFY_GRAPHQL___SECTION__KEY (triple underscore after prefix)
17
+ LIB_SHOPIFY_GRAPHQL___SHOPIFY__SHOP_URL: ${{ secrets.SHOPIFY_SHOP_URL }}
18
+ LIB_SHOPIFY_GRAPHQL___SHOPIFY__CLIENT_ID: ${{ secrets.SHOPIFY_CLIENT_ID }}
19
+ LIB_SHOPIFY_GRAPHQL___SHOPIFY__CLIENT_SECRET: ${{ secrets.SHOPIFY_CLIENT_SECRET }}
20
+ steps:
21
+ - uses: actions/checkout@v6
22
+
23
+ - uses: actions/setup-python@v6
24
+ with:
25
+ python-version: "3.14"
26
+ cache: 'pip'
27
+ cache-dependency-path: 'pyproject.toml'
28
+
29
+ - name: Install uv
30
+ uses: astral-sh/setup-uv@v7
31
+ with:
32
+ enable-cache: true
33
+
34
+ - name: Install journald prerequisites
35
+ shell: bash
36
+ run: |
37
+ sudo apt-get update
38
+ sudo apt-get install -y python3-systemd
39
+
40
+ - name: Upgrade pip
41
+ shell: bash
42
+ run: python -m pip install --upgrade pip
43
+
44
+ - name: Install dev deps
45
+ shell: bash
46
+ run: uv pip install -e .[dev] --system
47
+
48
+ - name: Check Shopify credentials
49
+ shell: bash
50
+ run: |
51
+ if [ -z "$LIB_SHOPIFY_GRAPHQL___SHOPIFY__SHOP_URL" ] || [ -z "$LIB_SHOPIFY_GRAPHQL___SHOPIFY__CLIENT_ID" ] || [ -z "$LIB_SHOPIFY_GRAPHQL___SHOPIFY__CLIENT_SECRET" ]; then
52
+ echo "::error::Missing Shopify credentials. Set SHOPIFY_SHOP_URL, SHOPIFY_CLIENT_ID, and SHOPIFY_CLIENT_SECRET as repository secrets."
53
+ exit 1
54
+ fi
55
+ echo "Shopify credentials configured for: $LIB_SHOPIFY_GRAPHQL___SHOPIFY__SHOP_URL"
56
+
57
+ - name: Run integration tests (test-slow)
58
+ shell: bash
59
+ run: make test-slow