From e23a908709e9b7f9ad5dadf77e3a134eb0480ce7 Mon Sep 17 00:00:00 2001
From: Joscha Schmiedt <joscha@schmiedt.dev>
Date: Wed, 10 Apr 2024 21:36:37 +0200
Subject: [PATCH] Add type hints to versioning.py

---
 src/linkahead/common/versioning.py | 42 +++++++++++++++++++++---------
 1 file changed, 30 insertions(+), 12 deletions(-)

diff --git a/src/linkahead/common/versioning.py b/src/linkahead/common/versioning.py
index facfbc48..beced57a 100644
--- a/src/linkahead/common/versioning.py
+++ b/src/linkahead/common/versioning.py
@@ -26,10 +26,15 @@
 Currently this module defines nothing but a single class, `Version`.
 """
 
-from __future__ import absolute_import
+from __future__ import absolute_import, annotations
 from .utils import xml2str
 from lxml import etree
 
+from typing import TYPE_CHECKING
+import sys
+if TYPE_CHECKING and sys.version_info > (3, 7):
+    from typing import Optional, List, Union, Literal
+
 
 class Version():
     """The version of an entity.
@@ -95,9 +100,11 @@ class Version():
     """
 
     # pylint: disable=redefined-builtin
-    def __init__(self, id=None, date=None, username=None, realm=None,
-                 predecessors=None, successors=None, is_head=False,
-                 is_complete_history=False):
+    def __init__(self, id: Optional[str] = None, date: Optional[str] = None,
+                 username: Optional[str] = None, realm: Optional[str] = None,
+                 predecessors: Optional[List[Version]] = None, successors: Optional[List[Version]] = None,
+                 is_head: Union[bool, str] = False,
+                 is_complete_history: Union[bool, str] = False):
         """Typically the `predecessors` or `successors` should not "link back" to an existing Version
 object."""
         self.id = id
@@ -109,7 +116,7 @@ object."""
         self.is_head = str(is_head).lower() == "true"
         self.is_complete_history = str(is_complete_history).lower() == "true"
 
-    def get_history(self):
+    def get_history(self) -> List[Version]:
         """ Returns a flat list of Version instances representing the history
         of the entity.
 
@@ -126,7 +133,7 @@ object."""
         -------
         list of Version
         """
-        versions = []
+        versions: List[Version] = []
         for p in self.predecessors:
             # assuming that predecessors don't have any successors
             versions = p.get_history()
@@ -137,7 +144,7 @@ object."""
             versions.extend(s.get_history())
         return versions
 
-    def to_xml(self, tag="Version"):
+    def to_xml(self, tag: str = "Version") -> etree._Element:
         """Serialize this version to xml.
 
         The tag name is 'Version' per default. But since this method is called
@@ -184,7 +191,7 @@ object."""
         return xml2str(self.to_xml())
 
     @staticmethod
-    def from_xml(xml):
+    def from_xml(xml: etree._Element) -> Version:
         """Parse a version object from a 'Version' xml element.
 
         Parameters
@@ -199,11 +206,22 @@ object."""
         version : Version
             a new version instance
         """
-        predecessors = [Version.from_xml(p) for p in xml if p.tag.lower() == "predecessor"]
-        successors = [Version.from_xml(s) for s in xml if s.tag.lower() == "successor"]
+        predecessors = [Version.from_xml(
+            p) for p in xml if p.tag.lower() == "predecessor"]
+        successors = [Version.from_xml(s)
+                      for s in xml if s.tag.lower() == "successor"]
+        is_head = xml.get("head")
+        if is_head is None:
+            raise ValueError(f"Version head is missing from xml:{str(xml)}")
+
+        is_complete_history = xml.get("completeHistory")
+        if is_complete_history is None:
+            raise ValueError(
+                f"Version completeHistory is missing from xml:{str(xml)}")
+
         return Version(id=xml.get("id"), date=xml.get("date"),
-                       is_head=xml.get("head"),
-                       is_complete_history=xml.get("completeHistory"),
+                       is_head=is_head,
+                       is_complete_history=is_complete_history,
                        username=xml.get("username"), realm=xml.get("realm"),
                        predecessors=predecessors, successors=successors)
 
-- 
GitLab