Since this thing is on the innerwebs I suppose it should have a
[python_utils.git] / logical_search.py
index b55e68901501ad2e68a7f45df034866072c3f61b..b6d7479879010d6ea40ef813d03e84574ead7e55 100644 (file)
@@ -1,15 +1,19 @@
 #!/usr/bin/env python3
 
+# © Copyright 2021-2022, Scott Gasch
+
 """This is a module concerned with the creation of and searching of a
 corpus of documents.  The corpus is held in memory for fast
-searching."""
+searching.
 
-from __future__ import annotations
+"""
 
+from __future__ import annotations
 import enum
 import sys
 from collections import defaultdict
-from typing import Any, Dict, List, NamedTuple, Optional, Sequence, Set, Tuple, Union
+from dataclasses import dataclass, field
+from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Union
 
 
 class ParseError(Exception):
@@ -20,13 +24,22 @@ class ParseError(Exception):
         self.message = message
 
 
-class Document(NamedTuple):
-    """A tuple representing a searchable document."""
+@dataclass
+class Document:
+    """A class representing a searchable document."""
+
+    # A unique identifier for each document.
+    docid: str = ''
+
+    # A set of tag strings for this document.  May be empty.
+    tags: Set[str] = field(default_factory=set)
+
+    # A list of key->value strings for this document.  May be empty.
+    properties: List[Tuple[str, str]] = field(default_factory=list)
 
-    docid: str  # a unique idenfier for the document
-    tags: Set[str]  # an optional set of tags
-    properties: List[Tuple[str, str]]  # an optional set of key->value properties
-    reference: Any  # an optional reference to something else
+    # An optional reference to something else; interpreted only by
+    # caller code, ignored here.
+    reference: Optional[Any] = None
 
 
 class Operation(enum.Enum):
@@ -173,7 +186,7 @@ class Corpus(object):
     def invert_docid_set(self, original: Set[str]) -> Set[str]:
         """Invert a set of docids."""
 
-        return set([docid for docid in self.documents_by_docid.keys() if docid not in original])
+        return {docid for docid in self.documents_by_docid if docid not in original}
 
     def get_doc(self, docid: str) -> Optional[Document]:
         """Given a docid, retrieve the previously added Document."""