Declare packaging as a runtime dependency
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.
This commit is contained in:
@@ -15,31 +15,29 @@
|
||||
#
|
||||
# Regenerate with the command above. Do NOT hand-edit: waitress and tzdata were
|
||||
# hand-added here once and vanished on the next compile.
|
||||
#
|
||||
# Only DIRECT requirements belong in requirements.in. A runtime import that is
|
||||
# satisfied in dev only because some test dependency happens to pull it in will
|
||||
# pass every test and then fail on a production venv: `packaging` reached this
|
||||
# project through pytest, and the Windows install could not import shopdb at
|
||||
# all until it was declared. tests/test_runtime_dependencies.py guards that.
|
||||
alembic==1.18.4 \
|
||||
--hash=sha256:a5ed4adcf6d8a4cb575f3d759f071b03cd6e5c7618eb796cb52497be25bfe19a \
|
||||
--hash=sha256:cb6e1fd84b6174ab8dbb2329f86d631ba9559dd78df550b57804d607672cedbc
|
||||
# via
|
||||
# -r requirements.in
|
||||
# flask-migrate
|
||||
# via flask-migrate
|
||||
blinker==1.9.0 \
|
||||
--hash=sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf \
|
||||
--hash=sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc
|
||||
# via
|
||||
# -r requirements.in
|
||||
# flask
|
||||
# via flask
|
||||
cachelib==0.13.0 \
|
||||
--hash=sha256:209d8996e3c57595bee274ff97116d1d73c4980b2fd9a34c7846cd07fd2e1a48 \
|
||||
--hash=sha256:8c8019e53b6302967d4e8329a504acf75e7bc46130291d30188a6e4e58162516
|
||||
# via
|
||||
# -r requirements.in
|
||||
# flask-caching
|
||||
# via flask-caching
|
||||
certifi==2026.4.22 \
|
||||
--hash=sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a \
|
||||
--hash=sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580
|
||||
# via
|
||||
# -r requirements.in
|
||||
# requests
|
||||
cffi==2.1.0 \
|
||||
# via requests
|
||||
cffi==2.1.0 ; platform_python_implementation != 'PyPy' \
|
||||
--hash=sha256:02cb7ff33ded4f1532476731f89ede53e2e488a8e6205515a82144246ffa7dcc \
|
||||
--hash=sha256:03e9810d18c646077e501f661b682fbf5dee4676048527ca3cffe66faa9960dd \
|
||||
--hash=sha256:0520e1f4c35f44e209cbbb421b67eec42e6a157f59444dfb6058874ff3610e5d \
|
||||
@@ -140,9 +138,7 @@ cffi==2.1.0 \
|
||||
--hash=sha256:f9912624a0c0b834b7520d7769b3644453aabc0a7e1c839da7359f050750e9bc \
|
||||
--hash=sha256:fb62edb5bb52cca65fab91a63afa7561607120d26090a7e8fda6fb9f064726da \
|
||||
--hash=sha256:ff067a8d8d880e7809e4ac88eb009bb848870115317b306666502ccad30b147f
|
||||
# via
|
||||
# -r requirements.in
|
||||
# cryptography
|
||||
# via cryptography
|
||||
charset-normalizer==3.4.7 \
|
||||
--hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \
|
||||
--hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \
|
||||
@@ -273,9 +269,7 @@ charset-normalizer==3.4.7 \
|
||||
--hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \
|
||||
--hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \
|
||||
--hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464
|
||||
# via
|
||||
# -r requirements.in
|
||||
# requests
|
||||
# via requests
|
||||
click==8.3.3 \
|
||||
--hash=sha256:398329ad4837b2ff7cbe1dd166a4c0f8900c3ca3a218de04466f38f6497f18a2 \
|
||||
--hash=sha256:a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613
|
||||
@@ -337,9 +331,7 @@ cryptography==50.0.0 \
|
||||
dnspython==2.8.0 \
|
||||
--hash=sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af \
|
||||
--hash=sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f
|
||||
# via
|
||||
# -r requirements.in
|
||||
# email-validator
|
||||
# via email-validator
|
||||
email-validator==2.3.0 \
|
||||
--hash=sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4 \
|
||||
--hash=sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426
|
||||
@@ -381,7 +373,7 @@ flask-sqlalchemy==3.1.1 \
|
||||
# via
|
||||
# -r requirements.in
|
||||
# flask-migrate
|
||||
greenlet==3.5.0 \
|
||||
greenlet==3.5.0 ; platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64' \
|
||||
--hash=sha256:0ecec963079cd58cbd14723582384f11f166fd58883c15dcbfb342e0bc9b5846 \
|
||||
--hash=sha256:0ed006e4b86c59de7467eb2601cd1b77b5a7d657d1ee55e30fe30d76451edba4 \
|
||||
--hash=sha256:0ff251e9a0279522e62f6176412869395a64ddf2b5c5f782ff609a8216a4e662 \
|
||||
@@ -441,34 +433,25 @@ greenlet==3.5.0 \
|
||||
--hash=sha256:f35807464c4c58c55f0d31dfa83c541a5615d825c2fe3d2b95360cf7c4e3c0a8 \
|
||||
--hash=sha256:f8c30c2225f40dd76c50790f0eb3b5c7c18431efb299e2782083e1981feed243 \
|
||||
--hash=sha256:fa94cb2288681e3a11645958f1871d48ee9211bd2f66628fdace505927d6e564
|
||||
# via
|
||||
# -r requirements.in
|
||||
# sqlalchemy
|
||||
# via sqlalchemy
|
||||
idna==3.13 \
|
||||
--hash=sha256:585ea8fe5d69b9181ec1afba340451fba6ba764af97026f92a91d4eef164a242 \
|
||||
--hash=sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3
|
||||
# via
|
||||
# -r requirements.in
|
||||
# email-validator
|
||||
# requests
|
||||
itsdangerous==2.2.0 \
|
||||
--hash=sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef \
|
||||
--hash=sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173
|
||||
# via
|
||||
# -r requirements.in
|
||||
# flask
|
||||
# via flask
|
||||
jinja2==3.1.6 \
|
||||
--hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \
|
||||
--hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67
|
||||
# via
|
||||
# -r requirements.in
|
||||
# flask
|
||||
# via flask
|
||||
mako==1.3.12 \
|
||||
--hash=sha256:8f61569480282dbf557145ce441e4ba888be453c30989f879f0d652e39f53ea9 \
|
||||
--hash=sha256:9f778e93289bd410bb35daadeb4fc66d95a746f0b75777b942088b7fd7af550a
|
||||
# via
|
||||
# -r requirements.in
|
||||
# alembic
|
||||
# via alembic
|
||||
markupsafe==3.0.3 \
|
||||
--hash=sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f \
|
||||
--hash=sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a \
|
||||
@@ -560,7 +543,6 @@ markupsafe==3.0.3 \
|
||||
--hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a \
|
||||
--hash=sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50
|
||||
# via
|
||||
# -r requirements.in
|
||||
# flask
|
||||
# jinja2
|
||||
# mako
|
||||
@@ -569,7 +551,6 @@ marshmallow==4.3.0 \
|
||||
--hash=sha256:46c4fe6984707e3cbd485dfebbf0a59874f58d695aad05c1668d15e8c6e13b46 \
|
||||
--hash=sha256:fb43c53b3fe240b8f6af37223d6ef1636f927ad9bea8ab323afad95dff090880
|
||||
# via
|
||||
# -r requirements.in
|
||||
# flask-marshmallow
|
||||
# marshmallow-sqlalchemy
|
||||
marshmallow-sqlalchemy==1.5.0 \
|
||||
@@ -604,18 +585,18 @@ mysql-connector-python==9.7.0 \
|
||||
--hash=sha256:ea4e05ab864ab8b0b5066d885d89ca51e5ba1320dba520c20a6f9388a8eca022 \
|
||||
--hash=sha256:ee90c5f44f706f012be17f03f6ad158ff96e7f2dcc077896fe4537d3d28b3cf4
|
||||
# via -r requirements.in
|
||||
pycparser==3.0 \
|
||||
packaging==26.3 \
|
||||
--hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \
|
||||
--hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c
|
||||
# via -r requirements.in
|
||||
pycparser==3.0 ; implementation_name != 'PyPy' and platform_python_implementation != 'PyPy' \
|
||||
--hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \
|
||||
--hash=sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992
|
||||
# via
|
||||
# -r requirements.in
|
||||
# cffi
|
||||
# via cffi
|
||||
pyjwt==2.12.1 \
|
||||
--hash=sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c \
|
||||
--hash=sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b
|
||||
# via
|
||||
# -r requirements.in
|
||||
# flask-jwt-extended
|
||||
# via flask-jwt-extended
|
||||
pymysql==1.1.3 \
|
||||
--hash=sha256:8164ba62c552f6105f3b11753352d0f16b90d1703ba67d81923d5a8a5d1c5289 \
|
||||
--hash=sha256:e70ebf2047a4edf6138cf79c68ad418ef620af65900aa585c5e8bfc95044d43a
|
||||
@@ -693,7 +674,6 @@ sqlalchemy==2.0.49 \
|
||||
--hash=sha256:ec44cfa7ef1a728e88ad41674de50f6db8cfdb3e2af84af86e0041aaf02d43d0 \
|
||||
--hash=sha256:fb37f15714ec2652d574f021d479e78cd4eb9d04396dca36568fdfffb3487982
|
||||
# via
|
||||
# -r requirements.in
|
||||
# alembic
|
||||
# flask-sqlalchemy
|
||||
# marshmallow-sqlalchemy
|
||||
@@ -705,7 +685,6 @@ typing-extensions==4.15.0 \
|
||||
--hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \
|
||||
--hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
|
||||
# via
|
||||
# -r requirements.in
|
||||
# alembic
|
||||
# sqlalchemy
|
||||
tzdata==2026.3 \
|
||||
@@ -715,9 +694,7 @@ tzdata==2026.3 \
|
||||
urllib3==2.7.0 \
|
||||
--hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \
|
||||
--hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897
|
||||
# via
|
||||
# -r requirements.in
|
||||
# requests
|
||||
# via requests
|
||||
waitress==3.0.2 \
|
||||
--hash=sha256:682aaaf2af0c44ada4abfb70ded36393f0e307f4ab9456a215ce0020baefc31f \
|
||||
--hash=sha256:c56d67fd6e87c2ee598b76abdd4e96cfad1f24cacdea5078d382b1f9d7b5ed2e
|
||||
|
||||
Reference in New Issue
Block a user