Skip to content

Commit

Permalink
Merge with Matt's Commentary
Browse files Browse the repository at this point in the history
  • Loading branch information
PonteIneptique committed Apr 21, 2017
2 parents ff671db + aee65f7 commit f65b57c
Show file tree
Hide file tree
Showing 11 changed files with 425 additions and 42 deletions.
9 changes: 6 additions & 3 deletions MyCapytain/resolvers/cts/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from MyCapytain.resolvers.prototypes import Resolver
from MyCapytain.resolvers.utils import CollectionDispatcher
from MyCapytain.resources.collections.cts import XmlCtsTextInventoryMetadata, XmlCtsTextgroupMetadata, XmlCtsWorkMetadata, XmlCtsCitation, XmlCtsTextMetadata as InventoryText, \
XmlCtsTranslationMetadata, XmlCtsEditionMetadata
XmlCtsTranslationMetadata, XmlCtsEditionMetadata, XmlCtsCommentaryMetadata
from MyCapytain.resources.prototypes.cts.inventory import CtsTextInventoryCollection
from MyCapytain.resources.texts.local.capitains.cts import CapitainsCtsText

Expand Down Expand Up @@ -230,8 +230,8 @@ def __getTextMetadata__(self,
(urn is None or (urn is not None and text.urn.upTo(__PART) == urn)) and
(text.citation is not None) and
(
category not in ["edition", "translation"] or
(category in ["edition", "translation"] and category.lower() == text.subtype.lower())
category not in ["edition", "translation", "commentary"] or
(category in ["edition", "translation", "commentary"] and category.lower() == text.subtype.lower())
)
]
if pagination:
Expand Down Expand Up @@ -308,6 +308,9 @@ def getMetadata(self, objectId=None, **filters):
elif isinstance(text, XmlCtsTranslationMetadata):
x = XmlCtsTranslationMetadata(urn=txt_urn, parent=inventory.textgroups[tg_urn].works[wk_urn], lang=text.lang)
x.citation = text.citation
elif isinstance(text, XmlCtsCommentaryMetadata):
x = XmlCtsCommentaryMetadata(urn=txt_urn, parent=inventory.textgroups[tg_urn].works[wk_urn], lang=text.lang)
x.citation = text.citation

return inventory[objectId]

Expand Down
23 changes: 22 additions & 1 deletion MyCapytain/resources/collections/cts.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from MyCapytain.resources.prototypes.cts import inventory as cts
from MyCapytain.common.reference import Citation as CitationPrototype
from MyCapytain.common.utils import xmlparser
from MyCapytain.common.constants import XPath_Namespaces, Mimetypes
from MyCapytain.common.constants import XPath_Namespaces, Mimetypes, RDF_Namespaces


class XmlCtsCitation(CitationPrototype):
Expand Down Expand Up @@ -116,6 +116,12 @@ def parse_metadata(obj, xml):

obj.citation = XmlCtsCitation.ingest(xml, obj.citation, "ti:online/ti:citationMapping/ti:citation")

# Added for commentary
for child in xml.xpath("ti:about", namespaces=XPath_Namespaces):
#lg = child.get("{http://www.w3.org/XML/1998/namespace}lang")
#if lg is not None:
obj.set_link(RDF_Namespaces.CTS.term("about"), child.get('urn'))

"""
online = xml.xpath("ti:online", namespaces=NS)
if len(online) > 0:
Expand Down Expand Up @@ -154,6 +160,19 @@ def parse(resource, parent=None):
XmlCtsTranslationMetadata.parse_metadata(o, xml)
return o

class XmlCtsCommentaryMetadata(cts.CtsCommentaryMetadata, XmlCtsTextMetadata):
""" Create a commentary subtyped PrototypeText object
"""
@staticmethod
def parse(resource, parent=None):
xml = xmlparser(resource)
lang = xml.get("{http://www.w3.org/XML/1998/namespace}lang")

o = XmlCtsCommentaryMetadata(urn=xml.get("urn"), parent=parent)
if lang is not None:
o.lang = lang
XmlCtsCommentaryMetadata.parse_metadata(o, xml)
return o

class XmlCtsWorkMetadata(cts.CtsWorkMetadata):
""" Represents a CTS Textgroup in XML
Expand Down Expand Up @@ -183,6 +202,8 @@ def parse(resource, parent=None):
# Parse children
xpathDict(xml=xml, xpath='ti:edition', cls=XmlCtsEditionMetadata, parent=o)
xpathDict(xml=xml, xpath='ti:translation', cls=XmlCtsTranslationMetadata, parent=o)
# Added for commentary
xpathDict(xml=xml, xpath='ti:commentary', cls=XmlCtsCommentaryMetadata, parent=o)

