usfmtc 0.2.2__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {usfmtc-0.2.2/python/lib/usfmtc.egg-info → usfmtc-0.2.3}/PKG-INFO +1 -1
- {usfmtc-0.2.2 → usfmtc-0.2.3}/pyproject.toml +1 -1
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/__init__.py +15 -13
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/extension.py +2 -2
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/usfmparser.py +49 -39
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/xmlutils.py +13 -3
- {usfmtc-0.2.2 → usfmtc-0.2.3/python/lib/usfmtc.egg-info}/PKG-INFO +1 -1
- {usfmtc-0.2.2 → usfmtc-0.2.3}/LICENSE.md +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/README.md +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/README.md +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/diagrams.py +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/grammar.py +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/parser.py +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/railroad.py +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/reference.py +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/rnc2rng/__init__.py +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/rnc2rng/parser.py +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/rnc2rng/rnctree.py +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/rnc2rng/serializer.py +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/sfmparser.py +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/usfmgenerate.py +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/usjproc.py +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/usx.rng +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/usxgrammar.py +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/usxmodel.py +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc/usxparser.py +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc.egg-info/SOURCES.txt +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc.egg-info/dependency_links.txt +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc.egg-info/entry_points.txt +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc.egg-info/requires.txt +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/python/lib/usfmtc.egg-info/top_level.txt +0 -0
- {usfmtc-0.2.2 → usfmtc-0.2.3}/setup.cfg +0 -0
|
@@ -58,15 +58,15 @@ def _usfmGrammar(rdoc, backend=None, start=None):
|
|
|
58
58
|
|
|
59
59
|
def usfmGrammar(gsrc, extensions=[], altparser=True, backend=None, start=None):
|
|
60
60
|
""" Create UsfmGrammarParser from gsrc as used by USX.fromUsfm """
|
|
61
|
-
if len(extensions) or not altparser:
|
|
62
|
-
rdoc = _grammarDoc(gsrc, extensions)
|
|
63
61
|
if altparser:
|
|
62
|
+
rdoc = _grammarDoc(gsrc, extensions)
|
|
63
|
+
return _usfmGrammar(rdoc, backend, start)
|
|
64
|
+
else:
|
|
64
65
|
res = Grammar()
|
|
65
66
|
if len(extensions):
|
|
66
67
|
for e in extensions:
|
|
67
68
|
res.readmrkrs(e)
|
|
68
69
|
return res
|
|
69
|
-
return _usfmGrammar(rdoc, backend, start)
|
|
70
70
|
|
|
71
71
|
|
|
72
72
|
_filetypes = {".xml": "usx", ".usx": "usx", ".usfm": "usfm", ".sfm": "usfm3.0", ".json": "usj"}
|
|
@@ -129,10 +129,12 @@ class USX:
|
|
|
129
129
|
@classmethod
|
|
130
130
|
def fromUsfm(cls, src, grammar, altparser=True, elfactory=None, timeout=1e7):
|
|
131
131
|
""" Parses USFM using UsfmGrammarParser grammar and creates USX object.
|
|
132
|
-
Raise usfmtc.parser.NoParseError on error.
|
|
132
|
+
Raise usfmtc.parser.NoParseError on error.
|
|
133
|
+
elfactory must take parent and pos named parameters not as attributes
|
|
134
|
+
"""
|
|
133
135
|
data = _readsrc(src)
|
|
134
136
|
|
|
135
|
-
if altparser:
|
|
137
|
+
if not altparser:
|
|
136
138
|
p = USFMParser(data, factory=elfactory or ParentElement, grammar=grammar)
|
|
137
139
|
xml = p.parse()
|
|
138
140
|
else:
|
|
@@ -181,7 +183,7 @@ class USX:
|
|
|
181
183
|
def outUsfm(self, grammar, file=None, altparser=True, **kw):
|
|
182
184
|
""" Output USFM from USX object. grammar is et doc. If file is None returns string """
|
|
183
185
|
el = messup(self.xml)
|
|
184
|
-
if altparser:
|
|
186
|
+
if not altparser:
|
|
185
187
|
return self._outwrite(file, el, fn=usx2usfm)
|
|
186
188
|
parser = USXConverter(grammar.getroot(), **kw)
|
|
187
189
|
res = parser.parse(el)
|
|
@@ -217,7 +219,7 @@ class USX:
|
|
|
217
219
|
elif outtype == "usj":
|
|
218
220
|
self.outUsj(outfpath)
|
|
219
221
|
elif outtype == "usfm":
|
|
220
|
-
if grammar is None and
|
|
222
|
+
if grammar is None and altparser:
|
|
221
223
|
if gramfile is None:
|
|
222
224
|
for a in ([], ['..', '..', '..', 'grammar']):
|
|
223
225
|
gramfile = os.path.join(os.path.dirname(__file__), *a, "usx.rng")
|
|
@@ -263,7 +265,7 @@ def main(hookcli=None, hookusx=None):
|
|
|
263
265
|
parser.add_argument("-e","--esids",action="store_true",help="Add esids, vids, sids, etc. to USX output")
|
|
264
266
|
parser.add_argument("-v","--version",default=None,help="Set USFM version [3.1]")
|
|
265
267
|
parser.add_argument("-x","--extfiles",action="append",default=[],help="markers.ext files to include")
|
|
266
|
-
parser.add_argument("--
|
|
268
|
+
parser.add_argument("-V","--validate",action="store_true",help="Use validating parsers for USFM")
|
|
267
269
|
parser.add_argument("-C","--canonical",action="store_true",help="Do not canonicalise")
|
|
268
270
|
parser.add_argument("-l","--logging",help="Set logging level to usfmxtest.log")
|
|
269
271
|
parser.add_argument("-q","--quiet",action="store_true",help="Don't say much")
|
|
@@ -326,16 +328,16 @@ def main(hookcli=None, hookusx=None):
|
|
|
326
328
|
if args.informat.startswith("usfm"):
|
|
327
329
|
args.extfiles.append(os.path.join(os.path.dirname(infiles[0]), "markers.ext"))
|
|
328
330
|
exts = [x for x in args.extfiles if os.path.exists(x)]
|
|
329
|
-
ingrammar = usfmGrammar(args.grammar, altparser=args.
|
|
331
|
+
ingrammar = usfmGrammar(args.grammar, altparser=args.validate, extensions=exts)
|
|
330
332
|
if args.outformat and args.outformat.startswith("usfm"):
|
|
331
333
|
outgrammar = _grammarDoc(args.grammar)
|
|
332
334
|
|
|
333
335
|
for infile in infiles:
|
|
334
336
|
outfile = None
|
|
335
337
|
if args.outfile is None:
|
|
336
|
-
outfile = _makeoutfile(infile, args.
|
|
338
|
+
outfile = _makeoutfile(infile, args.outformat)
|
|
337
339
|
elif os.path.isdir(args.outfile):
|
|
338
|
-
outf = _makeoutfile(infile, args.
|
|
340
|
+
outf = _makeoutfile(infile, args.outformat)
|
|
339
341
|
if outf is None:
|
|
340
342
|
doerror(f"invalid output format {args.format} in {args.outfile}")
|
|
341
343
|
outfile = os.path.join(args.outfile, os.path.basename(outf))
|
|
@@ -351,7 +353,7 @@ def main(hookcli=None, hookusx=None):
|
|
|
351
353
|
if not args.quiet:
|
|
352
354
|
print(f"{infile} -> {outfile}" if outfile else f"{infile}")
|
|
353
355
|
try:
|
|
354
|
-
usxdoc = readFile(infile, informat=args.informat, grammar=ingrammar, altparser=args.
|
|
356
|
+
usxdoc = readFile(infile, informat=args.informat, grammar=ingrammar, altparser=args.validate)
|
|
355
357
|
except NoParseError as e:
|
|
356
358
|
doerror(f"Failed to parse {infile}: {e}", False)
|
|
357
359
|
|
|
@@ -373,7 +375,7 @@ def main(hookcli=None, hookusx=None):
|
|
|
373
375
|
if not args.canonical:
|
|
374
376
|
usxdoc.canonicalise()
|
|
375
377
|
|
|
376
|
-
usxdoc.saveAs(outfile, outformat=args.outformat, addesids=args.esids, grammar=outgrammar, altparser=args.
|
|
378
|
+
usxdoc.saveAs(outfile, outformat=args.outformat, addesids=args.esids, grammar=outgrammar, altparser=args.validate)
|
|
377
379
|
|
|
378
380
|
if __name__ == "__main__":
|
|
379
381
|
main()
|
|
@@ -58,11 +58,11 @@ class Extensions(SFMFile):
|
|
|
58
58
|
|
|
59
59
|
def applyto(self, rdoc, factory=et):
|
|
60
60
|
res = False # nothing added
|
|
61
|
-
allcats = set([x.get('category',
|
|
61
|
+
allcats = set([x.get('category', "").split()[0] for x in self.markers.values()])
|
|
62
62
|
for a in allcats:
|
|
63
63
|
if a not in categories:
|
|
64
64
|
continue
|
|
65
|
-
ms = [k for k, v in self.markers.items() if v.get('category',
|
|
65
|
+
ms = [k for k, v in self.markers.items() if a in v.get('category', "").split()]
|
|
66
66
|
enum = categories[a]+".style.enum"
|
|
67
67
|
e = rdoc.find('./{0}define[@name="{1}"]/{0}choice'.format(relaxns, enum))
|
|
68
68
|
allmks = set([v.text for v in e.findall(f'./{relaxns}value')])
|
|
@@ -5,8 +5,14 @@ import xml.etree.ElementTree as et
|
|
|
5
5
|
from usfmtc.extension import SFMFile
|
|
6
6
|
from collections import UserDict, UserString
|
|
7
7
|
|
|
8
|
+
|
|
9
|
+
class Pos:
|
|
10
|
+
def __init__(self, l, c):
|
|
11
|
+
self.l = l
|
|
12
|
+
self.c = c
|
|
13
|
+
|
|
8
14
|
class Tag(str):
|
|
9
|
-
def __new__(cls, s):
|
|
15
|
+
def __new__(cls, s, l=0, c=0):
|
|
10
16
|
isend = False
|
|
11
17
|
isplus = False
|
|
12
18
|
if s.startswith("+"):
|
|
@@ -23,7 +29,7 @@ class Tag(str):
|
|
|
23
29
|
def __init__(self, s, l=0, c=0):
|
|
24
30
|
self.isplus = getattr(self, 'isplus', False)
|
|
25
31
|
self.isend = getattr(self, 'isend', False)
|
|
26
|
-
self.pos = (l, c)
|
|
32
|
+
self.pos = Pos(l, c)
|
|
27
33
|
|
|
28
34
|
def __repr__(self):
|
|
29
35
|
return "Tag("+str(self)+")"
|
|
@@ -43,12 +49,12 @@ class Tag(str):
|
|
|
43
49
|
class AttribText(UserString):
|
|
44
50
|
def __init__(self, s, l=0, c=0):
|
|
45
51
|
super().__init__(s)
|
|
46
|
-
self.pos = (l, c)
|
|
52
|
+
self.pos = Pos(l, c)
|
|
47
53
|
pass
|
|
48
54
|
|
|
49
55
|
class OptBreak:
|
|
50
56
|
def __init__(self, l=0, c=0):
|
|
51
|
-
self.pos = (l, c)
|
|
57
|
+
self.pos = Pos(l, c)
|
|
52
58
|
|
|
53
59
|
def __repr__(self):
|
|
54
60
|
return "OptBreak(" + str(self) + ")"
|
|
@@ -58,7 +64,7 @@ class OptBreak:
|
|
|
58
64
|
class String(UserString):
|
|
59
65
|
def __init__(self, s, l=0, c=0):
|
|
60
66
|
super().__init__(s)
|
|
61
|
-
self.pos = (l, c)
|
|
67
|
+
self.pos = Pos(l, c)
|
|
62
68
|
|
|
63
69
|
def __add__(self, s):
|
|
64
70
|
return String(str(self) + s)
|
|
@@ -68,7 +74,7 @@ class String(UserString):
|
|
|
68
74
|
class Attribs(UserDict):
|
|
69
75
|
def __init__(self, l=0, c=0):
|
|
70
76
|
super().__init__()
|
|
71
|
-
self.pos = (l, c)
|
|
77
|
+
self.pos = Pos(l, c)
|
|
72
78
|
|
|
73
79
|
class Lexer:
|
|
74
80
|
|
|
@@ -113,7 +119,7 @@ class Lexer:
|
|
|
113
119
|
curri = m.end() + 1
|
|
114
120
|
continue
|
|
115
121
|
else:
|
|
116
|
-
res = Tag(t.group(0))
|
|
122
|
+
res = Tag(t.group(0), l=self.lindex, c=curri-self.lpos)
|
|
117
123
|
curri += t.end()
|
|
118
124
|
break
|
|
119
125
|
elif n == '|':
|
|
@@ -179,7 +185,7 @@ class Grammar:
|
|
|
179
185
|
"versepara": "cls nb pc pi1 pi2 pi3 pi po pr pmo pmc pmr pm ph1 ph2 ph3 ph p q1 q2 q3 q4 qc qr qm1 qm2 qm3 qm qd q b d mi1 mi2 mi3 mi4 mi m",
|
|
180
186
|
}
|
|
181
187
|
|
|
182
|
-
marker_categories = {t:k for k, v in category_markers.items() for t in v.split(
|
|
188
|
+
marker_categories = {t:k for k, v in category_markers.items() for t in v.split()}
|
|
183
189
|
|
|
184
190
|
attribmap = { 'jmp' : 'href', 'k' : 'key', 'qt-s': 'who', 'qt1-s': 'who', 'qt2-s': 'who',
|
|
185
191
|
'qt3-s': 'who', 'qt4-s': 'who', 'qt5-s': 'who', 'rb': 'gloss', 't-s': 'sid', 'ts-s': 'sid',
|
|
@@ -211,13 +217,13 @@ def isfirstText(e):
|
|
|
211
217
|
return True
|
|
212
218
|
|
|
213
219
|
class Node:
|
|
214
|
-
def __init__(self, parser, usxtag, tag, ispara=False, notag=False):
|
|
220
|
+
def __init__(self, parser, usxtag, tag, ispara=False, notag=False, pos=None):
|
|
215
221
|
self.parser = parser
|
|
216
222
|
self.tag = tag
|
|
217
223
|
self.ispara = ispara
|
|
218
224
|
parent = parser.stack[-1] if len(parser.stack) else None
|
|
219
225
|
self.element = parser.factory(usxtag, {} if notag or tag is None else {"style": tag},
|
|
220
|
-
parent=getattr(parent, 'element', None))
|
|
226
|
+
parent=getattr(parent, 'element', None), pos=pos)
|
|
221
227
|
if parent:
|
|
222
228
|
parent.addNodeElement(self.element)
|
|
223
229
|
self.attribnodes = []
|
|
@@ -227,7 +233,7 @@ class Node:
|
|
|
227
233
|
|
|
228
234
|
def appendElement(self, child):
|
|
229
235
|
if isinstance(child, OptBreak):
|
|
230
|
-
c = self.parser.factory("optbreak", {}, parent=self.element)
|
|
236
|
+
c = self.parser.factory("optbreak", {}, parent=self.element, pos=child.pos)
|
|
231
237
|
self.element.append(c)
|
|
232
238
|
self.clearAttribNodes()
|
|
233
239
|
|
|
@@ -297,11 +303,12 @@ class USXNode(Node):
|
|
|
297
303
|
self.element.set('version', str(t).strip())
|
|
298
304
|
|
|
299
305
|
class AttribNode(Node):
|
|
300
|
-
def __init__(self, parser, parent, tag):
|
|
306
|
+
def __init__(self, parser, parent, tag, pos=None):
|
|
301
307
|
self.parser = parser
|
|
302
308
|
self.parent = parent
|
|
303
309
|
self.parent.addAttribNode(self)
|
|
304
310
|
self.tag = tag
|
|
311
|
+
self.pos = pos
|
|
305
312
|
self.attribnodes = []
|
|
306
313
|
|
|
307
314
|
def addNodeElement(self, e):
|
|
@@ -313,8 +320,8 @@ class AttribNode(Node):
|
|
|
313
320
|
self.parent.element.set(attrib, str(t).strip())
|
|
314
321
|
|
|
315
322
|
class NumberNode(Node):
|
|
316
|
-
def __init__(self, parser, usxtag, tag, ispara=False):
|
|
317
|
-
super().__init__(parser, usxtag, tag, ispara=ispara)
|
|
323
|
+
def __init__(self, parser, usxtag, tag, ispara=False, pos=None):
|
|
324
|
+
super().__init__(parser, usxtag, tag, ispara=ispara, pos=pos)
|
|
318
325
|
self.hasarg = False
|
|
319
326
|
|
|
320
327
|
def appendText(self, t):
|
|
@@ -327,7 +334,7 @@ class NumberNode(Node):
|
|
|
327
334
|
if len(b) > 1 and b[1].strip():
|
|
328
335
|
self.parser.removeTag(self.tag)
|
|
329
336
|
if self.ispara:
|
|
330
|
-
self.parser.addNode(Node(self.parser, 'para', 'p'))
|
|
337
|
+
self.parser.addNode(Node(self.parser, 'para', 'p', pos=self.element.pos))
|
|
331
338
|
self.parser.stack[-1].appendText(b[1])
|
|
332
339
|
|
|
333
340
|
def addNodeElement(self, e):
|
|
@@ -335,8 +342,8 @@ class NumberNode(Node):
|
|
|
335
342
|
self.parser.stack[-1].addNodeElement(e)
|
|
336
343
|
|
|
337
344
|
class NoteNode(Node):
|
|
338
|
-
def __init__(self, parser, usxtag, tag):
|
|
339
|
-
super().__init__(parser, usxtag, tag)
|
|
345
|
+
def __init__(self, parser, usxtag, tag, pos=None):
|
|
346
|
+
super().__init__(parser, usxtag, tag, pos=pos)
|
|
340
347
|
self.hascaller = False
|
|
341
348
|
|
|
342
349
|
def appendText(self, t):
|
|
@@ -384,7 +391,10 @@ class USFMParser:
|
|
|
384
391
|
|
|
385
392
|
def __init__(self, txt, factory=None, grammar=None):
|
|
386
393
|
if factory is None:
|
|
387
|
-
|
|
394
|
+
def makeel(tag, attrib, **extras):
|
|
395
|
+
attrib.update({" "+k:v for k, v in extras.items()})
|
|
396
|
+
return et.Element(tag, attrib)
|
|
397
|
+
factory = makeel
|
|
388
398
|
if grammar is None:
|
|
389
399
|
grammar = Grammar()
|
|
390
400
|
self.factory = factory
|
|
@@ -467,31 +477,31 @@ class USFMParser:
|
|
|
467
477
|
if tag.isend:
|
|
468
478
|
return self.removeTag(str(tag))
|
|
469
479
|
elif self.stack[-1].tag == "c":
|
|
470
|
-
parent = AttribNode(self, self.stack[-1], str(tag))
|
|
480
|
+
parent = AttribNode(self, self.stack[-1], str(tag), pos=tag.pos)
|
|
471
481
|
else:
|
|
472
|
-
parent = Node(self, 'para', str(tag), ispara=True)
|
|
482
|
+
parent = Node(self, 'para', str(tag), ispara=True, pos=tag.pos)
|
|
473
483
|
self.stack.append(parent)
|
|
474
484
|
return parent
|
|
475
485
|
|
|
476
486
|
def _esb(self, tag):
|
|
477
487
|
self.removeType(paratypes, paratags)
|
|
478
|
-
return self.addNode(Node(self, "sidebar", str(tag)))
|
|
488
|
+
return self.addNode(Node(self, "sidebar", str(tag), pos=tag.pos))
|
|
479
489
|
|
|
480
490
|
def _esbe(self, tag):
|
|
481
491
|
return self.removeTag("esb")
|
|
482
492
|
|
|
483
493
|
def _periph(self, tag):
|
|
484
494
|
self.removeTag(str(tag))
|
|
485
|
-
return self.addNode(PeriphNode(self, "periph", str(tag), notag=True))
|
|
495
|
+
return self.addNode(PeriphNode(self, "periph", str(tag), notag=True, pos=tag.pos))
|
|
486
496
|
|
|
487
497
|
def _ref(self, tag):
|
|
488
498
|
if tag.isend:
|
|
489
499
|
return self.removeTag(str(tag))
|
|
490
|
-
return self.addNode(Node(self, 'ref', tag.basestr(), notag=True))
|
|
500
|
+
return self.addNode(Node(self, 'ref', tag.basestr(), notag=True, pos=tag.pos))
|
|
491
501
|
|
|
492
502
|
def _rem(self, tag):
|
|
493
503
|
self.removeType(paratypes, paratags)
|
|
494
|
-
res = self.addNode(Node(self, 'para', str(tag), ispara=True))
|
|
504
|
+
res = self.addNode(Node(self, 'para', str(tag), ispara=True, pos=tag.pos))
|
|
495
505
|
self.lexer.readLine()
|
|
496
506
|
return res
|
|
497
507
|
|
|
@@ -499,23 +509,23 @@ class USFMParser:
|
|
|
499
509
|
self.removeTag('tr')
|
|
500
510
|
if not len(self.stack) or self.stack[-1].element.tag != "table":
|
|
501
511
|
self.removeType(paratypes,)
|
|
502
|
-
self.addNode(Node(self, 'table', ' table', notag=True))
|
|
503
|
-
return self.addNode(Node(self, 'row', 'tr'))
|
|
512
|
+
self.addNode(Node(self, 'table', ' table', notag=True, pos=tag.pos))
|
|
513
|
+
return self.addNode(Node(self, 'row', 'tr', pos=tag.pos))
|
|
504
514
|
|
|
505
515
|
def _v(self, tag):
|
|
506
516
|
self.removeTag('v')
|
|
507
517
|
if len(self.stack) and self.stack[-1].tag == "c":
|
|
508
518
|
self.removeTag('c')
|
|
509
|
-
self.addNode(Node(self, 'para', 'p'))
|
|
510
|
-
return self.addNode(NumberNode(self, "verse", str(tag)))
|
|
519
|
+
self.addNode(Node(self, 'para', 'p', pos=tag.pos))
|
|
520
|
+
return self.addNode(NumberNode(self, "verse", str(tag), pos=tag.pos))
|
|
511
521
|
|
|
512
522
|
def _vp(self, tag):
|
|
513
523
|
if tag.isend:
|
|
514
524
|
return self.removeTag(str(tag))
|
|
515
525
|
elif self.stack[-1].tag == "v":
|
|
516
|
-
parent = AttribNode(self, self.stack[-1], str(tag))
|
|
526
|
+
parent = AttribNode(self, self.stack[-1], str(tag), pos=tag.pos)
|
|
517
527
|
else:
|
|
518
|
-
parent = Node(self, 'para', tag.basestr())
|
|
528
|
+
parent = Node(self, 'para', tag.basestr(), pos=tag.pos)
|
|
519
529
|
self.stack.append(parent)
|
|
520
530
|
return parent
|
|
521
531
|
|
|
@@ -523,43 +533,43 @@ class USFMParser:
|
|
|
523
533
|
if self.grammar.marker_categories.get(self.stack[-1].tag, "") == "crossreferencechar":
|
|
524
534
|
res = self.removeType('crossreferencechar')
|
|
525
535
|
if not tag.isend:
|
|
526
|
-
res = self.addNode(Node(self, 'char', tag.basestr()))
|
|
536
|
+
res = self.addNode(Node(self, 'char', tag.basestr(), pos=tag.pos))
|
|
527
537
|
return res
|
|
528
538
|
|
|
529
539
|
def attrib(self, tag):
|
|
530
540
|
if tag.isend:
|
|
531
541
|
return self.removeTag(str(tag))
|
|
532
542
|
else:
|
|
533
|
-
parent = AttribNode(self, self.stack[-1], str(tag))
|
|
543
|
+
parent = AttribNode(self, self.stack[-1], str(tag), pos=tag.pos)
|
|
534
544
|
self.stack.append(parent)
|
|
535
545
|
return parent
|
|
536
546
|
|
|
537
547
|
def cell(self, tag):
|
|
538
548
|
self.removeType('cell')
|
|
539
549
|
if not tag.isend:
|
|
540
|
-
return self.addNode(Node(self, 'cell', str(tag)))
|
|
550
|
+
return self.addNode(Node(self, 'cell', str(tag), pos=tag.pos))
|
|
541
551
|
return self.parent
|
|
542
552
|
|
|
543
553
|
def crossreference(self, tag):
|
|
544
554
|
if tag.isend:
|
|
545
555
|
return self.removeTag(str(tag))
|
|
546
|
-
return self.addNode(NoteNode(self, 'note', str(tag)))
|
|
556
|
+
return self.addNode(NoteNode(self, 'note', str(tag), pos=tag.pos))
|
|
547
557
|
|
|
548
558
|
def crossreferencechar(self, tag):
|
|
549
559
|
res = self.removeType('crossreferencechar')
|
|
550
560
|
if not tag.isend:
|
|
551
|
-
res = self.addNode(Node(self, 'char', tag.basestr()))
|
|
561
|
+
res = self.addNode(Node(self, 'char', tag.basestr(), pos=tag.pos))
|
|
552
562
|
return res
|
|
553
563
|
|
|
554
564
|
def footnote(self, tag):
|
|
555
565
|
if tag.isend:
|
|
556
566
|
return self.removeTag(str(tag))
|
|
557
|
-
return self.addNode(NoteNode(self, 'note', str(tag)))
|
|
567
|
+
return self.addNode(NoteNode(self, 'note', str(tag), pos=tag.pos))
|
|
558
568
|
|
|
559
569
|
def footnotechar(self, tag):
|
|
560
570
|
res = self.removeType('footnotechar')
|
|
561
571
|
if not tag.isend:
|
|
562
|
-
res = self.addNode(Node(self, 'char', tag.basestr()))
|
|
572
|
+
res = self.addNode(Node(self, 'char', tag.basestr(), pos=tag.pos))
|
|
563
573
|
return res
|
|
564
574
|
|
|
565
575
|
def ident(self, tag):
|
|
@@ -570,10 +580,10 @@ class USFMParser:
|
|
|
570
580
|
def milestone(self, tag):
|
|
571
581
|
if tag.isend:
|
|
572
582
|
return self.removeType('milestone')
|
|
573
|
-
return self.addNode(Node(self, 'ms', tag.basestr()))
|
|
583
|
+
return self.addNode(Node(self, 'ms', tag.basestr(), pos=tag.pos))
|
|
574
584
|
|
|
575
585
|
def unknown(self, tag):
|
|
576
|
-
self.addNode(Node(self, 'ms', str(tag)))
|
|
586
|
+
self.addNode(Node(self, 'ms', str(tag), pos=tag.pos))
|
|
577
587
|
res = self.removeTag(tag)
|
|
578
588
|
return res
|
|
579
589
|
|
|
@@ -3,12 +3,13 @@ import re
|
|
|
3
3
|
import xml.etree.ElementTree as et
|
|
4
4
|
|
|
5
5
|
class ParentElement(et.Element):
|
|
6
|
-
def __init__(self, tag, attrib=None, parent=None):
|
|
6
|
+
def __init__(self, tag, attrib=None, parent=None, pos=None):
|
|
7
7
|
et.Element.__init__(self, tag, attrib)
|
|
8
8
|
self.parent = parent
|
|
9
|
+
self.pos = pos
|
|
9
10
|
|
|
10
|
-
def makeelement(self, tag, attrib):
|
|
11
|
-
return self.__class__(tag, attrib, parent=self)
|
|
11
|
+
def makeelement(self, tag, attrib, pos=None):
|
|
12
|
+
return self.__class__(tag, attrib, parent=self, pos=pos or self.pos)
|
|
12
13
|
|
|
13
14
|
def __str__(self):
|
|
14
15
|
return "{}[{}]".format(self.tag, " ".join('@{}="{}"'.format(k, v) for k, v in self.attrib.items()))
|
|
@@ -18,19 +19,24 @@ class ParentElement(et.Element):
|
|
|
18
19
|
return "{}/{}".format(p, str(self))
|
|
19
20
|
|
|
20
21
|
def _getindex(self):
|
|
22
|
+
''' Finds my index in my parent, returning both '''
|
|
21
23
|
if self.parent is None:
|
|
22
24
|
return -1, None
|
|
23
25
|
return list(self.parent).index(self), self.parent
|
|
24
26
|
|
|
25
27
|
def getprevious(self):
|
|
28
|
+
''' Returns the previous element with the same parent, if any '''
|
|
26
29
|
i, parent = self._getindex()
|
|
27
30
|
return parent[i-1] if parent is not None and i > 0 else None
|
|
28
31
|
|
|
29
32
|
def getnext(self):
|
|
33
|
+
''' Returns the next element with the same parent, if any '''
|
|
30
34
|
i, parent = self._getindex()
|
|
31
35
|
return parent[i+1] if parent is not None and i < len(parent) - 1 else None
|
|
32
36
|
|
|
33
37
|
def getnext_sibling(self):
|
|
38
|
+
''' Returns the next element, while going up and down the hierarchy.
|
|
39
|
+
Notice that any text at the start of an element stops any hierarchy descent '''
|
|
34
40
|
i, parent = self._getindex()
|
|
35
41
|
if i < len(parent) - 1:
|
|
36
42
|
return parent[i+1]
|
|
@@ -41,6 +47,8 @@ class ParentElement(et.Element):
|
|
|
41
47
|
return parent
|
|
42
48
|
|
|
43
49
|
def getprevious_sibling(self):
|
|
50
|
+
''' Returns the previous element, while going up and down the hierarchy
|
|
51
|
+
Notice that any text after an element stops any hierarchy descent '''
|
|
44
52
|
i, parent = self._getindex()
|
|
45
53
|
if i > 0:
|
|
46
54
|
return parent[i-1]
|
|
@@ -51,11 +59,13 @@ class ParentElement(et.Element):
|
|
|
51
59
|
return parent
|
|
52
60
|
|
|
53
61
|
def addprevious(self, el):
|
|
62
|
+
''' Inserts el before the current element in the same parent '''
|
|
54
63
|
i, parent = self._getindex()
|
|
55
64
|
if parent is not None:
|
|
56
65
|
parent.insert(i, el)
|
|
57
66
|
|
|
58
67
|
def getparent(self):
|
|
68
|
+
''' Returns the parent '''
|
|
59
69
|
return self.parent
|
|
60
70
|
|
|
61
71
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|