From 297ea519dd5a50d08323ae72c8031c3d28856480 Mon Sep 17 00:00:00 2001 From: David Roman Date: Fri, 22 Aug 2025 13:13:51 +0200 Subject: [PATCH] fix parsing of atoms Previously atoms like category/a-long-name were parsed in such a way that "name" was taken as the version --- ebuildtester/atom.py | 79 +++++++++++++++++++++++++++++++++++++++++--- test/test_atom.py | 19 ++++++++--- 2 files changed, 89 insertions(+), 9 deletions(-) diff --git a/ebuildtester/atom.py b/ebuildtester/atom.py index 7a7d04c..9015876 100644 --- a/ebuildtester/atom.py +++ b/ebuildtester/atom.py @@ -1,11 +1,82 @@ """An Atom.""" +import re + class AtomException(Exception): """An exception in this class.""" pass +# from lib/portage/version.py +# PMS 3.1.3: A slot name may contain any of the characters [A-Za-z0-9+_.-]. +# It must not begin with a hyphen or a dot. +_slot = r"([\w+][\w+.-]*)" + +# 2.1.1 A category name may contain any of the characters [A-Za-z0-9+_.-]. +# It must not begin with a hyphen or a dot. +_cat = r"[\w+][\w+.-]*" + +# 2.1.2 A package name may contain any of the characters [A-Za-z0-9+_-]. +# It must not begin with a hyphen, +# and must not end in a hyphen followed by one or more digits. +_pkg = r"[\w+][\w+-]*?" + +_v = r"(\d+)((\.\d+)*)([a-z]?)((_(pre|p|beta|alpha|rc)\d*)*)" +_rev = r"\d+" +_vr = _v + "(-r(" + _rev + "))?" + +_cp = "(" + _cat + "/" + _pkg + "(-" + _vr + ")?)" +_cpv = "(" + _cp + "-" + _vr + ")" +_pv = ( + "(?P" + + _pkg + + "(?P-" + + _vr + + ")?)" + + "-(?P" + + _v + + ")(-r(?P" + + _rev + + "))?" +) + +_pv_re = None + + +def _get_pv_re(): + global _pv_re + if _pv_re is not None: + return _pv_re + + _pv_re = re.compile(r"^" + _pv + r"$", re.VERBOSE | re.UNICODE) + + return _pv_re + + +def _pkgsplit(mypkg: str): + """ + @param mypkg: pv + @return: + 1. None if input is invalid. + 2. (pn, ver, rev) if input is pv + """ + m = _get_pv_re().match(mypkg) + if m is None: + return None + + if m.group("pn_inval") is not None: + # package name appears to have a version-like suffix + return None + + rev = m.group("rev") + if rev is None: + rev = "0" + rev = "r" + rev + + return (m.group("pn"), m.group("ver"), rev) + + class Atom(object): def __init__(self, atom): @@ -26,10 +97,10 @@ def __init__(self, atom): # Split off version. try: - temp = self.package.index("-") - if temp > -1: - self.version = self.package[temp + 1:] - self.package = self.package[:temp] + # If atom don't start with "=" we assume there is no version + if '=' in atom: + self.package, self.version, rev = _pkgsplit(self.package) + self.version = f"{self.version}-{rev}" except ValueError: pass diff --git a/test/test_atom.py b/test/test_atom.py index 95f8343..b92d4b1 100644 --- a/test/test_atom.py +++ b/test/test_atom.py @@ -7,7 +7,7 @@ class TestAtom(unittest.TestCase): def test_equals(self): atom = Atom("=CATEGORY/PACKAGE-1.0.0") self.assertEqual(atom.__str__()[0], "=") - self.assertEqual(atom.__str__(), "=CATEGORY/PACKAGE-1.0.0") + self.assertEqual(atom.__str__(), "=CATEGORY/PACKAGE-1.0.0-r0") def test_slash_1(self): with self.assertRaises(AtomException) as e: @@ -19,12 +19,21 @@ def test_slash_2(self): self.assertEqual(atom.package, "PACKAGE") def test_version(self): - self.assertEqual(Atom("CATEGORY/PACKAGE-1").version, "1") - self.assertEqual(Atom("CATEGORY/PACKAGE-1.0").version, "1.0") - self.assertEqual( - Atom("CATEGORY/PACKAGE-1.0-r1").version, "1.0-r1") + self.assertEqual(Atom("CATEGORY/PACKAGE-1").version, None) + self.assertEqual(Atom("CATEGORY/PACKAGE-NAME-1").version, None) + self.assertEqual(Atom("CATEGORY/PACKAGE-1.0-r1").version, None) + self.assertEqual(Atom("CATEGORY/P-NAME-1.0-r1").version, None) + + self.assertEqual(Atom("=CATEGORY/PACKAGE-1").version, "1-r0") + self.assertEqual(Atom("=CATEGORY/PACKAGE-NAME-1").version, "1-r0") + self.assertEqual(Atom("=CATEGORY/PACKAGE-NAME-1.0").version, "1.0-r0") + self.assertEqual(Atom("=CATEGORY/PACKAGE-1.0-r1").version, "1.0-r1") def test_str(self): atom_1 = Atom("=CATEGORY/PACKAGE-1.0.0-r1") atom_2 = Atom(str(atom_1)) self.assertEqual(atom_1, atom_2) + atom_3 = Atom("=CATEGORY/PACKAGE-NAME-1.0.0-r1") + atom_4 = Atom(str(atom_3)) + self.assertEqual(atom_3, atom_4) +