diff --git a/src/pkgcheck/checks/python.py b/src/pkgcheck/checks/python.py index 1f260c42d..a8960372d 100644 --- a/src/pkgcheck/checks/python.py +++ b/src/pkgcheck/checks/python.py @@ -1,8 +1,11 @@ +from collections import defaultdict import itertools import re from pkgcore import fetch from pkgcore.ebuild.atom import atom +from pkgcore.ebuild.conditionals import DepSet +from pkgcore.ebuild.errors import DepsetParseError from pkgcore.restrictions import packages, values from pkgcore.restrictions.boolean import JustOneRestriction, OrRestriction from snakeoil.sequences import iflatten_instance @@ -32,6 +35,7 @@ GITHUB_ARCHIVE_RE = re.compile(r'^https://github\.com/[^/]+/[^/]+/archive/') SNAPSHOT_RE = re.compile(r'[a-fA-F0-9]{40}\.tar\.gz$') +USE_FLAGS_PYTHON_USEDEP = re.compile(r'\[(.+,)?\$\{PYTHON_USEDEP\}(,.+)?\]$') def get_python_eclass(pkg): @@ -467,3 +471,207 @@ def feed(self, pkg): if GITHUB_ARCHIVE_RE.match(uri): yield PythonGHDistfileSuffix(f.filename, uri, pkg=pkg) break + + +class PythonHasVersionUsage(results.VersionResult, results.Style): + """Package uses has_version inside ``python_check_deps``. + + Ebuilds which declare the ``python_check_deps`` function (which tests + Python implementations for matching dependencies) should use the special + ``python_has_version`` function (instead of ``has_version``) for enhanced + log output and defaults [#]_. + + .. [#] https://projects.gentoo.org/python/guide/any.html#dependencies + """ + + def __init__(self, lines, **kwargs): + super().__init__(**kwargs) + self.lines = tuple(lines) + + @property + def desc(self): + s = pluralism(self.lines) + lines = ', '.join(map(str, self.lines)) + return f'usage of has_version on line{s}: {lines}, replace with python_has_version' + + +class PythonHasVersionMissingPythonUseDep(results.LineResult, results.Error): + """Package calls ``python_has_version`` or ``has_version`` without + ``[${PYTHON_USEDEP}]`` suffix. + + All calls to ``python_has_version`` or ``has_version`` inside + ``python_check_deps`` should contain ``[${PYTHON_USEDEP}]`` suffix for the + dependency argument [#]_. + + .. [#] https://projects.gentoo.org/python/guide/any.html#dependencies + """ + + @property + def desc(self): + return f'line: {self.lineno}: missing [${{PYTHON_USEDEP}}] suffix for argument "{self.line}"' + + +class PythonAnyMismatchedUseHasVersionCheck(results.VersionResult, results.Warning): + """Package has mismatch in dependency's use flags between call to + ``python_gen_any_dep`` and ``python_has_version``. + + For every dependency used under ``python_gen_any_dep``, the check for a + matching python implementation in ``python_has_version`` should match the + exact use flags. + + .. [#] https://projects.gentoo.org/python/guide/any.html#dependencies + """ + + def __init__(self, dep_category, dep_atom, use_flags, location, **kwargs): + super().__init__(**kwargs) + self.dep_category = dep_category + self.dep_atom = dep_atom + self.use_flags = tuple(use_flags) + self.location = location + + @property + def desc(self): + s = pluralism(self.use_flags) + use_flags = ', '.join(map(str, self.use_flags)) + return f'{self.dep_category}: mismatch for {self.dep_atom} check use flag{s} [{use_flags}] in {self.location}' + + +class PythonAnyMismatchedDepHasVersionCheck(results.VersionResult, results.Warning): + """Package has mismatch in dependencies between call to + ``python_gen_any_dep`` and ``python_has_version``. + + For every dependency used under ``python_gen_any_dep``, a matching check + for a matching python implementation in ``python_has_version`` should + exist. + + .. [#] https://projects.gentoo.org/python/guide/any.html#dependencies + """ + + def __init__(self, dep_category, dep_atom, use_flags, location, **kwargs): + super().__init__(**kwargs) + self.dep_category = dep_category + self.dep_atom = dep_atom + self.use_flags = tuple(use_flags) + self.location = location + + @property + def desc(self): + use_flags = ', '.join(map(str, self.use_flags)) + return f'{self.dep_category}: missing check for {self.dep_atom}[{use_flags}] in {self.location}' + + +class PythonWrongUsageCheck(Check): + """Check ebuilds for wrong usage of Python eclasses features. + + This check parses the ebuild and checks for more advanced failures/misuses + of API. + """ + + _source = sources.EbuildParseRepoSource + known_results = frozenset({ + PythonHasVersionUsage, + PythonHasVersionMissingPythonUseDep, + PythonAnyMismatchedUseHasVersionCheck, + PythonAnyMismatchedDepHasVersionCheck, + }) + + has_version_known_flags = { + '-b': 'BDEPEND', + '-r': 'RDEPEND', + '-d': 'DEPEND', + '--host-root': 'BDEPEND', + } + + has_version_default = { + 'has_version': 'DEPEND', + 'python_has_version': 'BDEPEND', + } + + @staticmethod + def _prepare_deps(deps: str): + try: + deps_str = deps.strip('\"\'').replace('\\$', '$').replace('${PYTHON_USEDEP}', 'pkgcheck_python_usedep') + return iflatten_instance(DepSet.parse(deps_str, atom), atom) + except DepsetParseError: + # if we are unable to parse that dep's string, skip it + return () + + + def build_python_gen_any_dep_calls(self, pkg): + check_deps = defaultdict(set) + for var_node in pkg.global_query(bash.var_assign_query): + name = pkg.node_str(var_node.child_by_field_name('name')) + if name in {'DEPEND', 'BDEPEND'}: + for call_node, _ in bash.cmd_query.captures(var_node): + call_name = pkg.node_str(call_node.child_by_field_name('name')) + if call_name == "python_gen_any_dep" and len(call_node.children) > 1: + check_deps[name].update(self._prepare_deps( + pkg.node_str(call_node.children[1]))) + return {dep: frozenset(atoms) for dep, atoms in check_deps.items()} + + def report_mismatch_check_deps(self, pkg, python_check_deps, has_version_checked_deps): + for dep_type in frozenset(python_check_deps.keys()).union( + has_version_checked_deps.keys()): + extra = has_version_checked_deps[dep_type] - python_check_deps.get(dep_type, set()) + missing = python_check_deps.get(dep_type, set()) - has_version_checked_deps[dep_type] + for diff, other, location in ( + (extra, missing, "python_check_deps"), + (missing, extra, "python_gen_any_dep"), + ): + for dep in diff: + dep_atom = str(dep.versioned_atom) + for other_dep in other: + if dep_atom == str(other_dep.versioned_atom): + if diff_flags := set(other_dep.use) - set(dep.use): + yield PythonAnyMismatchedUseHasVersionCheck(pkg=pkg, + dep_category=dep_type, dep_atom=dep_atom, + use_flags=diff_flags, location=location) + break + else: + use_flags = {'${PYTHON_USEDEP}'} | set(dep.use) \ + - {'pkgcheck_python_usedep'} + yield PythonAnyMismatchedDepHasVersionCheck(pkg=pkg, + dep_category=dep_type, dep_atom=dep_atom, + use_flags=use_flags, location=location) + + @staticmethod + def _prepare_dep_type(pkg, dep_type: str) -> str: + if dep_type == 'BDEPEND' not in pkg.eapi.dep_keys: + return 'DEPEND' + return dep_type + + def check_python_check_deps(self, pkg, func_node, python_check_deps): + has_version_checked_deps = defaultdict(set) + has_version_lines = set() + for node, _ in bash.cmd_query.captures(func_node): + call_name = pkg.node_str(node.child_by_field_name('name')) + if call_name == "has_version": + lineno, _ = node.start_point + has_version_lines.add(lineno + 1) + if dep_mode := self.has_version_default.get(call_name, None): + dep_mode = self._prepare_dep_type(pkg, dep_mode) + for arg in node.children[1:]: + arg_name = pkg.node_str(arg) + if new_dep_mode := self.has_version_known_flags.get(arg_name, None): + dep_mode = self._prepare_dep_type(pkg, new_dep_mode) + else: + arg_name = arg_name.strip('\"\'') + if not USE_FLAGS_PYTHON_USEDEP.search(arg_name): + lineno, _ = arg.start_point + yield PythonHasVersionMissingPythonUseDep( + lineno=lineno+1, line=arg_name, pkg=pkg) + else: + has_version_checked_deps[dep_mode].update( + self._prepare_deps(arg_name)) + + if has_version_lines: + yield PythonHasVersionUsage(lines=sorted(has_version_lines), pkg=pkg) + + yield from self.report_mismatch_check_deps(pkg, python_check_deps, has_version_checked_deps) + + def feed(self, pkg): + python_check_deps = self.build_python_gen_any_dep_calls(pkg) + for func_node, _ in bash.func_query.captures(pkg.tree.root_node): + func_name = pkg.node_str(func_node.child_by_field_name('name')) + if func_name == "python_check_deps": + yield from self.check_python_check_deps(pkg, func_node, python_check_deps) diff --git a/testdata/data/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/expected.json b/testdata/data/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/expected.json new file mode 100644 index 000000000..b23abc431 --- /dev/null +++ b/testdata/data/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/expected.json @@ -0,0 +1,6 @@ +{"__class__": "PythonHasVersionUsage", "category": "PythonWrongUsageCheck", "package": "PythonAnyMismatchedDepHasVersionCheck", "version": "0", "lines": [35, 36]} +{"__class__": "PythonAnyMismatchedDepHasVersionCheck", "category": "PythonWrongUsageCheck", "package": "PythonAnyMismatchedDepHasVersionCheck", "version": "0", "dep_category": "BDEPEND", "dep_atom": "dev-python/flit_core", "use_flags": ["${PYTHON_USEDEP}"], "location": "python_check_deps"} +{"__class__": "PythonAnyMismatchedDepHasVersionCheck", "category": "PythonWrongUsageCheck", "package": "PythonAnyMismatchedDepHasVersionCheck", "version": "0", "dep_category": "BDEPEND", "dep_atom": "dev-python/lxml", "use_flags": ["${PYTHON_USEDEP}"], "location": "python_gen_any_dep"} +{"__class__": "PythonAnyMismatchedDepHasVersionCheck", "category": "PythonWrongUsageCheck", "package": "PythonAnyMismatchedDepHasVersionCheck", "version": "0", "dep_category": "DEPEND", "dep_atom": "dev-python/flit_core", "use_flags": ["${PYTHON_USEDEP}"], "location": "python_gen_any_dep"} +{"__class__": "PythonAnyMismatchedDepHasVersionCheck", "category": "PythonWrongUsageCheck", "package": "PythonAnyMismatchedDepHasVersionCheck", "version": "0", "dep_category": "DEPEND", "dep_atom": "dev-python/lxml", "use_flags": ["${PYTHON_USEDEP}"], "location": "python_check_deps"} +{"__class__": "PythonAnyMismatchedDepHasVersionCheck", "category": "PythonWrongUsageCheck", "package": "PythonAnyMismatchedDepHasVersionCheck", "version": "0", "dep_category": "RDEPEND", "dep_atom": "dev-python/lxml", "use_flags": ["${PYTHON_USEDEP}"], "location": "python_check_deps"} diff --git a/testdata/data/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/fix.patch b/testdata/data/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/fix.patch new file mode 100644 index 000000000..20f5fafd7 --- /dev/null +++ b/testdata/data/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/fix.patch @@ -0,0 +1,28 @@ +diff -dupr python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/PythonAnyMismatchedDepHasVersionCheck-0.ebuild fixed/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/PythonAnyMismatchedDepHasVersionCheck-0.ebuild +index a70a4d3e..21db4ebf 100644 +--- python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/PythonAnyMismatchedDepHasVersionCheck-0.ebuild ++++ fixed/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/PythonAnyMismatchedDepHasVersionCheck-0.ebuild +@@ -32,8 +32,7 @@ BDEPEND="${PYTHON_DEPS} + + python_check_deps() { + use test || return 1 +- has_version "dev-python/lxml[${PYTHON_USEDEP}]" && +- has_version -r "dev-python/lxml[${PYTHON_USEDEP}]" && ++ python_has_version "dev-python/lxml[${PYTHON_USEDEP}]" && + python_has_version "dev-python/gpep517[${PYTHON_USEDEP}]" && +- python_has_version "dev-python/flit_core[${PYTHON_USEDEP}]" ++ python_has_version -d "dev-python/flit_core[${PYTHON_USEDEP}]" + } +diff -dupr python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/PythonHasVersionMissingPythonUseDep-0.ebuild fixed/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/PythonHasVersionMissingPythonUseDep-0.ebuild +index 24ebb878..48f4ae11 100644 +--- python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/PythonHasVersionMissingPythonUseDep-0.ebuild ++++ fixed/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/PythonHasVersionMissingPythonUseDep-0.ebuild +@@ -22,6 +22,6 @@ BDEPEND="${PYTHON_DEPS} + " + + python_check_deps() { +- has_version -b "dev-python/lxml" && +- python_has_version "dev-python/gpep517" ++ python_has_version "dev-python/lxml[${PYTHON_USEDEP}]" && ++ python_has_version "dev-python/gpep517[${PYTHON_USEDEP}]" + } diff --git a/testdata/data/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/expected.json b/testdata/data/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/expected.json new file mode 100644 index 000000000..e718bb830 --- /dev/null +++ b/testdata/data/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/expected.json @@ -0,0 +1,4 @@ +{"__class__": "PythonAnyMismatchedUseHasVersionCheck", "category": "PythonWrongUsageCheck", "package": "PythonAnyMismatchedUseHasVersionCheck", "version": "0", "dep_category": "BDEPEND", "dep_atom": "dev-python/gpep517", "use_flags": ["xml"], "location": "python_gen_any_dep"} +{"__class__": "PythonAnyMismatchedUseHasVersionCheck", "category": "PythonWrongUsageCheck", "package": "PythonAnyMismatchedUseHasVersionCheck", "version": "0", "dep_category": "BDEPEND", "dep_atom": "dev-python/lxml", "use_flags": ["threads"], "location": "python_check_deps"} +{"__class__": "PythonAnyMismatchedUseHasVersionCheck", "category": "PythonWrongUsageCheck", "package": "PythonAnyMismatchedUseHasVersionCheck", "version": "1", "dep_category": "BDEPEND", "dep_atom": "dev-python/flit", "use_flags": ["threads"], "location": "python_gen_any_dep"} +{"__class__": "PythonAnyMismatchedUseHasVersionCheck", "category": "PythonWrongUsageCheck", "package": "PythonAnyMismatchedUseHasVersionCheck", "version": "1", "dep_category": "BDEPEND", "dep_atom": "dev-python/gpep517", "use_flags": ["xml"], "location": "python_check_deps"} diff --git a/testdata/data/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/fix.patch b/testdata/data/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/fix.patch new file mode 100644 index 000000000..e2c61061d --- /dev/null +++ b/testdata/data/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/fix.patch @@ -0,0 +1,37 @@ +diff -dupr a/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-0.ebuild b/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-0.ebuild +index 52e24cab..f2040c7b 100644 +--- python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-0.ebuild ++++ fixed/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-0.ebuild +@@ -17,11 +17,11 @@ DEPEND="${PYTHON_DEPS}" + BDEPEND="${PYTHON_DEPS} + $(python_gen_any_dep ' + dev-python/lxml[${PYTHON_USEDEP},threads] +- dev-python/gpep517[${PYTHON_USEDEP}] ++ dev-python/gpep517[${PYTHON_USEDEP},xml] + ') + " + + python_check_deps() { +- python_has_version "dev-python/lxml[${PYTHON_USEDEP}]" && ++ python_has_version "dev-python/lxml[${PYTHON_USEDEP},threads]" && + python_has_version "dev-python/gpep517[${PYTHON_USEDEP},xml]" + } +diff -dupr python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-1.ebuild fixed/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-1.ebuild +index d34cef22..f2040c7b 100644 +--- python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-1.ebuild ++++ fixed/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-1.ebuild +@@ -16,12 +16,12 @@ SLOT="0" + DEPEND="${PYTHON_DEPS}" + BDEPEND="${PYTHON_DEPS} + $(python_gen_any_dep ' +- dev-python/flit[${PYTHON_USEDEP}] ++ dev-python/flit[${PYTHON_USEDEP},threads] + dev-python/gpep517[${PYTHON_USEDEP},xml] + ') + " + + python_check_deps() { + python_has_version "dev-python/flit[${PYTHON_USEDEP},threads]" && +- python_has_version "dev-python/gpep517[${PYTHON_USEDEP}]" ++ python_has_version "dev-python/gpep517[${PYTHON_USEDEP},xml]" + } diff --git a/testdata/data/repos/python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/expected.json b/testdata/data/repos/python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/expected.json new file mode 100644 index 000000000..130abd049 --- /dev/null +++ b/testdata/data/repos/python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/expected.json @@ -0,0 +1,5 @@ +{"__class__": "PythonHasVersionMissingPythonUseDep", "category": "PythonWrongUsageCheck", "package": "PythonHasVersionMissingPythonUseDep", "version": "0", "line": "dev-python/lxml", "lineno": 25} +{"__class__": "PythonHasVersionMissingPythonUseDep", "category": "PythonWrongUsageCheck", "package": "PythonHasVersionMissingPythonUseDep", "version": "0", "line": "dev-python/gpep517", "lineno": 26} +{"__class__": "PythonHasVersionUsage", "category": "PythonWrongUsageCheck", "package": "PythonHasVersionMissingPythonUseDep", "version": "0", "lines": [25]} +{"__class__": "PythonAnyMismatchedDepHasVersionCheck", "category": "PythonWrongUsageCheck", "package": "PythonHasVersionMissingPythonUseDep", "version": "0", "dep_category": "BDEPEND", "dep_atom": "dev-python/gpep517", "use_flags": ["${PYTHON_USEDEP}"], "location": "python_gen_any_dep"} +{"__class__": "PythonAnyMismatchedDepHasVersionCheck", "category": "PythonWrongUsageCheck", "package": "PythonHasVersionMissingPythonUseDep", "version": "0", "dep_category": "BDEPEND", "dep_atom": "dev-python/lxml", "use_flags": ["${PYTHON_USEDEP}"], "location": "python_gen_any_dep"} diff --git a/testdata/data/repos/python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/fix.patch b/testdata/data/repos/python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/fix.patch new file mode 100644 index 000000000..cb34f7bba --- /dev/null +++ b/testdata/data/repos/python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/fix.patch @@ -0,0 +1,13 @@ +diff -dupr a/python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/PythonHasVersionMissingPythonUseDep-0.ebuild fixed/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/PythonHasVersionMissingPythonUseDep-0.ebuild +index 24ebb878..48f4ae11 100644 +--- python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/PythonHasVersionMissingPythonUseDep-0.ebuild ++++ fixed/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/PythonHasVersionMissingPythonUseDep-0.ebuild +@@ -22,6 +22,6 @@ BDEPEND="${PYTHON_DEPS} + " + + python_check_deps() { +- has_version -b "dev-python/lxml" && +- python_has_version "dev-python/gpep517" ++ python_has_version "dev-python/lxml[${PYTHON_USEDEP}]" && ++ python_has_version "dev-python/gpep517[${PYTHON_USEDEP}]" + } diff --git a/testdata/data/repos/python/PythonWrongUsageCheck/PythonHasVersionUsage/expected.json b/testdata/data/repos/python/PythonWrongUsageCheck/PythonHasVersionUsage/expected.json new file mode 100644 index 000000000..06234ba85 --- /dev/null +++ b/testdata/data/repos/python/PythonWrongUsageCheck/PythonHasVersionUsage/expected.json @@ -0,0 +1,2 @@ +{"__class__": "PythonHasVersionUsage", "category": "PythonWrongUsageCheck", "package": "PythonHasVersionUsage", "version": "0", "lines": [24]} +{"__class__": "PythonHasVersionUsage", "category": "PythonWrongUsageCheck", "package": "PythonHasVersionUsage", "version": "1", "lines": [25, 26]} diff --git a/testdata/data/repos/python/PythonWrongUsageCheck/PythonHasVersionUsage/fix.patch b/testdata/data/repos/python/PythonWrongUsageCheck/PythonHasVersionUsage/fix.patch new file mode 100644 index 000000000..2b017c8d4 --- /dev/null +++ b/testdata/data/repos/python/PythonWrongUsageCheck/PythonHasVersionUsage/fix.patch @@ -0,0 +1,52 @@ +diff -dupr python/PythonWrongUsageCheck/PythonHasVersionUsage/PythonHasVersionUsage-0.ebuild fixed/PythonWrongUsageCheck/PythonHasVersionUsage/PythonHasVersionUsage-0.ebuild +index face1460..d8f40dd7 100644 +--- python/PythonWrongUsageCheck/PythonHasVersionUsage/PythonHasVersionUsage-0.ebuild ++++ fixed/PythonWrongUsageCheck/PythonHasVersionUsage/PythonHasVersionUsage-0.ebuild +@@ -21,5 +21,5 @@ BDEPEND="${PYTHON_DEPS} + " + + python_check_deps() { +- has_version -b "dev-python/lxml[${PYTHON_USEDEP}]" ++ python_has_version "dev-python/lxml[${PYTHON_USEDEP}]" + } +diff -dupr python/PythonWrongUsageCheck/PythonHasVersionUsage/PythonHasVersionUsage-1.ebuild fixed/PythonWrongUsageCheck/PythonHasVersionUsage/PythonHasVersionUsage-1.ebuild +index 240f5364..48f4ae11 100644 +--- python/PythonWrongUsageCheck/PythonHasVersionUsage/PythonHasVersionUsage-1.ebuild ++++ fixed/PythonWrongUsageCheck/PythonHasVersionUsage/PythonHasVersionUsage-1.ebuild +@@ -22,6 +22,6 @@ BDEPEND="${PYTHON_DEPS} + " + + python_check_deps() { +- has_version -b "dev-python/lxml[${PYTHON_USEDEP}]" && +- has_version -b "dev-python/gpep517[${PYTHON_USEDEP}]" ++ python_has_version "dev-python/lxml[${PYTHON_USEDEP}]" && ++ python_has_version "dev-python/gpep517[${PYTHON_USEDEP}]" + } +diff -dupr a/python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/PythonHasVersionMissingPythonUseDep-0.ebuild b/python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/PythonHasVersionMissingPythonUseDep-0.ebuild +index 24ebb878..48f4ae11 100644 +--- python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/PythonHasVersionMissingPythonUseDep-0.ebuild ++++ fixed/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/PythonHasVersionMissingPythonUseDep-0.ebuild +@@ -22,6 +22,6 @@ BDEPEND="${PYTHON_DEPS} + " + + python_check_deps() { +- has_version -b "dev-python/lxml" && +- python_has_version "dev-python/gpep517" ++ python_has_version "dev-python/lxml[${PYTHON_USEDEP}]" && ++ python_has_version "dev-python/gpep517[${PYTHON_USEDEP}]" + } +diff -dupr python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/PythonAnyMismatchedDepHasVersionCheck-0.ebuild fixed/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/PythonAnyMismatchedDepHasVersionCheck-0.ebuild +index a70a4d3e..21db4ebf 100644 +--- python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/PythonAnyMismatchedDepHasVersionCheck-0.ebuild ++++ fixed/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/PythonAnyMismatchedDepHasVersionCheck-0.ebuild +@@ -32,8 +32,7 @@ BDEPEND="${PYTHON_DEPS} + + python_check_deps() { + use test || return 1 +- has_version "dev-python/lxml[${PYTHON_USEDEP}]" && +- has_version -r "dev-python/lxml[${PYTHON_USEDEP}]" && ++ python_has_version "dev-python/lxml[${PYTHON_USEDEP}]" && + python_has_version "dev-python/gpep517[${PYTHON_USEDEP}]" && +- python_has_version "dev-python/flit_core[${PYTHON_USEDEP}]" ++ python_has_version -d "dev-python/flit_core[${PYTHON_USEDEP}]" + } diff --git a/testdata/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/PythonAnyMismatchedDepHasVersionCheck-0.ebuild b/testdata/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/PythonAnyMismatchedDepHasVersionCheck-0.ebuild new file mode 100644 index 000000000..a70a4d3e5 --- /dev/null +++ b/testdata/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/PythonAnyMismatchedDepHasVersionCheck-0.ebuild @@ -0,0 +1,39 @@ +# Copyright 2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +PYTHON_COMPAT=( python3_10 ) + +inherit python-any-r1 + +DESCRIPTION="Ebuild that uses has_version" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" + +LICENSE="BSD" +SLOT="0" + +RDEPEND=" + $(python_gen_cond_dep ' + dev-python/flit_core[${PYTHON_USEDEP}] + ' 3.10) +" +DEPEND="${PYTHON_DEPS} + $(python_gen_any_dep ' + dev-python/flit_core[${PYTHON_USEDEP}] + ') +" +BDEPEND="${PYTHON_DEPS} + $(python_gen_any_dep ' + dev-python/lxml[${PYTHON_USEDEP}] + dev-python/gpep517[${PYTHON_USEDEP}] + ') +" + +python_check_deps() { + use test || return 1 + has_version "dev-python/lxml[${PYTHON_USEDEP}]" && + has_version -r "dev-python/lxml[${PYTHON_USEDEP}]" && + python_has_version "dev-python/gpep517[${PYTHON_USEDEP}]" && + python_has_version "dev-python/flit_core[${PYTHON_USEDEP}]" +} diff --git a/testdata/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/PythonAnyMismatchedDepHasVersionCheck-1.ebuild b/testdata/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/PythonAnyMismatchedDepHasVersionCheck-1.ebuild new file mode 100644 index 000000000..2652cf8c1 --- /dev/null +++ b/testdata/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedDepHasVersionCheck/PythonAnyMismatchedDepHasVersionCheck-1.ebuild @@ -0,0 +1,24 @@ +# Copyright 2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=6 + +PYTHON_COMPAT=( python3_10 ) + +inherit python-any-r1 + +DESCRIPTION="Ebuild that uses has_version" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" + +LICENSE="BSD" +SLOT="0" + +DEPEND="${PYTHON_DEPS} + $(python_gen_any_dep ' + dev-python/flit_core[${PYTHON_USEDEP}] + ') +" + +python_check_deps() { + python_has_version "dev-python/flit_core[${PYTHON_USEDEP}]" +} diff --git a/testdata/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-0.ebuild b/testdata/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-0.ebuild new file mode 100644 index 000000000..e1b1c707e --- /dev/null +++ b/testdata/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-0.ebuild @@ -0,0 +1,27 @@ +# Copyright 2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +PYTHON_COMPAT=( python3_10 ) + +inherit python-any-r1 + +DESCRIPTION="Ebuild that uses has_version" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" + +LICENSE="BSD" +SLOT="0" + +DEPEND="${PYTHON_DEPS}" +BDEPEND="${PYTHON_DEPS} + $(python_gen_any_dep ' + dev-python/lxml[${PYTHON_USEDEP},threads] + dev-python/gpep517[${PYTHON_USEDEP}] + ') +" + +python_check_deps() { + python_has_version "dev-python/lxml[${PYTHON_USEDEP}]" && + python_has_version "dev-python/gpep517[${PYTHON_USEDEP},xml]" +} diff --git a/testdata/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-1.ebuild b/testdata/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-1.ebuild new file mode 100644 index 000000000..616bcd955 --- /dev/null +++ b/testdata/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-1.ebuild @@ -0,0 +1,27 @@ +# Copyright 2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +PYTHON_COMPAT=( python3_10 ) + +inherit python-any-r1 + +DESCRIPTION="Ebuild that uses has_version" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" + +LICENSE="BSD" +SLOT="0" + +DEPEND="${PYTHON_DEPS}" +BDEPEND="${PYTHON_DEPS} + $(python_gen_any_dep ' + dev-python/flit[${PYTHON_USEDEP}] + dev-python/gpep517[${PYTHON_USEDEP},xml] + ') +" + +python_check_deps() { + python_has_version "dev-python/flit[${PYTHON_USEDEP},threads]" && + python_has_version "dev-python/gpep517[${PYTHON_USEDEP}]" +} diff --git a/testdata/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-2.ebuild b/testdata/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-2.ebuild new file mode 100644 index 000000000..0f011b363 --- /dev/null +++ b/testdata/repos/python/PythonWrongUsageCheck/PythonAnyMismatchedUseHasVersionCheck/PythonAnyMismatchedUseHasVersionCheck-2.ebuild @@ -0,0 +1,38 @@ +# Copyright 2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +PYTHON_COMPAT=( python3_10 ) + +inherit python-any-r1 + +DESCRIPTION="Ebuild that uses has_version" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" + +LICENSE="BSD" +SLOT="0" + +# In this file I check edge cases for the parser: +# - no args for $(python_gen_any_dep) +# - usage of \$ is replaced with $ +# - unable to parse atom (because of ${PV}) - skip the check for it + +DEPEND="${PYTHON_DEPS}" +BDEPEND="${PYTHON_DEPS} + $(python_gen_any_dep) + $(python_gen_any_dep " + dev-python/mako[\${PYTHON_USEDEP}] + ") + $(python_gen_any_dep " + dev-python/tempest[\${PYTHON_USEDEP}] + ~dev-python/lit-${PV}[\${PYTHON_USEDEP}] + ") +" + +dummy() { :; } + +python_check_deps() { + python_has_version "dev-python/mako[${PYTHON_USEDEP}]" + # won't report tempest & lit as unable to parse atom string +} diff --git a/testdata/repos/python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/PythonHasVersionMissingPythonUseDep-0.ebuild b/testdata/repos/python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/PythonHasVersionMissingPythonUseDep-0.ebuild new file mode 100644 index 000000000..24ebb8780 --- /dev/null +++ b/testdata/repos/python/PythonWrongUsageCheck/PythonHasVersionMissingPythonUseDep/PythonHasVersionMissingPythonUseDep-0.ebuild @@ -0,0 +1,27 @@ +# Copyright 2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +PYTHON_COMPAT=( python3_10 ) + +inherit python-any-r1 + +DESCRIPTION="Ebuild that uses has_version" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" + +LICENSE="BSD" +SLOT="0" + +DEPEND="${PYTHON_DEPS}" +BDEPEND="${PYTHON_DEPS} + $(python_gen_any_dep ' + dev-python/lxml[${PYTHON_USEDEP}] + dev-python/gpep517[${PYTHON_USEDEP}] + ') +" + +python_check_deps() { + has_version -b "dev-python/lxml" && + python_has_version "dev-python/gpep517" +} diff --git a/testdata/repos/python/PythonWrongUsageCheck/PythonHasVersionUsage/PythonHasVersionUsage-0.ebuild b/testdata/repos/python/PythonWrongUsageCheck/PythonHasVersionUsage/PythonHasVersionUsage-0.ebuild new file mode 100644 index 000000000..face1460c --- /dev/null +++ b/testdata/repos/python/PythonWrongUsageCheck/PythonHasVersionUsage/PythonHasVersionUsage-0.ebuild @@ -0,0 +1,25 @@ +# Copyright 2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +PYTHON_COMPAT=( python3_10 ) + +inherit python-any-r1 + +DESCRIPTION="Ebuild that uses has_version" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" + +LICENSE="BSD" +SLOT="0" + +DEPEND="${PYTHON_DEPS}" +BDEPEND="${PYTHON_DEPS} + $(python_gen_any_dep ' + dev-python/lxml[${PYTHON_USEDEP}] + ') +" + +python_check_deps() { + has_version -b "dev-python/lxml[${PYTHON_USEDEP}]" +} diff --git a/testdata/repos/python/PythonWrongUsageCheck/PythonHasVersionUsage/PythonHasVersionUsage-1.ebuild b/testdata/repos/python/PythonWrongUsageCheck/PythonHasVersionUsage/PythonHasVersionUsage-1.ebuild new file mode 100644 index 000000000..240f53648 --- /dev/null +++ b/testdata/repos/python/PythonWrongUsageCheck/PythonHasVersionUsage/PythonHasVersionUsage-1.ebuild @@ -0,0 +1,27 @@ +# Copyright 2022 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +PYTHON_COMPAT=( python3_10 ) + +inherit python-any-r1 + +DESCRIPTION="Ebuild that uses has_version" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" + +LICENSE="BSD" +SLOT="0" + +DEPEND="${PYTHON_DEPS}" +BDEPEND="${PYTHON_DEPS} + $(python_gen_any_dep ' + dev-python/lxml[${PYTHON_USEDEP}] + dev-python/gpep517[${PYTHON_USEDEP}] + ') +" + +python_check_deps() { + has_version -b "dev-python/lxml[${PYTHON_USEDEP}]" && + has_version -b "dev-python/gpep517[${PYTHON_USEDEP}]" +} diff --git a/testdata/repos/python/dev-lang/python/python-3.10.ebuild b/testdata/repos/python/dev-lang/python/python-3.10.ebuild new file mode 100644 index 000000000..85da2a701 --- /dev/null +++ b/testdata/repos/python/dev-lang/python/python-3.10.ebuild @@ -0,0 +1,6 @@ +EAPI=8 + +DESCRIPTION="Stub ebuild for python interpreter" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" +LICENSE="BSD" +SLOT="3.10" diff --git a/testdata/repos/python/eclass/python-any-r1.eclass b/testdata/repos/python/eclass/python-any-r1.eclass index 9646b3a35..1066a5ade 100644 --- a/testdata/repos/python/eclass/python-any-r1.eclass +++ b/testdata/repos/python/eclass/python-any-r1.eclass @@ -24,3 +24,6 @@ _python_set_impls() { PYTHON_USEDEP=$(IFS=","; echo "${use[*]}") } _python_set_impls + +python_gen_any_dep() { :; } +python_gen_cond_dep() { :; }