return o

Expand Down
65 changes: 63 additions & 2 deletions MyCapytain/resources/prototypes/cts/inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class PrototypeCtsCollection(Collection):
CTS_MODEL = "CtsCollection"
DC_TITLE_KEY = None
CTS_PROPERTIES = []
CTS_LINKS = []

EXPORT_TO = [Mimetypes.PYTHON.ETREE]
DEFAULT_EXPORT = Mimetypes.PYTHON.ETREE
Expand Down Expand Up @@ -96,6 +97,40 @@ def set_cts_property(self, prop, value, lang=None):
(self.metadata.asNode(), prop, value)
)

# new for commentary
def get_link(self, prop):
""" Get given link in CTS Namespace
.. example::
collection.get_link("about")
:param prop: Property to get (Without namespace)
:return: whole set of values
:rtype: list
"""
return list([o for o in self.graph.objects(self.metadata.asNode(), prop)])

def set_link(self, prop, value):
""" Set given link in CTS Namespace
.. example::
collection.set_link(NAMESPACES.CTS.about, "urn:cts:latinLit:phi1294.phi002")
:param prop: Property to set (Without namespace)
:param value: Value to set for given property
"""
# https://rdflib.readthedocs.io/en/stable/
# URIRef == identifiers (urn, http, URI in general)
# Literal == String or Number (can have a language)
# BNode == Anonymous nodes (So no specific identifier)
# eg. BNode : Edition(MartialEpigrams:URIRef) ---has_metadata--> Metadata(BNode)
if not isinstance(value, URIRef):
value = URIRef(value)

self.graph.add(
(self.metadata.asNode(), prop, value)
)

def __xml_export_generic__(self, attrs, namespaces=False, lines="\n", members=None):
""" Shared method for Mimetypes.XML.CTS Export
Expand Down Expand Up @@ -151,6 +186,7 @@ class CtsTextMetadata(ResourceCollection, PrototypeCtsCollection):
MODEL_URI = URIRef(RDF_Namespaces.DTS.resource)
EXPORT_TO = [Mimetypes.XML.CTS]
CTS_PROPERTIES = [RDF_Namespaces.CTS.label, RDF_Namespaces.CTS.description]
CTS_LINKS = [RDF_Namespaces.CTS.about]
SUBTYPE = "unknown"

def __init__(self, urn="", parent=None, lang=None):
Expand Down Expand Up @@ -228,7 +264,7 @@ def __export__(self, output=None, domain="", namespaces=True, lines="\n"):
:type output: basestring
:param domain: Domain to prefix IDs when necessary
:type domain: str
:returns: Desired output formated resource
:returns: Desired output formatted resource
"""
if output == Mimetypes.XML.CTS:
attrs = {"urn": self.id, "xml:lang": self.lang}
Expand All @@ -248,7 +284,18 @@ def __export__(self, output=None, domain="", namespaces=True, lines="\n"):
)
)

# XmlCtsCitation !
for pred in self.CTS_LINKS:
# For each predicate in CTS_LINKS
for obj in self.graph.objects(self.metadata.asNode(), pred):
# For each item in the graph connected to the current item metadata as object through the predicate "pred"
strings.append(
make_xml_node(
self.graph, pred, attributes={"urn": str(obj)}, complete=True
)
# <pref urn="obj.language"/>
)

