>From 10623540095b666051e5b95718224a7bfa9bc984 Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <nicolas@debian.org>
Date: Thu, 6 Nov 2025 21:28:36 +0100
Subject: [PATCH 7/7] Add deb822.PkgRelation.{holds_on_arch,
 holds_with_profiles}

The next concern after parse_relations is probably to check that the
relation holds in a given context.  Enable callers to do that without
depending on the internal representation of arch and profiles
restrictions.
---
 src/debian/deb822.py | 40 ++++++++++++++++++++++++++++++++++++++++
 tests/test_deb822.py | 41 ++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/src/debian/deb822.py b/src/debian/deb822.py
index 4929583..1fab800 100644
--- a/src/debian/deb822.py
+++ b/src/debian/deb822.py
@@ -1487,6 +1487,46 @@ class PkgRelation:
         cnf = map(cls.__pipe_sep_RE.split, tl_deps)
         return [[parse_rel(or_dep) for or_dep in or_deps] for or_deps in cnf]
 
+    @staticmethod
+    def holds_on_arch(
+        relation: ParsedRelation,
+        arch: str,
+        table: debian_support.DpkgArchTable,
+    ) -> bool:
+        """Is relation active on the given architecture?
+
+        >>> table = DpkgArchTable.load_arch_table()
+        >>> relation = PkgRelation.parse_relations("foo [armel linux-any],")[0][0]
+        >>> PkgRelation.holds_on_arch(relation, "amd64", table)
+        True
+        >>> PkgRelation.holds_on_arch(relation, "hurd-i386", table)
+        False
+        """
+        archs = relation["arch"]
+        return (archs is None
+                or table.architecture_is_concerned(
+                    arch,
+                    tuple(("" if a.enabled else "!") + a.arch for a in archs)))
+
+    @staticmethod
+    def holds_with_profiles(
+        relation: ParsedRelation,
+        profiles: collections.abc.Container[str],
+    ) -> bool:
+        """Is relation active under the given profiles?
+
+        >>> relation = PkgRelation.parse_relations("foo <a !b> <c>")[0][0]
+        >>> PkgRelation.holds_with_profiles(relation, ("a", "b"))
+        False
+        >>> PkgRelation.holds_with_profiles(relation, ("c", ))
+        True
+        """
+        restrictions = relation["restrictions"]
+        return (restrictions is None
+                or any(all(term.enabled == (term.profile in profiles)
+                           for term in restriction_list)
+                       for restriction_list in restrictions))
+
     @staticmethod
     def str(rels: List[List[PkgRelation.ParsedRelation]]) -> builtins.str:
         """Format to string structured inter-package relationships
diff --git a/tests/test_deb822.py b/tests/test_deb822.py
index 97623dd..5909b06 100755
--- a/tests/test_deb822.py
+++ b/tests/test_deb822.py
@@ -59,7 +59,7 @@ except ImportError:
 
 
 from debian import deb822
-from debian.debian_support import Version
+from debian.debian_support import DpkgArchTable, Version
 
 
 from typing import (
@@ -1701,6 +1701,45 @@ class TestPkgRelations:
         assert term == "native"
         assert deb822.PkgRelation.str(rel) == r
 
+    def test_holds_on_arch(self) -> None:
+        table = DpkgArchTable.load_arch_table()
+        for one_relation, expected in (
+            # no restriction
+            ("foo",                     True),
+            # architecture membership
+            ("foo [ amd64  armel]",     True),
+            ("foo [        armel]",     False),
+            # architecture exclusions
+            ("foo [!amd64 !armel]",     False),
+            ("foo [       !armel]",     True),
+        ):
+            rel = deb822.PkgRelation.parse_relations(one_relation)[0][0]
+            got = deb822.PkgRelation.holds_on_arch(rel, "amd64", table)
+            assert got == expected, one_relation
+
+    def test_holds_with_profiles(self) -> None:
+        for one_relation, expected in (
+            # no restriction
+            ("foo",                     True),
+            # profile membership
+            ("foo <p1>",                True),
+            ("foo <p>",                 False),
+            # profile negation
+            ("foo <!p1>",               False),
+            ("foo <!p>",                True),
+            # profile conjunction
+            ("foo <p p1>",              False),
+            ("foo <p1 p2>",             True),
+            ("foo <p1 p2 p>",           False),
+            # profile disjunction
+            ("foo <p> <p1>",            True),
+            ("foo <p> <q>",             False),
+            ("foo <p1> <p2>",           True),
+        ):
+            rel = deb822.PkgRelation.parse_relations(one_relation)[0][0]
+            got = deb822.PkgRelation.holds_with_profiles(rel, ("p1", "p2"))
+            assert got == expected, one_relation
+
 
 class TestVersionAccessor:
 
-- 
2.47.3

