Gentoo Archives: gentoo-commits

From: Arthur Zamarin <arthurzam@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/pkgcore/pkgcheck:master commit in: src/pkgcheck/checks/, ...
Date: Mon, 02 Jan 2023 20:19:07
Message-Id: 1672690303.4247e10d9c266ac1f6aac48b0c67f1092dde1d78.arthurzam@gentoo
1 commit: 4247e10d9c266ac1f6aac48b0c67f1092dde1d78
2 Author: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
3 AuthorDate: Fri Dec 30 19:27:23 2022 +0000
4 Commit: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
5 CommitDate: Mon Jan 2 20:11:43 2023 +0000
6 URL: https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=4247e10d
7
8 ProvidedEclassInherit: new check for inheriting provided eclases
9
10 Resolves: https://github.com/pkgcore/pkgcheck/issues/504
11 Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org>
12
13 src/pkgcheck/checks/eclass.py | 103 ++++++++++++++-------
14 .../ProvidedEclassInherit/expected.json | 1 +
15 .../ProvidedEclassInherit/fix.patch | 10 ++
16 .../ProvidedEclassInherit-0.ebuild | 11 +++
17 4 files changed, 93 insertions(+), 32 deletions(-)
18
19 diff --git a/src/pkgcheck/checks/eclass.py b/src/pkgcheck/checks/eclass.py
20 index 5c4f205f..862dbb91 100644
21 --- a/src/pkgcheck/checks/eclass.py
22 +++ b/src/pkgcheck/checks/eclass.py
23 @@ -98,18 +98,36 @@ class MisplacedEclassVar(results.LineResult, results.Error):
24 return f"invalid pre-inherit placement, line {self.lineno}: {self.line!r}"
25
26
27 +class ProvidedEclassInherit(results.LineResult, results.Style):
28 + """Ebuild inherits an eclass which is already provided by another eclass.
29 +
30 + When inheriting an eclass which declares ``@PROVIDES``, those referenced
31 + eclasses are guaranteed to be provided by the eclass. Therefore, inheriting
32 + them in ebuilds is redundant and should be removed.
33 + """
34 +
35 + def __init__(self, provider, **kwargs):
36 + super().__init__(**kwargs)
37 + self.provider = provider
38 +
39 + @property
40 + def desc(self):
41 + return f"line {self.lineno}: redundant eclass inherit {self.line!r}, provided by {self.provider!r}"
42 +
43 +
44 class EclassUsageCheck(Check):
45 """Scan packages for various eclass-related issues."""
46
47 _source = sources.EbuildParseRepoSource
48 known_results = frozenset(
49 - [
50 + {
51 DeprecatedEclass,
52 DeprecatedEclassVariable,
53 DeprecatedEclassFunction,
54 DuplicateEclassInherit,
55 MisplacedEclassVar,
56 - ]
57 + ProvidedEclassInherit,
58 + }
59 )
60 required_addons = (addons.eclass.EclassAddon,)
61
62 @@ -118,15 +136,16 @@ class EclassUsageCheck(Check):
63 self.deprecated_eclasses = eclass_addon.deprecated
64 self.eclass_cache = eclass_addon.eclasses
65
66 - def check_pre_inherits(self, pkg, inherits):
67 + def check_pre_inherits(self, pkg, inherits: list[tuple[list[str], int]]):
68 """Check for invalid @PRE_INHERIT variable placement."""
69 - pre_inherits = {}
70 # determine if any inherited eclasses have @PRE_INHERIT variables
71 - for eclasses, lineno in inherits:
72 - for eclass in eclasses:
73 - for var in self.eclass_cache[eclass].variables:
74 - if var.pre_inherit:
75 - pre_inherits[var.name] = lineno
76 + pre_inherits = {
77 + var.name: lineno
78 + for eclasses, lineno in inherits
79 + for eclass in eclasses
80 + for var in self.eclass_cache[eclass].variables
81 + if var.pre_inherit
82 + }
83
84 # scan for any misplaced @PRE_INHERIT variables
85 if pre_inherits:
86 @@ -137,22 +156,23 @@ class EclassUsageCheck(Check):
87 line = pkg.node_str(node)
88 yield MisplacedEclassVar(var_name, line=line, lineno=lineno + 1, pkg=pkg)
89
90 - def check_deprecated_variables(self, pkg, inherits):
91 - """Check for usage of @DEPRECATED variables or functions."""
92 - deprecated = {}
93 + def check_deprecated_variables(self, pkg, inherits: list[tuple[list[str], int]]):
94 + """Check for usage of @DEPRECATED variables."""
95 # determine if any inherited eclasses have @DEPRECATED variables
96 - for eclasses, _ in inherits:
97 - for eclass in eclasses:
98 - for var in self.eclass_cache[eclass].variables:
99 - if var.deprecated:
100 - deprecated[var.name] = var.deprecated
101 + deprecated = {
102 + var.name: var.deprecated
103 + for eclasses, _ in inherits
104 + for eclass in eclasses
105 + for var in self.eclass_cache[eclass].variables
106 + if var.deprecated
107 + }
108
109 # scan for usage of @DEPRECATED variables
110 if deprecated:
111 for node, _ in bash.var_query.captures(pkg.tree.root_node):
112 var_name = pkg.node_str(node)
113 - lineno, _colno = node.start_point
114 if var_name in deprecated:
115 + lineno, _colno = node.start_point
116 line = pkg.node_str(node)
117 replacement = deprecated[var_name]
118 if not isinstance(replacement, str):
119 @@ -161,22 +181,23 @@ class EclassUsageCheck(Check):
120 var_name, replacement, line=line, lineno=lineno + 1, pkg=pkg
121 )
122
123 - def check_deprecated_functions(self, pkg, inherits):
124 - """Check for usage of @DEPRECATED variables or functions."""
125 - deprecated = {}
126 - # determine if any inherited eclasses have @DEPRECATED variables or functions
127 - for eclasses, _ in inherits:
128 - for eclass in eclasses:
129 - for func in self.eclass_cache[eclass].functions:
130 - if func.deprecated:
131 - deprecated[func.name] = func.deprecated
132 + def check_deprecated_functions(self, pkg, inherits: list[tuple[list[str], int]]):
133 + """Check for usage of @DEPRECATED functions."""
134 + # determine if any inherited eclasses have @DEPRECATED functions
135 + deprecated = {
136 + func.name: func.deprecated
137 + for eclasses, _ in inherits
138 + for eclass in eclasses
139 + for func in self.eclass_cache[eclass].functions
140 + if func.deprecated
141 + }
142
143 # scan for usage of @DEPRECATED functions
144 if deprecated:
145 for node, _ in bash.cmd_query.captures(pkg.tree.root_node):
146 func_name = pkg.node_str(node.child_by_field_name("name"))
147 - lineno, _colno = node.start_point
148 if func_name in deprecated:
149 + lineno, _colno = node.start_point
150 line = pkg.node_str(node)
151 replacement = deprecated[func_name]
152 if not isinstance(replacement, str):
153 @@ -185,10 +206,22 @@ class EclassUsageCheck(Check):
154 func_name, replacement, line=line, lineno=lineno + 1, pkg=pkg
155 )
156
157 + def check_provided_eclasses(self, pkg, inherits: list[tuple[list[str], int]]):
158 + """Check for usage of eclasses (i.e. redundant inherits) that are
159 + provided by another inherited eclass."""
160 + provided_eclasses = {
161 + provided: (eclass, lineno + 1)
162 + for eclasses, lineno in inherits
163 + for eclass in eclasses
164 + for provided in pkg.inherit.intersection(self.eclass_cache[eclass].provides)
165 + }
166 + for provided, (eclass, lineno) in provided_eclasses.items():
167 + yield ProvidedEclassInherit(eclass, pkg=pkg, line=provided, lineno=lineno)
168 +
169 def feed(self, pkg):
170 if pkg.inherit:
171 inherited = set()
172 - inherits = []
173 + inherits: list[tuple[list[str], int]] = []
174 for node, _ in bash.cmd_query.captures(pkg.tree.root_node):
175 name = pkg.node_str(node.child_by_field_name("name"))
176 if name == "inherit":
177 @@ -207,6 +240,7 @@ class EclassUsageCheck(Check):
178 eclass, line=call, lineno=lineno + 1, pkg=pkg
179 )
180
181 + yield from self.check_provided_eclasses(pkg, inherits)
182 # verify @PRE_INHERIT variable placement
183 yield from self.check_pre_inherits(pkg, inherits)
184 # verify @DEPRECATED variables or functions
185 @@ -281,7 +315,7 @@ class EclassParseCheck(Check):
186 for var_node, _ in bash.var_query.captures(func_node):
187 var_name = eclass.node_str(var_node)
188 if var_name in variables:
189 - lineno, colno = var_node.start_point
190 + lineno, _colno = var_node.start_point
191 usage[var_name].add(lineno + 1)
192 for var, lines in sorted(usage.items()):
193 yield EclassVariableScope(
194 @@ -369,7 +403,12 @@ class EclassCheck(Check):
195
196 _source = sources.EclassRepoSource
197 known_results = frozenset(
198 - [EclassBashSyntaxError, EclassDocError, EclassDocMissingFunc, EclassDocMissingVar]
199 + [
200 + EclassBashSyntaxError,
201 + EclassDocError,
202 + EclassDocMissingFunc,
203 + EclassDocMissingVar,
204 + ]
205 )
206
207 def __init__(self, *args):
208 @@ -393,7 +432,7 @@ class EclassCheck(Check):
209 lineno = 0
210 error = []
211 for line in p.stderr.splitlines():
212 - path, line, msg = line.split(": ", 2)
213 + _path, line, msg = line.split(": ", 2)
214 lineno = line[5:]
215 error.append(msg.strip("\n"))
216 error = ": ".join(error)
217
218 diff --git a/testdata/data/repos/eclass/EclassUsageCheck/ProvidedEclassInherit/expected.json b/testdata/data/repos/eclass/EclassUsageCheck/ProvidedEclassInherit/expected.json
219 new file mode 100644
220 index 00000000..397c0644
221 --- /dev/null
222 +++ b/testdata/data/repos/eclass/EclassUsageCheck/ProvidedEclassInherit/expected.json
223 @@ -0,0 +1 @@
224 +{"__class__": "ProvidedEclassInherit", "category": "EclassUsageCheck", "package": "ProvidedEclassInherit", "version": "0", "line": "inherit", "lineno": 2, "provider": "deep-provided-inherit"}
225
226 diff --git a/testdata/data/repos/eclass/EclassUsageCheck/ProvidedEclassInherit/fix.patch b/testdata/data/repos/eclass/EclassUsageCheck/ProvidedEclassInherit/fix.patch
227 new file mode 100644
228 index 00000000..607e8caf
229 --- /dev/null
230 +++ b/testdata/data/repos/eclass/EclassUsageCheck/ProvidedEclassInherit/fix.patch
231 @@ -0,0 +1,10 @@
232 +diff -Naur eclass/EclassUsageCheck/ProvidedEclassInherit/ProvidedEclassInherit-0.ebuild fixed/EclassUsageCheck/ProvidedEclassInherit/ProvidedEclassInherit-0.ebuild
233 +--- eclass/EclassUsageCheck/ProvidedEclassInherit/ProvidedEclassInherit-0.ebuild 2021-05-23 20:23:16.423009026 -0600
234 ++++ fixed/EclassUsageCheck/ProvidedEclassInherit/ProvidedEclassInherit-0.ebuild 2021-05-23 20:23:43.734588313 -0600
235 +@@ -1,5 +1,5 @@
236 + EAPI=7
237 +-inherit inherit deep-provided-inherit
238 ++inherit deep-provided-inherit
239 + DESCRIPTION="Ebuild inheriting provided eclass"
240 + HOMEPAGE="https://github.com/pkgcore/pkgcheck"
241 + SLOT="0"
242
243 diff --git a/testdata/repos/eclass/EclassUsageCheck/ProvidedEclassInherit/ProvidedEclassInherit-0.ebuild b/testdata/repos/eclass/EclassUsageCheck/ProvidedEclassInherit/ProvidedEclassInherit-0.ebuild
244 new file mode 100644
245 index 00000000..cd8585ea
246 --- /dev/null
247 +++ b/testdata/repos/eclass/EclassUsageCheck/ProvidedEclassInherit/ProvidedEclassInherit-0.ebuild
248 @@ -0,0 +1,11 @@
249 +EAPI=7
250 +inherit inherit deep-provided-inherit
251 +DESCRIPTION="Ebuild inheriting provided eclass"
252 +HOMEPAGE="https://github.com/pkgcore/pkgcheck"
253 +SLOT="0"
254 +LICENSE="BSD"
255 +
256 +src_prepare() {
257 + inherit_public_func
258 + deep-provided-inherit_public_func
259 +}