def test_equality(self): a = CtsReference("1.1@[0]") b = CtsReference("1.1@[0]") c = CtsReference("1.1@[1]") d = "1.1@[0]" self.assertEqual(a, b) self.assertNotEqual(a, c) self.assertNotEqual(a, d)
def test_highest(self): self.assertEqual( str((CtsReference("1.1-1.2.8")).highest), "1.1", "1.1 is higher" ) self.assertEqual( str((CtsReference("1.1-2")).highest), "2", "2 is higher" )
def getTextualNode(self, subreference=None, simple=False): """ Finds a passage in the current text :param subreference: Identifier of the subreference / passages :type subreference: Union[list, CtsReference] :param simple: If set to true, retrieves nodes up to the given one, cleaning non required siblings. :type simple: boolean :rtype: CapitainsCtsPassage, ContextPassage :returns: Asked passage """ if subreference is None: return self._getSimplePassage() if not isinstance(subreference, CtsReference): if isinstance(subreference, str): subreference = CtsReference(subreference) elif isinstance(subreference, list): subreference = CtsReference(".".join(subreference)) if len(subreference.start) > self.citation.root.depth: raise CitationDepthError("URN is deeper than citation scheme") if simple is True: return self._getSimplePassage(subreference) if not subreference.is_range(): start = end = subreference.start.list else: start, end = subreference.start.list, subreference.end.list citation_start = self.citation.root[len(start) - 1] citation_end = self.citation.root[len(end) - 1] start, end = citation_start.fill(passage=start), citation_end.fill( passage=end) start, end = normalizeXpath(start.split("/")[2:]), normalizeXpath( end.split("/")[2:]) xml = self.textObject.xml if isinstance(xml, etree._Element): root = copyNode(xml) else: root = copyNode(xml.getroot()) root = passageLoop(xml, root, start, end) if self.urn: urn = URN("{}:{}".format(self.urn, subreference)) else: urn = None return CapitainsCtsPassage(urn=urn, resource=root, text=self, citation=citation_start, reference=subreference)
def test_fill(self): c = Citation( name="line", scope="/TEI/text/body/div/div[@n=\"?\"]", xpath="//l[@n=\"?\"]" ) self.assertEqual(c.fill(CtsReference("1.2")), "/TEI/text/body/div/div[@n='1']//l[@n='2']") self.assertEqual(c.fill(CtsReference("1.1")), "/TEI/text/body/div/div[@n='1']//l[@n='1']") self.assertEqual(c.fill(None), "/TEI/text/body/div/div[@n]//l[@n]") self.assertEqual(c.fill("1", xpath=True), "//l[@n='1']") self.assertEqual(c.fill("2", xpath=True), "//l[@n='2']") self.assertEqual(c.fill(None, xpath=True), "//l[@n]") self.assertEqual(c.fill([None, None]), "/TEI/text/body/div/div[@n]//l[@n]") self.assertEqual(c.fill(["1", None]), "/TEI/text/body/div/div[@n='1']//l[@n]")
def getTextualNode(self, subreference=None, *args, **kwargs): if not isinstance(subreference, CtsReference): subreference = CtsReference(subreference) X = super(CapitainsCtsPassage, self).getTextualNode(subreference=subreference) X._text = self._text return X
def test_Unicode_Support(self): a = CtsReference("1.1@καὶ[0]-1.10@Ἀλκιβιάδου[3]") self.assertEqual(a.start, "1.1@καὶ[0]") self.assertEqual(a.start.list, ["1", "1"]) self.assertEqual(a.start.subreference.word, "καὶ") self.assertEqual(a.end, "1.10@Ἀλκιβιάδου[3]") self.assertEqual(a.end.list, ["1", "10"]) self.assertEqual(a.end.subreference.counter, 3) self.assertEqual(a.end.subreference.tuple(), ("Ἀλκιβιάδου", 3))
def test_properties(self): a = CtsReference("[email protected]@Atreus[3]") self.assertEqual(a.start, "1.1@Achilles") self.assertEqual(a.start.list, ["1", "1"]) self.assertEqual(a.start.subreference.word, "Achilles") self.assertEqual(a.end, "1.10@Atreus[3]") self.assertEqual(a.end.list, ["1", "10"]) self.assertEqual(a.end.subreference.counter, 3) self.assertEqual(a.end.subreference.tuple(), ("Atreus", 3))
def getTextualNode(self, subreference: CtsReference = None): """ Special GetPassage implementation for SimplePassage (Simple is True by default) :param subreference: :return: """ if not isinstance(subreference, CtsReference): subreference = CtsReference(subreference) return self.textObject.getTextualNode(subreference)
def test_properties(self): a = URN("urn:cts:greekLit:tlg0012.tlg001.mth-01:[email protected]@the[2]") self.assertEqual(a.urn_namespace, "cts") a.urn_namespace = "dts" self.assertEqual(a.urn_namespace, "dts") self.assertEqual(a.namespace, "greekLit") self.assertEqual(a.textgroup, "tlg0012") self.assertEqual(a.work, "tlg001") self.assertEqual(a.version, "mth-01") self.assertEqual(a.reference, CtsReference("[email protected]@the[2]"))
def test_no_end_text_emptiness(self): a = URN("urn:cts:greekLit:textgroup.work.text:1") self.assertEqual(str(a), "urn:cts:greekLit:textgroup.work.text:1") self.assertEqual(a.upTo(URN.COMPLETE), "urn:cts:greekLit:textgroup.work.text:1") self.assertEqual(a.upTo(URN.NAMESPACE), "urn:cts:greekLit") self.assertEqual(a.upTo(URN.TEXTGROUP), "urn:cts:greekLit:textgroup") self.assertEqual(a.upTo(URN.WORK), "urn:cts:greekLit:textgroup.work") self.assertEqual(a.upTo(URN.VERSION), "urn:cts:greekLit:textgroup.work.text") self.assertEqual(a.upTo(URN.PASSAGE), "urn:cts:greekLit:textgroup.work.text:1") self.assertEqual(a.upTo(URN.NO_PASSAGE), "urn:cts:greekLit:textgroup.work.text") self.assertEqual(a.reference, CtsReference("1")) self.assertIsNone(a.reference.end)
def test_get_parent(self): a = CtsReference("1.1") b = CtsReference("1") c = CtsReference("1.1-2.3") d = CtsReference("1.1-1.2") e = CtsReference("1.1@Something[0]-1.2@SomethingElse[2]") f = CtsReference("1-2") self.assertEqual(a.parent, CtsReference("1")) self.assertEqual(b.parent, None) self.assertEqual(str(c.parent), "1-2") self.assertEqual(c.parent, CtsReference("1-2"), "Output should also be CtsReference") self.assertEqual(str(d.parent), "1") self.assertEqual(str(e.parent), "1@Something[0]-1@SomethingElse[2]") self.assertEqual(f.parent, None)
def test_set(self): a = URN("urn:cts:latinLit:phi1294.phi002.perseus-lat2") a.reference = CtsReference("1.1") self.assertEqual(str(a), "urn:cts:latinLit:phi1294.phi002.perseus-lat2:1.1") a.reference = "2.2" self.assertEqual(str(a), "urn:cts:latinLit:phi1294.phi002.perseus-lat2:2.2") a.version = "perseus-eng2" self.assertEqual(str(a), "urn:cts:latinLit:phi1294.phi002.perseus-eng2:2.2") a.work = "phi001" self.assertEqual(str(a), "urn:cts:latinLit:phi1294.phi001.perseus-eng2:2.2") a.textgroup = "phi1293" self.assertEqual(str(a), "urn:cts:latinLit:phi1293.phi001.perseus-eng2:2.2") a.namespace = "greekLit" self.assertEqual(str(a), "urn:cts:greekLit:phi1293.phi001.perseus-eng2:2.2")
def test_missing_text_in_passage_emptiness(self): a = URN("urn:cts:greekLit:textgroup.work:1-2") self.assertEqual(str(a), "urn:cts:greekLit:textgroup.work:1-2") self.assertEqual(a.upTo(URN.COMPLETE), "urn:cts:greekLit:textgroup.work:1-2") self.assertEqual(a.upTo(URN.NAMESPACE), "urn:cts:greekLit") self.assertEqual(a.upTo(URN.TEXTGROUP), "urn:cts:greekLit:textgroup") self.assertEqual(a.upTo(URN.WORK), "urn:cts:greekLit:textgroup.work") self.assertEqual(a.upTo(URN.NO_PASSAGE), "urn:cts:greekLit:textgroup.work") self.assertEqual(a.upTo(URN.PASSAGE), "urn:cts:greekLit:textgroup.work:1-2") self.assertEqual(a.upTo(URN.PASSAGE_START), "urn:cts:greekLit:textgroup.work:1") self.assertEqual(a.upTo(URN.PASSAGE_END), "urn:cts:greekLit:textgroup.work:2") self.assertEqual(a.reference, CtsReference("1-2")) self.assertEqual(a.reference.start, "1") self.assertEqual(a.reference.end, "2") self.assertIsNone(a.version)
def getReffs(self, level: int = 1, subreference: CtsReference = None) -> CtsReferenceSet: """ CtsReference available at a given level :param level: Depth required. If not set, should retrieve first encountered level (1 based) :param subreference: Subreference (optional) :returns: List of levels """ if not subreference and hasattr(self, "reference"): subreference = self.reference elif subreference and not isinstance(subreference, CtsReference): subreference = CtsReference(subreference) return self.getValidReff(level=level, reference=subreference)
def test_set(self): a = URN("urn:cts:greekLit:textgroup") a.textgroup = "tg" self.assertEqual(a.textgroup, "tg") self.assertEqual(str(a), "urn:cts:greekLit:tg") a.namespace = "ns" self.assertEqual(a.namespace, "ns") self.assertEqual(str(a), "urn:cts:ns:tg") a.work = "wk" self.assertEqual(a.work, "wk") self.assertEqual(str(a), "urn:cts:ns:tg.wk") a.reference = "1-2" self.assertEqual(a.reference, CtsReference("1-2")) self.assertEqual(str(a), "urn:cts:ns:tg.wk:1-2") a.version = "vs" self.assertEqual(a.version, "vs") self.assertEqual(str(a), "urn:cts:ns:tg.wk.vs:1-2")
def getValidReff(self, level: int = 1, reference: CtsReference = None, _debug: bool = False) -> CtsReferenceSet: """ Retrieve valid passages directly :param level: Depth required. If not set, should retrieve first encountered level (1 based) :type level: int :param reference: CapitainsCtsPassage Reference :type reference: CtsReference :param _debug: Check on passages duplicates :type _debug: bool :returns: List of levels .. note:: GetValidReff works for now as a loop using CapitainsCtsPassage, subinstances of CtsTextMetadata, to retrieve the valid \ informations. Maybe something is more powerfull ? """ depth = 0 xml = self.textObject.xml if reference: if isinstance(reference, CtsReference): if not reference.is_range(): passages = [reference.start.list] depth = len(passages[0]) if level == 0: level = None if _debug: warnings.warn( "Using level=0 with a Non-range Reference is invalid. Autocorrected to 1" ) else: xml = self.getTextualNode(subreference=reference) common = [] for index, part in enumerate(reference.start.list): if index <= reference.end.depth: if part == reference.end.list[index]: common.append(part) else: break else: break passages = [common] depth = len(common) if level is None: level = reference.start.depth + depth elif level == 1: level = reference.start.depth + 1 elif level == 0: level = reference.start.depth else: raise TypeError() else: passages = [[]] if level is None: level = 1 if level <= len(passages[0]) and reference is not None: level = len(passages[0]) + 1 if level > len(self.citation.root): raise CitationDepthError("The required level is too deep") nodes = [None] * (level - depth) citations = [citation for citation in self.citation.root] while len(nodes) >= 1: passages = [ refs + [ node.get( current_citation.attribute.replace( "xml:", "{http://www.w3.org/XML/1998/namespace}")) ] for xpath_result, refs, current_citation in [( xml.xpath(citations[len(filling) - 1].fill(filling), namespaces=XPATH_NAMESPACES), refs, citations[len(filling) - 1]) for filling, refs in [(refs + [None], refs) for refs in passages]] for node in xpath_result ] nodes.pop(0) if len(passages) == 0: msg = "Unknown reference {}".format(reference) raise KeyError(msg) passages = [".".join(passage) for passage in passages] if _debug: duplicates = set() seen = set() for n in passages: if n in seen: duplicates.add(n) else: seen.add(n) if len(duplicates) > 0: message = ", ".join(duplicates) warnings.warn(message, DuplicateReference) del duplicates empties = [n for n in passages if n.rstrip('.') != n or n == ''] if len(empties) > 0: message = '{} empty reference(s) at citation level {}'.format( len(empties), level) warnings.warn(message, EmptyReference) references = CtsReferenceSet([CtsReference(reff) for reff in passages], citation=self.citation.root[level - 1], level=level) return references
def test_depth_ref(self): a = CtsReference("1.1@Achilles[0]-1.10@Atreus[3]") self.assertEqual(a.depth, 2) a = CtsReference("1.1.1") self.assertEqual(a.depth, 3)
def test_No_End_Support(self): a = CtsReference("1.1@[0]") self.assertEqual(a.end, None) self.assertEqual(a.start, "1.1@[0]") self.assertEqual(a.start.subreference.word, "") self.assertEqual(a.start.subreference.counter, 0)
def siblingsId(self) -> Tuple[CtsReference, CtsReference]: """ Siblings Identifiers of the passage :rtype: (str, str) """ self._raise_depth() if not self._text: raise MissingAttribute( "CapitainsCtsPassage was initiated without CtsTextMetadata object" ) if self._prev_next: return self._prev_next document_references = self._text.getReffs(level=self.depth) if self.reference.is_range(): start, end = self.reference.start, self.reference.end range_length = len(self.getReffs(level=0)) else: start = end = self.reference.start range_length = 1 start = document_references.index(start) end = document_references.index(end) if start == 0: # If the passage is already at the beginning _prev = None elif start - range_length < 0: if start == end: _prev = document_references[0] else: _prev = "{}-{}".format(document_references[0], document_references[start - 1]) else: if start == end: _prev = document_references[start - 1] else: _prev = "{}-{}".format( document_references[start - range_length], document_references[start - 1]) if start + 1 == len(document_references) or end + 1 == len( document_references): # If the passage is already at the end _next = None elif end + range_length >= len(document_references): if start == end: _next = document_references[-1] else: _next = "{}-{}".format(document_references[end + 1], document_references[-1]) else: if start == end: _next = document_references[end + 1] else: _next = "{}-{}".format(document_references[end + 1], document_references[end + range_length]) self._prev_next = (CtsReference(_prev), CtsReference(_next)) return self._prev_next
def test_NoWord_Support(self): a = CtsReference("1.1@[0]-1.10@Ἀλκιβιάδου[3]") self.assertEqual(a.start, "1.1@[0]") self.assertEqual(a.start.subreference.word, "") self.assertEqual(a.start.subreference.counter, 0)
def test_str_function(self): a = CtsReference("1-1") self.assertEqual(str(a), "1-1")