Skip to content

Commit

Permalink
Merge 6c7d62e into 12fbd9d
Browse files Browse the repository at this point in the history
  • Loading branch information
PonteIneptique committed Jul 10, 2018
2 parents 12fbd9d + 6c7d62e commit 0b610d4
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 64 deletions.
10 changes: 10 additions & 0 deletions CHANGES.md
@@ -1,3 +1,13 @@
### 2018-06-25 2.0.8 @sonofmun

- Corrected error on the empty references exception from 2.0.7
- Now raises an exception when there is no refsDecl found (MissingRefsDecl)
- The exception now raised by a citation request that is deeper than the citation scheme is a CitationDepthError

### 2018-06-22 2.0.7 @sonofmun

- Added exception for empty references

### 2017-11-16 2.0.6 @ponteineptique

- Added a way to specify the joining string for Plaintext export in TEIResource (Fixed #146)
Expand Down
14 changes: 14 additions & 0 deletions MyCapytain/errors.py
Expand Up @@ -60,3 +60,17 @@ class UndispatchedTextError(Exception, MyCapytainException):
class UnknownCollection(KeyError, MyCapytainException):
""" A collection is unknown to its ancestor
"""

class EmptyReference(SyntaxWarning, MyCapytainException):
""" Error generated when a duplicate is found in Reference
"""


class CitationDepthError(UnknownObjectError, MyCapytainException):
""" Error generated when the depth of a requested citation is deeper than the citation scheme of the text
"""


class MissingRefsDecl(Exception, MyCapytainException):
""" A text has no properly encoded refsDecl
"""
4 changes: 1 addition & 3 deletions MyCapytain/resolvers/cts/local.py
Expand Up @@ -140,8 +140,7 @@ def _parse_textgroup(self, cts_file):
"""
with io.open(cts_file) as __xml__:
return self.classes["textgroup"].parse(
resource=__xml__,
_cls_dict=self.classes
resource=__xml__
), cts_file

def _parse_work_wrapper(self, cts_file, textgroup):
Expand Down Expand Up @@ -173,7 +172,6 @@ def _parse_work(self, cts_file, textgroup):
work, texts = self.classes["work"].parse(
resource=__xml__,
parent=textgroup,
_cls_dict=self.classes,
_with_children=True
)

Expand Down
86 changes: 43 additions & 43 deletions MyCapytain/resources/collections/cts.py
Expand Up @@ -27,8 +27,8 @@ class XmlCtsCitation(CitationPrototype):
"""

@staticmethod
def ingest(resource, element=None, xpath="ti:citation", _cls_dict=_CLASSES_DICT):
@classmethod
def ingest(cls, resource, element=None, xpath="ti:citation"):
""" Ingest xml to create a citation
:param resource: XML on which to do xpath
Expand All @@ -39,23 +39,22 @@ def ingest(resource, element=None, xpath="ti:citation", _cls_dict=_CLASSES_DICT)
"""
# Reuse of of find citation
results = resource.xpath(xpath, namespaces=XPATH_NAMESPACES)
CLASS = _cls_dict.get("citation", XmlCtsCitation)
if len(results) > 0:
citation = CLASS(
citation = cls(
name=results[0].get("label"),
xpath=results[0].get("xpath"),
scope=results[0].get("scope")
)

if isinstance(element, CLASS):
if isinstance(element, cls):
element.child = citation
CLASS.ingest(
cls.ingest(
resource=results[0],
element=element.child
)
else:
element = citation
CLASS.ingest(
cls.ingest(
resource=results[0],
element=element
)
Expand Down Expand Up @@ -131,6 +130,7 @@ class XmlCtsTextMetadata(cts.CtsTextMetadata):
"""
DEFAULT_EXPORT = Mimetypes.PYTHON.ETREE
CLASS_CITATION = XmlCtsCitation

@staticmethod
def __findCitations(obj, xml, xpath="ti:citation"):
Expand All @@ -140,15 +140,14 @@ def __findCitations(obj, xml, xpath="ti:citation"):
:param xpath: Xpath to use to retrieve the xml node
"""

@staticmethod
def parse_metadata(obj, xml, _cls_dict=_CLASSES_DICT):
@classmethod
def parse_metadata(cls, obj, xml):
""" Parse a resource to feed the object
:param obj: Obj to set metadata of
:type obj: XmlCtsTextMetadata
:param xml: An xml representation object
:type xml: lxml.etree._Element
:param _cls_dict: Dictionary of classes to generate subclasses
"""

for child in xml.xpath("ti:description", namespaces=XPATH_NAMESPACES):
Expand All @@ -161,7 +160,7 @@ def parse_metadata(obj, xml, _cls_dict=_CLASSES_DICT):
if lg is not None:
obj.set_cts_property("label", child.text, lg)

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

# Added for commentary
for child in xml.xpath("ti:about", namespaces=XPATH_NAMESPACES):
Expand Down Expand Up @@ -192,54 +191,57 @@ def path(self):
def path(self, value):
self._path = value


class XmlCtsEditionMetadata(cts.CtsEditionMetadata, XmlCtsTextMetadata):
""" Create an edition subtyped CtsTextMetadata object
"""
@staticmethod
def parse(resource, parent=None, _cls_dict=_CLASSES_DICT):
@classmethod
def parse(cls, resource, parent=None):
xml = xmlparser(resource)
o = _cls_dict.get("edition", XmlCtsEditionMetadata)(urn=xml.get("urn"), parent=parent)
type(o).parse_metadata(o, xml)

o = cls(urn=xml.get("urn"), parent=parent)
cls.parse_metadata(o, xml)
return o


class XmlCtsTranslationMetadata(cts.CtsTranslationMetadata, XmlCtsTextMetadata):
""" Create a translation subtyped CtsTextMetadata object
"""
@staticmethod
def parse(resource, parent=None, _cls_dict=_CLASSES_DICT):
@classmethod
def parse(cls, resource, parent=None):
xml = xmlparser(resource)
lang = xml.get("{http://www.w3.org/XML/1998/namespace}lang")

o = _cls_dict.get("translation", XmlCtsTranslationMetadata)(urn=xml.get("urn"), parent=parent)
o = cls(urn=xml.get("urn"), parent=parent)
if lang is not None:
o.lang = lang
type(o).parse_metadata(o, xml)
cls.parse_metadata(o, xml)
return o


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

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


class XmlCtsWorkMetadata(cts.CtsWorkMetadata):
""" Represents a CTS Textgroup in XML
"""
CLASS_EDITION = XmlCtsEditionMetadata
CLASS_TRANSLATION = XmlCtsTranslationMetadata
CLASS_COMMENTARY = XmlCtsCommentaryMetadata

@staticmethod
def parse(resource, parent=None, _cls_dict=_CLASSES_DICT, _with_children=False):
@classmethod
def parse(cls, resource, parent=None, _with_children=False):
""" Parse a resource
:param resource: Element rerpresenting a work
Expand All @@ -249,7 +251,7 @@ def parse(resource, parent=None, _cls_dict=_CLASSES_DICT, _with_children=False):
:param _cls_dict: Dictionary of classes to generate subclasses
"""
xml = xmlparser(resource)
o = _cls_dict.get("work", XmlCtsWorkMetadata)(urn=xml.get("urn"), parent=parent)
o = cls(urn=xml.get("urn"), parent=parent)

lang = xml.get("{http://www.w3.org/XML/1998/namespace}lang")
if lang is not None:
Expand All @@ -264,19 +266,15 @@ def parse(resource, parent=None, _cls_dict=_CLASSES_DICT, _with_children=False):
children = []
children.extend(xpathDict(
xml=xml, xpath='ti:edition',
cls=_cls_dict.get("edition", XmlCtsEditionMetadata), parent=o,
_cls_dict=_cls_dict
cls=cls.CLASS_EDITION, parent=o
))
children.extend(xpathDict(
xml=xml, xpath='ti:translation',
cls=_cls_dict.get("translation", XmlCtsTranslationMetadata), parent=o,
_cls_dict=_cls_dict
cls=cls.CLASS_TRANSLATION, parent=o
))
# Added for commentary
children.extend(xpathDict(
xml=xml, xpath='ti:commentary',
cls=_cls_dict.get("commentary", XmlCtsCommentaryMetadata), parent=o,
_cls_dict=_cls_dict
cls=cls.CLASS_COMMENTARY, parent=o
))

__parse_structured_metadata__(o, xml)
Expand All @@ -289,25 +287,26 @@ def parse(resource, parent=None, _cls_dict=_CLASSES_DICT, _with_children=False):
class XmlCtsTextgroupMetadata(cts.CtsTextgroupMetadata):
""" Represents a CTS Textgroup in XML
"""
CLASS_WORK = XmlCtsWorkMetadata

@staticmethod
def parse(resource, parent=None, _cls_dict=_CLASSES_DICT):
@classmethod
def parse(cls, resource, parent=None):
""" Parse a textgroup resource
:param resource: Element representing the textgroup
:param parent: Parent of the textgroup
:param _cls_dict: Dictionary of classes to generate subclasses
"""
xml = xmlparser(resource)
o = _cls_dict.get("textgroup", XmlCtsTextgroupMetadata)(urn=xml.get("urn"), parent=parent)
o = cls(urn=xml.get("urn"), parent=parent)

for child in xml.xpath("ti:groupname", namespaces=XPATH_NAMESPACES):
lg = child.get("{http://www.w3.org/XML/1998/namespace}lang")
if lg is not None:
o.set_cts_property("groupname", child.text, lg)

# Parse Works
xpathDict(xml=xml, xpath='ti:work', cls=_cls_dict.get("work", XmlCtsWorkMetadata), parent=o)
xpathDict(xml=xml, xpath='ti:work', cls=cls.CLASS_WORK, parent=o)

__parse_structured_metadata__(o, xml)
return o
Expand All @@ -316,16 +315,17 @@ def parse(resource, parent=None, _cls_dict=_CLASSES_DICT):
class XmlCtsTextInventoryMetadata(cts.CtsTextInventoryMetadata):
""" Represents a CTS Inventory file
"""
CLASS_TEXTGROUP = XmlCtsTextgroupMetadata

@staticmethod
def parse(resource, _cls_dict=_CLASSES_DICT):
@classmethod
def parse(cls, resource):
""" Parse a resource
:param resource: Element representing the text inventory
:param _cls_dict: Dictionary of classes to generate subclasses
"""
xml = xmlparser(resource)
o = _cls_dict.get("inventory", XmlCtsTextInventoryMetadata)(name=xml.xpath("//ti:TextInventory", namespaces=XPATH_NAMESPACES)[0].get("tiid") or "")
o = cls(name=xml.xpath("//ti:TextInventory", namespaces=XPATH_NAMESPACES)[0].get("tiid") or "")
# Parse textgroups
xpathDict(xml=xml, xpath='//ti:textgroup', cls=_cls_dict.get("textgroup", XmlCtsTextgroupMetadata), parent=o)
return o
xpathDict(xml=xml, xpath='//ti:textgroup', cls=cls.CLASS_TEXTGROUP, parent=o)
return o
20 changes: 11 additions & 9 deletions MyCapytain/resources/collections/dts.py
Expand Up @@ -3,15 +3,17 @@


class DTSCollection(Collection):
@staticmethod
def parse(resource, mimetype="application/json+ld"):
CLASS_SHORT = DTSCollectionShort

@classmethod
def parse(cls, resource, mimetype="application/json+ld"):
""" Given a dict representation of a json object, generate a DTS Collection
:param resource:
:param mimetype:
:return:
"""
obj = DTSCollection(identifier=resource["@id"])
obj = cls(identifier=resource["@id"])
obj.type = resource["type"]
obj.version = resource["version"]
for label in resource["label"]:
Expand All @@ -35,29 +37,29 @@ def parse(resource, mimetype="application/json+ld"):
obj.metadata.add(term, value)

for member in resource["members"]["contents"]:
subobj = DTSCollectionShort.parse(member)
subobj = cls.CLASS_SHORT.parse(member)
subobj.parent = member

last = obj
for member in resource["parents"]:
subobj = DTSCollectionShort.parse(member)
subobj = cls.CLASS_SHORT.parse(member)
last.parent = subobj

return obj


class DTSCollectionShort(DTSCollection):
@staticmethod
def parse(resource):
@classmethod
def parse(cls, resource):
""" Given a dict representation of a json object, generate a DTS Collection
:param resource:
:param mimetype:
:return:
"""
obj = DTSCollectionShort(identifier=resource["@id"])
obj = cls(identifier=resource["@id"])
obj.type = resource["type"]
obj.model = resource["model"]
for label in resource["label"]:
obj.set_label(label["value"], label["lang"])
return obj
return obj
13 changes: 10 additions & 3 deletions MyCapytain/resources/texts/local/capitains/cts.py
Expand Up @@ -11,7 +11,7 @@

import warnings

from MyCapytain.errors import DuplicateReference, MissingAttribute, RefsDeclError
from MyCapytain.errors import DuplicateReference, MissingAttribute, RefsDeclError, EmptyReference, CitationDepthError, MissingRefsDecl
from MyCapytain.common.utils import copyNode, passageLoop, normalizeXpath
from MyCapytain.common.constants import XPATH_NAMESPACES, RDF_NAMESPACES
from MyCapytain.common.reference import URN, Citation, Reference
Expand Down Expand Up @@ -68,7 +68,7 @@ def getTextualNode(self, subreference=None, simple=False):
start, end = subreference.start.list, subreference.end.list

if len(start) > len(self.citation):
raise ReferenceError("URN is deeper than citation scheme")
raise CitationDepthError("URN is deeper than citation scheme")

if simple is True:
return self._getSimplePassage(subreference)
Expand Down Expand Up @@ -248,6 +248,11 @@ def getValidReff(self, level=None, reference=None, _debug=False):
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)
print(empties)
warnings.warn(message, EmptyReference)

return passages

Expand Down Expand Up @@ -450,6 +455,8 @@ def __findCRefPattern(self, xml):
citation = xml.xpath("//tei:refsDecl[@n='CTS']", namespaces=XPATH_NAMESPACES)
if len(citation):
self.citation = Citation.ingest(resource=citation[0], xpath=".//tei:cRefPattern")
else:
raise MissingRefsDecl("No reference declaration (refsDecl) found.")

def test(self):
""" Parse the object and generate the children
Expand Down Expand Up @@ -664,4 +671,4 @@ def textObject(self):
:rtype: CapitainsCtsText
"""
return self.__text__
return self.__text__

0 comments on commit 0b610d4

Please sign in to comment.