about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/docx/opc/rel.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/docx/opc/rel.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/docx/opc/rel.py')
-rw-r--r--.venv/lib/python3.12/site-packages/docx/opc/rel.py155
1 files changed, 155 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/docx/opc/rel.py b/.venv/lib/python3.12/site-packages/docx/opc/rel.py
new file mode 100644
index 00000000..47e8860d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/docx/opc/rel.py
@@ -0,0 +1,155 @@
+"""Relationship-related objects."""
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any, Dict, cast
+
+from docx.opc.oxml import CT_Relationships
+
+if TYPE_CHECKING:
+    from docx.opc.part import Part
+
+
+class Relationships(Dict[str, "_Relationship"]):
+    """Collection object for |_Relationship| instances, having list semantics."""
+
+    def __init__(self, baseURI: str):
+        super(Relationships, self).__init__()
+        self._baseURI = baseURI
+        self._target_parts_by_rId: dict[str, Any] = {}
+
+    def add_relationship(
+        self, reltype: str, target: Part | str, rId: str, is_external: bool = False
+    ) -> "_Relationship":
+        """Return a newly added |_Relationship| instance."""
+        rel = _Relationship(rId, reltype, target, self._baseURI, is_external)
+        self[rId] = rel
+        if not is_external:
+            self._target_parts_by_rId[rId] = target
+        return rel
+
+    def get_or_add(self, reltype: str, target_part: Part) -> _Relationship:
+        """Return relationship of `reltype` to `target_part`, newly added if not already
+        present in collection."""
+        rel = self._get_matching(reltype, target_part)
+        if rel is None:
+            rId = self._next_rId
+            rel = self.add_relationship(reltype, target_part, rId)
+        return rel
+
+    def get_or_add_ext_rel(self, reltype: str, target_ref: str) -> str:
+        """Return rId of external relationship of `reltype` to `target_ref`, newly added
+        if not already present in collection."""
+        rel = self._get_matching(reltype, target_ref, is_external=True)
+        if rel is None:
+            rId = self._next_rId
+            rel = self.add_relationship(reltype, target_ref, rId, is_external=True)
+        return rel.rId
+
+    def part_with_reltype(self, reltype: str) -> Part:
+        """Return target part of rel with matching `reltype`, raising |KeyError| if not
+        found and |ValueError| if more than one matching relationship is found."""
+        rel = self._get_rel_of_type(reltype)
+        return rel.target_part
+
+    @property
+    def related_parts(self):
+        """Dict mapping rIds to target parts for all the internal relationships in the
+        collection."""
+        return self._target_parts_by_rId
+
+    @property
+    def xml(self) -> str:
+        """Serialize this relationship collection into XML suitable for storage as a
+        .rels file in an OPC package."""
+        rels_elm = CT_Relationships.new()
+        for rel in self.values():
+            rels_elm.add_rel(rel.rId, rel.reltype, rel.target_ref, rel.is_external)
+        return rels_elm.xml
+
+    def _get_matching(
+        self, reltype: str, target: Part | str, is_external: bool = False
+    ) -> _Relationship | None:
+        """Return relationship of matching `reltype`, `target`, and `is_external` from
+        collection, or None if not found."""
+
+        def matches(rel: _Relationship, reltype: str, target: Part | str, is_external: bool):
+            if rel.reltype != reltype:
+                return False
+            if rel.is_external != is_external:
+                return False
+            rel_target = rel.target_ref if rel.is_external else rel.target_part
+            if rel_target != target:
+                return False
+            return True
+
+        for rel in self.values():
+            if matches(rel, reltype, target, is_external):
+                return rel
+        return None
+
+    def _get_rel_of_type(self, reltype: str):
+        """Return single relationship of type `reltype` from the collection.
+
+        Raises |KeyError| if no matching relationship is found. Raises |ValueError| if
+        more than one matching relationship is found.
+        """
+        matching = [rel for rel in self.values() if rel.reltype == reltype]
+        if len(matching) == 0:
+            tmpl = "no relationship of type '%s' in collection"
+            raise KeyError(tmpl % reltype)
+        if len(matching) > 1:
+            tmpl = "multiple relationships of type '%s' in collection"
+            raise ValueError(tmpl % reltype)
+        return matching[0]
+
+    @property
+    def _next_rId(self) -> str:  # pyright: ignore[reportReturnType]
+        """Next available rId in collection, starting from 'rId1' and making use of any
+        gaps in numbering, e.g. 'rId2' for rIds ['rId1', 'rId3']."""
+        for n in range(1, len(self) + 2):
+            rId_candidate = "rId%d" % n  # like 'rId19'
+            if rId_candidate not in self:
+                return rId_candidate
+
+
+class _Relationship:
+    """Value object for relationship to part."""
+
+    def __init__(
+        self, rId: str, reltype: str, target: Part | str, baseURI: str, external: bool = False
+    ):
+        super(_Relationship, self).__init__()
+        self._rId = rId
+        self._reltype = reltype
+        self._target = target
+        self._baseURI = baseURI
+        self._is_external = bool(external)
+
+    @property
+    def is_external(self) -> bool:
+        return self._is_external
+
+    @property
+    def reltype(self) -> str:
+        return self._reltype
+
+    @property
+    def rId(self) -> str:
+        return self._rId
+
+    @property
+    def target_part(self) -> Part:
+        if self._is_external:
+            raise ValueError(
+                "target_part property on _Relationship is undef" "ined when target mode is External"
+            )
+        return cast("Part", self._target)
+
+    @property
+    def target_ref(self) -> str:
+        if self._is_external:
+            return cast(str, self._target)
+        else:
+            target = cast("Part", self._target)
+            return target.partname.relative_ref(self._baseURI)