shopdb/plugins/loader.py imports packaging.specifiers and packaging.version at module scope, but packaging was never listed in requirements.in. It was present in every development and CI environment as a transitive dependency of pytest, so the full suite passed while a venv built from requirements.txt alone could not import shopdb at all. The Windows installer builds exactly such a venv, so stage 3 failed on a customer server with ModuleNotFoundError: No module named 'packaging', after the runtime and all wheels had installed successfully. Add packaging to requirements.in, recompile the hashed lockfile, and add the wheel to the offline wheelhouse with the matching bundle-lock entry. The recompile also picked up newer uv formatting: inline environment markers on cffi and greenlet and shorter "via" comments. The pinned distribution set and every existing hash are unchanged. tests/test_runtime_dependencies.py guards the general case by scanning shopdb/, plugins/ and scripts/ for unconditional third-party imports and asserting each maps to a distribution pinned in requirements.txt. Test dependencies are the blind spot for this class of failure, since they are present wherever the suite runs and absent wherever it does not.
241 lines
8.9 KiB
JSON
241 lines
8.9 KiB
JSON
{
|
|
"schema": 1,
|
|
"generated": "2026-08-04T23:11:22Z",
|
|
"pythontag": "cp314",
|
|
"platform": "win_amd64",
|
|
"note": "Exact third-party payload of the installer bundle. Regenerate with refresh-bundle-lock.ps1 and COMMIT the change as a reviewed dependency bump.",
|
|
"payloads": {
|
|
"httpplatformhandler": {
|
|
"files": {
|
|
"httpPlatformHandler_amd64.msi": {
|
|
"sha256": "90f8d4905a0ab4f2c95223b3c79e2807a0b74507747d240e43c4302e8db4b5ef",
|
|
"size": 557056
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"python": {
|
|
"files": {
|
|
"python-3.14.6-amd64.exe": {
|
|
"sha256": "14b3e9a710a3fcf0bd9b55ab6b60412bd91227563f813fc49040cabc0209e0bd",
|
|
"size": 30774112
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"vcredist": {
|
|
"files": {
|
|
"VC_redist.x64.exe": {
|
|
"sha256": "cc0ff0eb1dc3f5188ae6300faef32bf5beeba4bdd6e8e445a9184072096b713b",
|
|
"size": 25635768
|
|
}
|
|
},
|
|
"required": false
|
|
},
|
|
"mysql": {
|
|
"files": {
|
|
"mysql-8.4.6-winx64.msi": {
|
|
"sha256": "868885b2e221409f0170729bb30b2b2ce83440a1a4c735d19b3c225b51045762",
|
|
"size": 135081984
|
|
}
|
|
},
|
|
"required": false
|
|
},
|
|
"wheels": {
|
|
"files": {
|
|
"email_validator-2.3.0-py3-none-any.whl": {
|
|
"sha256": "80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4",
|
|
"size": 35604
|
|
},
|
|
"cachelib-0.13.0-py3-none-any.whl": {
|
|
"sha256": "8c8019e53b6302967d4e8329a504acf75e7bc46130291d30188a6e4e58162516",
|
|
"size": 20914
|
|
},
|
|
"flask_caching-2.4.0-py3-none-any.whl": {
|
|
"sha256": "d15b8135f055c4f28f6f7dbcf8d36a3de4af1224def975ae6e0b43cbfa684486",
|
|
"size": 28727
|
|
},
|
|
"typing_extensions-4.15.0-py3-none-any.whl": {
|
|
"sha256": "f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548",
|
|
"size": 44614
|
|
},
|
|
"greenlet-3.5.0-cp314-cp314-win_amd64.whl": {
|
|
"sha256": "3bc59be3945ae9750b9e7d45067d01ae3fe90ea5f9ade99239dabdd6e28a5033",
|
|
"size": 239835
|
|
},
|
|
"charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl": {
|
|
"sha256": "92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f",
|
|
"size": 159634
|
|
},
|
|
"colorama-0.4.6-py2.py3-none-any.whl": {
|
|
"sha256": "4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6",
|
|
"size": 25335
|
|
},
|
|
"Flask_Migrate-4.1.0-py3-none-any.whl": {
|
|
"sha256": "24d8051af161782e0743af1b04a152d007bad9772b2bca67b7ec1e8ceeb3910d",
|
|
"size": 21237
|
|
},
|
|
"markupsafe-3.0.3-cp314-cp314-win_amd64.whl": {
|
|
"sha256": "bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581",
|
|
"size": 15341
|
|
},
|
|
"flask_marshmallow-1.5.0-py3-none-any.whl": {
|
|
"sha256": "99951c77e5654111ed733811c6dc9310bfb4c3688c78a9e76f80b5ae0b2279a6",
|
|
"size": 12161
|
|
},
|
|
"tzdata-2026.3-py2.py3-none-any.whl": {
|
|
"sha256": "dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931",
|
|
"size": 348168
|
|
},
|
|
"python_dotenv-1.2.2-py3-none-any.whl": {
|
|
"sha256": "1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a",
|
|
"size": 22101
|
|
},
|
|
"dnspython-2.8.0-py3-none-any.whl": {
|
|
"sha256": "01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af",
|
|
"size": 331094
|
|
},
|
|
"pymysql-1.1.3-py3-none-any.whl": {
|
|
"sha256": "8164ba62c552f6105f3b11753352d0f16b90d1703ba67d81923d5a8a5d1c5289",
|
|
"size": 45356
|
|
},
|
|
"packaging-26.3-py3-none-any.whl": {
|
|
"sha256": "d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c",
|
|
"size": 129956
|
|
},
|
|
"flask_jwt_extended-4.7.3-py2.py3-none-any.whl": {
|
|
"sha256": "905ac807b52b5409bc9244dbcca434968c13ca6f9d91bffe7d4cb71e0e6231cb",
|
|
"size": 22698
|
|
},
|
|
"urllib3-2.7.0-py3-none-any.whl": {
|
|
"sha256": "9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897",
|
|
"size": 131087
|
|
},
|
|
"marshmallow-4.3.0-py3-none-any.whl": {
|
|
"sha256": "46c4fe6984707e3cbd485dfebbf0a59874f58d695aad05c1668d15e8c6e13b46",
|
|
"size": 49148
|
|
},
|
|
"waitress-3.0.2-py3-none-any.whl": {
|
|
"sha256": "c56d67fd6e87c2ee598b76abdd4e96cfad1f24cacdea5078d382b1f9d7b5ed2e",
|
|
"size": 56232
|
|
},
|
|
"idna-3.13-py3-none-any.whl": {
|
|
"sha256": "892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3",
|
|
"size": 68629
|
|
},
|
|
"flask-3.1.3-py3-none-any.whl": {
|
|
"sha256": "f4bcbefc124291925f1a26446da31a5178f9483862233b23c0c96a20701f670c",
|
|
"size": 103424
|
|
},
|
|
"werkzeug-3.1.8-py3-none-any.whl": {
|
|
"sha256": "63a77fb8892bf28ebc3178683445222aa500e48ebad5ec77b0ad80f8726b1f50",
|
|
"size": 226459
|
|
},
|
|
"flask_sqlalchemy-3.1.1-py3-none-any.whl": {
|
|
"sha256": "4ba4be7f419dc72f4efd8802d69974803c37259dd42f3913b0dcf75c9447e0a0",
|
|
"size": 25125
|
|
},
|
|
"marshmallow_sqlalchemy-1.5.0-py3-none-any.whl": {
|
|
"sha256": "3865232672f3dd38c4d5e4e85fdedce76904200742c3594948a2d11d0af93258",
|
|
"size": 16582
|
|
},
|
|
"alembic-1.18.4-py3-none-any.whl": {
|
|
"sha256": "a5ed4adcf6d8a4cb575f3d759f071b03cd6e5c7618eb796cb52497be25bfe19a",
|
|
"size": 263893
|
|
},
|
|
"tabulate-0.10.0-py3-none-any.whl": {
|
|
"sha256": "f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3",
|
|
"size": 39814
|
|
},
|
|
"cffi-2.1.0-cp314-cp314-win_amd64.whl": {
|
|
"sha256": "1b96bfe2c4bd825681b7d311ad6d9b7280a091f43e8f63da5729638083cd3bfb",
|
|
"size": 187937
|
|
},
|
|
"jinja2-3.1.6-py3-none-any.whl": {
|
|
"sha256": "85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67",
|
|
"size": 134899
|
|
},
|
|
"cryptography-50.0.0-cp311-abi3-win_amd64.whl": {
|
|
"sha256": "bd1c592e4d5974f0d08d4888e432157adba757c66da0246918e43677fafa2d30",
|
|
"size": 3840395
|
|
},
|
|
"certifi-2026.4.22-py3-none-any.whl": {
|
|
"sha256": "3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a",
|
|
"size": 135707
|
|
},
|
|
"sqlalchemy-2.0.49-cp314-cp314-win_amd64.whl": {
|
|
"sha256": "77641d299179c37b89cf2343ca9972c88bb6eef0d5fc504a2f86afd15cd5adf5",
|
|
"size": 2144204
|
|
},
|
|
"blinker-1.9.0-py3-none-any.whl": {
|
|
"sha256": "ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc",
|
|
"size": 8458
|
|
},
|
|
"pycparser-3.0-py3-none-any.whl": {
|
|
"sha256": "b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992",
|
|
"size": 48172
|
|
},
|
|
"flask_cors-6.0.2-py3-none-any.whl": {
|
|
"sha256": "e57544d415dfd7da89a9564e1e3a9e515042df76e12130641ca6f3f2f03b699a",
|
|
"size": 13257
|
|
},
|
|
"requests-2.33.1-py3-none-any.whl": {
|
|
"sha256": "4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a",
|
|
"size": 64947
|
|
},
|
|
"pyjwt-2.12.1-py3-none-any.whl": {
|
|
"sha256": "28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c",
|
|
"size": 29726
|
|
},
|
|
"click-8.3.3-py3-none-any.whl": {
|
|
"sha256": "a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613",
|
|
"size": 110502
|
|
},
|
|
"mysql_connector_python-9.7.0-cp314-cp314-win_amd64.whl": {
|
|
"sha256": "5a5abbc152bc28cb2e64a04605ecd9941eff6b0dc5f9528cb84adb873e9a1e49",
|
|
"size": 18197576
|
|
},
|
|
"mako-1.3.12-py3-none-any.whl": {
|
|
"sha256": "8f61569480282dbf557145ce441e4ba888be453c30989f879f0d652e39f53ea9",
|
|
"size": 78521
|
|
},
|
|
"itsdangerous-2.2.0-py3-none-any.whl": {
|
|
"sha256": "c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef",
|
|
"size": 16234
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"urlrewrite": {
|
|
"files": {
|
|
"rewrite_amd64_en-US.msi": {
|
|
"sha256": "37342ff2f585f263f34f48e9de59eb1051d61015a8e967dbde4075716230a32a",
|
|
"size": 6078464
|
|
}
|
|
},
|
|
"required": false
|
|
},
|
|
"mysqlclient": {
|
|
"files": {
|
|
"libcrypto-3-x64.dll": {
|
|
"sha256": "e84ec61fc1b07a3c899ae39c1dc3f38591cdd310c043a388e7ab40a6828aa297",
|
|
"size": 5187216
|
|
},
|
|
"mysqldump.exe": {
|
|
"sha256": "329410b7a8ae3d68d38e6f5b781610770854d3f11b975060e231dae62c20dc46",
|
|
"size": 7142528
|
|
},
|
|
"mysql.exe": {
|
|
"sha256": "bd6880253c1853fc17b1e19129d6e5d9f9c86a2dccf2c7c9e6b878a10baa9770",
|
|
"size": 7177336
|
|
},
|
|
"libssl-3-x64.dll": {
|
|
"sha256": "e24fcd6c8ec31a14c97f520b5b960ed360c55ddf0935040eff297e511697633e",
|
|
"size": 788616
|
|
}
|
|
},
|
|
"required": false
|
|
}
|
|
}
|
|
}
|