# Citation !
if self.citation is not None:
strings.append(
# Online
Expand Down Expand Up @@ -329,6 +376,20 @@ class CtsTranslationMetadata(CtsTextMetadata):
MODEL_URI = URIRef(RDF_Namespaces.DTS.resource)
SUBTYPE = "translation"

class CtsCommentaryMetadata(CtsTextMetadata):
""" Represents a CTS Commentary
:param urn: Identifier of the PrototypeText
:type urn: str
:param parent: Parent of current item
:type parent: PrototypeWork
:param lang: Language of the commentary
:type lang: Lang
"""
TYPE_URI = RDF_Namespaces.CTS.term("commentary")
MODEL_URI = URIRef(RDF_Namespaces.DTS.resource)
SUBTYPE = "commentary"


class CtsWorkMetadata(PrototypeCtsCollection):
""" Represents a CTS CtsWorkMetadata
Expand Down
12 changes: 6 additions & 6 deletions tests/resolvers/cts/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,16 +311,16 @@ def test_getMetadata_full(self):
"Members of Inventory should be TextGroups"
)
self.assertEqual(
len(metadata.descendants), 32,
"There should be as many descendants as there is edition, translation, works and textgroup"
len(metadata.descendants), 33,
"There should be as many descendants as there is edition, translation, commentaries, works and textgroup"
)
self.assertEqual(
len(metadata.readableDescendants), 15,
"There should be as many readable descendants as there is edition, translation"
len(metadata.readableDescendants), 16,
"There should be as many readable descendants as there is edition, translation, and commentaries"
)
self.assertEqual(
len([x for x in metadata.readableDescendants if isinstance(x, XmlCtsTextMetadata)]), 15,
"There should be 14 editions + 1 translations in readableDescendants"
len([x for x in metadata.readableDescendants if isinstance(x, XmlCtsTextMetadata)]), 16,
"There should be 14 editions + 1 translations + 1 commentary in readableDescendants"
)
self.assertEqual(
len(metadata.export(output=Mimetypes.PYTHON.ETREE).xpath("//ti:edition[@urn='urn:cts:latinLit:phi1294.phi002.perseus-lat2']", namespaces=XPath_Namespaces)), 1,
Expand Down
72 changes: 46 additions & 26 deletions tests/resolvers/cts/test_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@

from MyCapytain.resolvers.cts.local import CtsCapitainsLocalResolver
from MyCapytain.common.constants import XPath_Namespaces, Mimetypes, RDF_Namespaces, get_graph
from MyCapytain.common.constants import XPath_Namespaces, Mimetypes, RDF_Namespaces, get_graph
from MyCapytain.common.reference import URN, Reference
from MyCapytain.errors import InvalidURN, UnknownObjectError, UndispatchedTextError
from MyCapytain.resources.prototypes.metadata import Collection
from MyCapytain.resources.collections.cts import XmlCtsTextInventoryMetadata
from MyCapytain.resources.prototypes.cts.inventory import CtsTextgroupMetadata, CtsTextMetadata as TextMetadata, \
CtsTranslationMetadata, CtsTextInventoryMetadata, CtsTextInventoryCollection
CtsTranslationMetadata, CtsTextInventoryMetadata, CtsCommentaryMetadata, CtsTextInventoryCollection
from MyCapytain.resources.prototypes.text import Passage
from MyCapytain.resolvers.utils import CollectionDispatcher
from unittest import TestCase
Expand Down Expand Up @@ -58,13 +57,17 @@ def test_get_capabilities(self):
["./tests/testing_data/farsiLit"]
)
self.assertEqual(
len(Repository.__getTextMetadata__()[0]), 4,
len(Repository.__getTextMetadata__()[0]), 5,
"General no filter works"
)
self.assertEqual(
len(Repository.__getTextMetadata__(category="edition")[0]), 2,
"Type filter works"
)
self.assertEqual(
len(Repository.__getTextMetadata__(category="commentary")[0]), 1,
"Type filter works"
)
self.assertEqual(
len(Repository.__getTextMetadata__(lang="ger")[0]), 1,
"Filtering on language works"
Expand All @@ -77,6 +80,10 @@ def test_get_capabilities(self):
len(Repository.__getTextMetadata__(category="translation", lang="ger")[0]), 1,
"Type filter + lang works"
)
self.assertEqual(
len(Repository.__getTextMetadata__(category="commentary", lang="lat")[0]), 1,
"Type filter + lang works"
)
self.assertEqual(
len(Repository.__getTextMetadata__(page=1, limit=2, pagination=True)[0]), 2,
"Pagination works without other filters"
Expand All @@ -90,7 +97,7 @@ def test_get_capabilities(self):
"URN Filtering works"
)
self.assertEqual(
len(Repository.__getTextMetadata__(urn="urn:cts:latinLit")[0]), 1,
len(Repository.__getTextMetadata__(urn="urn:cts:latinLit")[0]), 2,
"URN Filtering works"
)
self.assertEqual(
Expand Down Expand Up @@ -420,17 +427,17 @@ def test_getMetadata_full(self):
"Members of Inventory should be TextGroups"
)
self.assertEqual(
len(metadata.descendants), 43,
"There should be as many descendants as there is edition, translation, works and textgroup + 1 for "
"default inventory"
len(metadata.descendants), 44,
"There should be as many descendants as there is edition, translation, commentary, works and textgroup + 1 "
"for default inventory"
)
self.assertEqual(
len(metadata.readableDescendants), 25,
"There should be as many readable descendants as there is edition, translation(25 ed+tr)"
len(metadata.readableDescendants), 26,
"There should be as many readable descendants as there is edition, translation, commentary (26 ed+tr+cm)"
)
self.assertEqual(
len([x for x in metadata.readableDescendants if isinstance(x, TextMetadata)]), 25,
"There should be 24 editions + 1 translations in readableDescendants"
len([x for x in metadata.readableDescendants if isinstance(x, TextMetadata)]), 26,
"There should be 24 editions + 1 translation + 1 commentary in readableDescendants"
)
self.assertEqual(
len(metadata.export(output=Mimetypes.PYTHON.ETREE).xpath(
Expand All @@ -456,16 +463,16 @@ def test_getMetadata_subset(self):
"Members of CtsWorkMetadata should be Texts"
)
self.assertEqual(
len(metadata.descendants), 1,
"There should be as many descendants as there is edition, translation"
len(metadata.descendants), 2,
"There should be as many descendants as there is edition, translation, commentary"
)
self.assertEqual(
len(metadata.readableDescendants), 1,
"There should be 1 edition in readableDescendants"
len(metadata.readableDescendants), 2,
"There should be 1 edition + 1 commentary in readableDescendants"
)
self.assertEqual(
len([x for x in metadata.readableDescendants if isinstance(x, TextMetadata)]), 1,
"There should be 1 edition in readableDescendants"
len([x for x in metadata.readableDescendants if isinstance(x, TextMetadata)]), 2,
"There should be 1 edition + 1 commentary in readableDescendants"
)
self.assertIsInstance(
metadata.parent, CtsTextgroupMetadata,
Expand All @@ -480,10 +487,10 @@ def test_getMetadata_subset(self):
"//ti:edition[@urn='urn:cts:latinLit:phi1294.phi002.perseus-lat2']", namespaces=XPath_Namespaces)), 1,
"There should be one node in exported format corresponding to lat2"
)
self.assertEqual(
self.assertCountEqual(
[x["@id"] for x in metadata.export(output=Mimetypes.JSON.DTS.Std)["@graph"]["dts:members"]],
["urn:cts:latinLit:phi1294.phi002.perseus-lat2"],
"There should be one member in DTS JSON"
["urn:cts:latinLit:phi1294.phi002.opp-eng3", "urn:cts:latinLit:phi1294.phi002.perseus-lat2"],
"There should be two members in DTS JSON"
)

tr = self.resolver.getMetadata(objectId="urn:cts:greekLit:tlg0003.tlg001.opp-fre1")
Expand All @@ -499,6 +506,19 @@ def test_getMetadata_subset(self):
"Description should be the right one"
)

cm = self.resolver.getMetadata(objectId="urn:cts:latinLit:phi1294.phi002.opp-eng3")
self.assertIsInstance(
cm, CtsCommentaryMetadata, "Metadata should be commentary"
)
self.assertEqual(
cm.lang, "eng", "Language is English"
)
self.assertIn(
"Introduction to Martial's Epigrammata",
cm.get_description("eng"),
"Description should be the right one"
)

def test_getSiblings(self):
""" Ensure getSiblings works well """
previous, nextious = self.resolver.getSiblings(
Expand Down Expand Up @@ -618,8 +638,8 @@ def dispatchGreekLit(collection, path=None, **kwargs):
greek_stuff = resolver.getMetadata("urn:perseus:greekLit")
farsi_stuff = resolver.getMetadata("urn:perseus:farsiLit")
self.assertEqual(
len(latin_stuff.readableDescendants), 19,
"There should be 19 readable descendants in Latin"
len(latin_stuff.readableDescendants), 20,
"There should be 20 readable descendants in Latin"
)
self.assertIsInstance(
latin_stuff, CtsTextInventoryMetadata, "should be textinventory"
Expand Down Expand Up @@ -714,8 +734,8 @@ def dispatchGreekLit(collection, path=None, **kwargs):
latin_stuff, greek_stuff, farsi_stuff = XmlCtsTextInventoryMetadata.parse(latin_stuff), XmlCtsTextInventoryMetadata.parse(greek_stuff), \
XmlCtsTextInventoryMetadata.parse(farsi_stuff)
self.assertEqual(
len(latin_stuff.readableDescendants), 19,
"There should be 19 readable descendants in Latin"
len(latin_stuff.readableDescendants), 20,
"There should be 20 readable descendants in Latin"
)
self.assertIsInstance(
latin_stuff, CtsTextInventoryMetadata, "should be textinventory"
Expand All @@ -735,6 +755,6 @@ def dispatchGreekLit(collection, path=None, **kwargs):
get_graph().remove((None, None, None))
all = XmlCtsTextInventoryMetadata.parse(all)
self.assertEqual(
len(all.readableDescendants), 25,
"There should be all 25 readable descendants in the master collection"
len(all.readableDescendants), 26,
"There should be all 26 readable descendants in the master collection"
)

0 comments on commit f65b57c

Please sign in to comment.