From d4816fd8c6d3b627d02acc0e605f89008cd9bf42 Mon Sep 17 00:00:00 2001 From: Gabriel Dugny Date: Wed, 27 Mar 2024 01:37:33 +0100 Subject: [PATCH] feat: module shadow (fix #19) --- src/check_wheel_contents/checker.py | 23 ++++++++++++++++++ src/check_wheel_contents/checks.py | 1 + ...file_folder_shadow-0.1.0-py3-none-any.json | 5 ++++ ..._file_folder_shadow-0.1.0-py3-none-any.whl | Bin 0 -> 1840 bytes 4 files changed, 29 insertions(+) create mode 100644 test/data/wheels/module_file_folder_shadow-0.1.0-py3-none-any.json create mode 100644 test/data/wheels/module_file_folder_shadow-0.1.0-py3-none-any.whl diff --git a/src/check_wheel_contents/checker.py b/src/check_wheel_contents/checker.py index 87d2d41..f6abe64 100644 --- a/src/check_wheel_contents/checker.py +++ b/src/check_wheel_contents/checker.py @@ -299,6 +299,29 @@ def check_W010(self, contents: WheelContents) -> list[FailedCheck]: else: return [] + def check_W011(self, contents: WheelContents) -> list[FailedCheck]: + """ + W011 — Conflict between module as a file (.py) and as a folder (__init__.py) + + Checks for both `path/foo.py` and `path/foo/__init__.py` being present + """ + conflicts: list[str] = [] + + def check_dir(tree: Directory) -> None: + for name, entry in tree.entries.items(): + if isinstance(entry, Directory): + if tree.files.get(name + ".py") is not None: + conflicts.append(entry.path or name) + check_dir(entry) + + for tree in (contents.purelib_tree, contents.platlib_tree): + if isinstance(tree, Directory): + check_dir(tree) + + if conflicts: + return [FailedCheck(Check.W011, conflicts)] + return [] + def check_W101(self, contents: WheelContents) -> list[FailedCheck]: """ W101 — Wheel library is missing files in package tree diff --git a/src/check_wheel_contents/checks.py b/src/check_wheel_contents/checks.py index d630cfb..929005c 100644 --- a/src/check_wheel_contents/checks.py +++ b/src/check_wheel_contents/checks.py @@ -27,6 +27,7 @@ class Check(Enum): W102 = "Wheel library contains files not in package tree" W201 = "Wheel library is missing specified toplevel entry" W202 = "Wheel library has undeclared toplevel entry" + W011 = "Wheel library has multiple declared toplevel entries" @attr.s(auto_attribs=True) diff --git a/test/data/wheels/module_file_folder_shadow-0.1.0-py3-none-any.json b/test/data/wheels/module_file_folder_shadow-0.1.0-py3-none-any.json new file mode 100644 index 0000000..a99d057 --- /dev/null +++ b/test/data/wheels/module_file_folder_shadow-0.1.0-py3-none-any.json @@ -0,0 +1,5 @@ +{ + "stdout": "module_file_folder_shadow-0.1.0-py3-none-any.whl: W011: Wheel library has multiple declared toplevel entries:\n module_file_folder_shadow/foo/\n module_file_folder_shadow/foo/bar/", + "stderr": "", + "rc": 1 +} diff --git a/test/data/wheels/module_file_folder_shadow-0.1.0-py3-none-any.whl b/test/data/wheels/module_file_folder_shadow-0.1.0-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..521546dc7ddac79dd909a89f606dddb4f24bb241 GIT binary patch literal 1840 zcmWIWW@Zs#U|`??VnvU0C52Cq0a;9p3=Bp#nuYqBH(|Y;E*DKY7jde+ zTUNL`ymD< zvPMa`{=xf-rP6zw&OfqUy7XwDyOv+Tjq`mig*}}7vHixp>9Zu}bYVeY%^?zB zg_;WlN@JeQ68bmww^!-9J&X_D)z5xa#2SDSDn{n}MWcbC5e3BhB!x=2hpVd(_jwQB zvln^2b+yi&Ilno`;EM5sBLB1Ax?Vab^*04+c$~cI>*aIK@2q#=1%pe*S2kaG!gcDr z{>864*LXE_z0RKW0V>ke@_owX>BFwI-sIZZ)91af`kq<+goy#woj|8CFo6glPz7R~ zv8Nv&pP83g5+AQuP|1wP5Cy!3q~+%m(632IKd}x`A!txiVi5ty=n`WFJ_r4sc>eKw zpdlB4VQhfUFpSI*y%g@8m&$^BFb_$E7$M%X(2wv z->>J2tW%24%vdJ*a<69FrX;)RJF@DV=XMtzNOtDh=FnLEkY!!Qan5bAM=Q>El?L~h zez@E{>5to!AFpogGhf-Z$z|JmnYjY;k=GP%EVMekfJ1olx7fKo4pXl1{@t#5H}cx? z*v;Y-*Tk*+X`Z$1%F)cVorf>!95PV6{O3 zLk-t1uwS|RdxwL}Zj)9aqf?d|hxN7I?v-1*b93&Zn|=q3OOD>Kx-!-MGrQ3m_qf78 z^G~--d)ThVFk3pnn~_O`8F$$N3_&nh(g>n(rd5oO+rhw+MrT5%5$i}$ zCWL_{jXea7g=9&54h3aN7+BH>%2#;3tq(L2pJUN8D9q>vMp