linkture 3.3.1__tar.gz → 4.1.0__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.
- {linkture-3.3.1 → linkture-4.1.0}/PKG-INFO +1 -2
- {linkture-3.3.1 → linkture-4.1.0}/pyproject.toml +1 -2
- {linkture-3.3.1 → linkture-4.1.0}/src/linkture/__main__.py +26 -19
- {linkture-3.3.1 → linkture-4.1.0}/src/linkture/linkture.py +47 -30
- {linkture-3.3.1 → linkture-4.1.0}/src/linkture/res/custom.json +1 -1
- {linkture-3.3.1 → linkture-4.1.0}/src/linkture/res/resources.db +0 -0
- {linkture-3.3.1 → linkture-4.1.0}/LICENSE +0 -0
- {linkture-3.3.1 → linkture-4.1.0}/README.md +0 -0
- {linkture-3.3.1 → linkture-4.1.0}/src/linkture/__init__.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: linkture
|
3
|
-
Version:
|
3
|
+
Version: 4.1.0
|
4
4
|
Summary: PARSE and PROCESS BIBLE SCRIPTURE REFERENCES: extract, tag, link, rewrite, translate, BCV-encode and decode
|
5
5
|
Keywords: bible,scriptures,scripture-references,scripture-translation,scripture-parser,scripture-linker
|
6
6
|
Author-Email: "Eryk J." <infiniti@inventati.org>
|
@@ -23,7 +23,6 @@ Requires-Dist: setuptools>=59.6.0
|
|
23
23
|
Requires-Dist: argparse>=1.4.0
|
24
24
|
Requires-Dist: regex>=2023.8.8
|
25
25
|
Requires-Dist: unidecode>=1.3.8
|
26
|
-
Requires-Dist: pandas==2.2.*
|
27
26
|
Requires-Dist: pathlib>=1.0.1
|
28
27
|
Description-Content-Type: text/markdown
|
29
28
|
|
@@ -10,7 +10,6 @@ dependencies = [
|
|
10
10
|
"argparse>=1.4.0",
|
11
11
|
"regex>=2023.8.8",
|
12
12
|
"unidecode>=1.3.8",
|
13
|
-
"pandas==2.2.*",
|
14
13
|
"pathlib>=1.0.1",
|
15
14
|
]
|
16
15
|
requires-python = ">=3.9"
|
@@ -36,7 +35,7 @@ keywords = [
|
|
36
35
|
"scripture-parser",
|
37
36
|
"scripture-linker",
|
38
37
|
]
|
39
|
-
version = "
|
38
|
+
version = "4.1.0"
|
40
39
|
|
41
40
|
[project.license]
|
42
41
|
text = "MIT"
|
@@ -26,7 +26,7 @@
|
|
26
26
|
SOFTWARE.
|
27
27
|
"""
|
28
28
|
|
29
|
-
import argparse
|
29
|
+
import argparse, sys, traceback
|
30
30
|
from .linkture import _available_languages, __app__, __version__, Scriptures
|
31
31
|
from ast import literal_eval
|
32
32
|
|
@@ -34,24 +34,31 @@ from ast import literal_eval
|
|
34
34
|
def main(args):
|
35
35
|
|
36
36
|
def switchboard(text):
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
37
|
+
try:
|
38
|
+
if args['l'] is not None:
|
39
|
+
prefix = '<a href="'
|
40
|
+
suffix = '">'
|
41
|
+
if len(args['l']) > 1 and args['l'][1] != '':
|
42
|
+
suffix = args['l'][1]
|
43
|
+
if len(args['l']) > 0 and args['l'][0] != '':
|
44
|
+
prefix = args['l'][0]
|
45
|
+
return s.link_scriptures(text, prefix, suffix)
|
46
|
+
elif args['c']:
|
47
|
+
return s.code_scriptures(text)
|
48
|
+
elif args['d']:
|
49
|
+
return s.decode_scriptures(literal_eval(text))
|
50
|
+
elif args['x']:
|
51
|
+
return s.list_scriptures(text)
|
52
|
+
elif args['t']:
|
53
|
+
return s.tag_scriptures(text)
|
54
|
+
else:
|
55
|
+
return s.rewrite_scriptures(text)
|
56
|
+
except Exception as e:
|
57
|
+
print("\n--- CRASH DETECTED ---", file=sys.stderr)
|
58
|
+
print("Input causing failure:", repr(text), file=sys.stderr)
|
59
|
+
print("Error:", str(e), file=sys.stderr)
|
60
|
+
traceback.print_exc()
|
61
|
+
raise
|
55
62
|
|
56
63
|
form = None
|
57
64
|
if args['standard']:
|
@@ -27,11 +27,10 @@
|
|
27
27
|
"""
|
28
28
|
|
29
29
|
__app__ = 'linkture'
|
30
|
-
__version__ = '
|
30
|
+
__version__ = 'v4.1.0'
|
31
31
|
|
32
32
|
|
33
33
|
import json, regex, sqlite3
|
34
|
-
import pandas as pd
|
35
34
|
from pathlib import Path
|
36
35
|
from unidecode import unidecode
|
37
36
|
|
@@ -66,25 +65,27 @@ class Scriptures():
|
|
66
65
|
form = 5
|
67
66
|
else:
|
68
67
|
form = 3
|
69
|
-
self._src_book_names = {}
|
70
|
-
path = Path(__file__).resolve().parent
|
71
68
|
|
72
|
-
|
69
|
+
path = Path(__file__).resolve().parent
|
73
70
|
con = sqlite3.connect(path / 'res/resources.db')
|
74
71
|
cur = con.cursor()
|
75
|
-
|
72
|
+
|
73
|
+
self._src_book_names = {}
|
74
|
+
self._tr_book_names = ['Bible']
|
75
|
+
for rec in cur.execute(f"SELECT * FROM Books WHERE Language = ?;", (translate,)).fetchall():
|
76
76
|
if self._upper:
|
77
77
|
tr = rec[form].upper()
|
78
78
|
else:
|
79
79
|
tr = rec[form]
|
80
80
|
self._tr_book_names.insert(rec[2], tr)
|
81
|
-
for rec in cur.execute(f"SELECT * FROM Books WHERE Language =
|
81
|
+
for rec in cur.execute(f"SELECT * FROM Books WHERE Language = ?;", (language,)).fetchall():
|
82
82
|
for i in range(3,6):
|
83
83
|
item = rec[i]
|
84
84
|
if not self._nl:
|
85
85
|
item = unidecode(item)
|
86
86
|
normalized = regex.sub(r'\p{P}|\p{Z}', '', item.upper())
|
87
87
|
self._src_book_names[normalized] = rec[2]
|
88
|
+
|
88
89
|
with open(path / 'res/custom.json', 'r', encoding='UTF-8') as json_file:
|
89
90
|
b = json.load(json_file)
|
90
91
|
if language in b.keys():
|
@@ -95,12 +96,30 @@ class Scriptures():
|
|
95
96
|
item = unidecode(item)
|
96
97
|
normalized = regex.sub(r'\p{P}|\p{Z}', '', item.upper())
|
97
98
|
self._src_book_names[normalized] = row[0]
|
98
|
-
|
99
|
-
|
100
|
-
self.
|
101
|
-
|
99
|
+
|
100
|
+
# Ranges: {(book, chapter): last} (chapter 0 -> num of chapters in book)
|
101
|
+
self._ranges = {}
|
102
|
+
for book, chapter, last in cur.execute("SELECT Book, Chapter, Last FROM Ranges;"):
|
103
|
+
self._ranges[(book, chapter)] = last
|
104
|
+
|
105
|
+
# Chapters: two-way mappings
|
106
|
+
self._chapters = {}
|
107
|
+
self._chapters_id = {}
|
108
|
+
for chapter_id, book, chapter in cur.execute("SELECT ChapterId, Book, Chapter FROM Chapters;"):
|
109
|
+
self._chapters[(book, chapter)] = chapter_id
|
110
|
+
self._chapters_id[chapter_id] = (book, chapter)
|
111
|
+
|
112
|
+
# Verses: two-way mappings
|
113
|
+
self._verses = {}
|
114
|
+
self._verses_id = {}
|
115
|
+
for verse_id, book, chapter, verse in cur.execute("SELECT VerseId, Book, Chapter, Verse FROM Verses;"):
|
116
|
+
self._verses[(book, chapter, verse)] = verse_id
|
117
|
+
self._verses_id[verse_id] = (book, chapter, verse)
|
118
|
+
|
102
119
|
cur.close()
|
103
120
|
con.close()
|
121
|
+
|
122
|
+
self._headings = (3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 92, 98, 100, 101, 102, 103, 108, 109, 110, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 138, 139, 140, 141, 142, 143, 144, 145)
|
104
123
|
self._reported = []
|
105
124
|
self._encoded = {}
|
106
125
|
self._linked = {}
|
@@ -151,7 +170,6 @@ class Scriptures():
|
|
151
170
|
""", flags=regex.VERBOSE | regex.IGNORECASE)
|
152
171
|
|
153
172
|
self._tagged = regex.compile(r'({{.*?}})')
|
154
|
-
|
155
173
|
self._cv_cv = regex.compile(r'(\d+):(\d+)-(\d+):(\d+)')
|
156
174
|
self._v_cv = regex.compile(r'(\d+)-(\d+):(\d+)')
|
157
175
|
self._cv_v = regex.compile(r'(\d+):(\d+)-(\d+)')
|
@@ -162,7 +180,6 @@ class Scriptures():
|
|
162
180
|
self._d_d = regex.compile(r'(\d+)-(\d+)(?!:)')
|
163
181
|
self._dd = regex.compile(r'(\d+),(\d+)')
|
164
182
|
self._d = regex.compile(r'(\d+)')
|
165
|
-
|
166
183
|
self._chunk = regex.compile(r'([^,;\p{Z}]+.*)')
|
167
184
|
self._sep = regex.compile(r'(?<!;)\s')
|
168
185
|
|
@@ -181,7 +198,7 @@ class Scriptures():
|
|
181
198
|
return None, 0
|
182
199
|
else:
|
183
200
|
bk_num = self._src_book_names[bk_name]
|
184
|
-
return
|
201
|
+
return bk_num, self._ranges.get((bk_num, 0))
|
185
202
|
|
186
203
|
reduced = regex.sub(r'\p{Z}', '', scripture)
|
187
204
|
reduced = regex.sub(r'\p{Pd}', '-', reduced)
|
@@ -258,7 +275,7 @@ class Scriptures():
|
|
258
275
|
|
259
276
|
def _code_scripture(self, scripture, bk_num, rest, last):
|
260
277
|
|
261
|
-
def reform_series(txt): # rewrite comma-separated consecutive sequences
|
278
|
+
def reform_series(txt): # rewrite comma-separated consecutive sequences (1, 2, 3) as ranges (1-3)
|
262
279
|
for result in self._d_dd.finditer(txt, overlapped=True):
|
263
280
|
end = result.group(3)
|
264
281
|
mid = result.group(2)
|
@@ -287,13 +304,13 @@ class Scriptures():
|
|
287
304
|
v = int(vs)
|
288
305
|
if not (0 < b <= 66): # book out of range
|
289
306
|
return None
|
290
|
-
if not (0 < c <= self._ranges.
|
307
|
+
if not (0 < c <= self._ranges.get((b, 0), 0)): # chapter out of range
|
291
308
|
return None
|
292
309
|
if b == 19 and c in self._headings:
|
293
310
|
first = 0
|
294
311
|
else:
|
295
312
|
first = 1
|
296
|
-
if not (first <= v <= self._ranges.
|
313
|
+
if not (first <= v <= self._ranges.get((b, c), 0)): # verse out of range
|
297
314
|
return None
|
298
315
|
return True
|
299
316
|
|
@@ -376,7 +393,7 @@ class Scriptures():
|
|
376
393
|
if not validate(book, c, v):
|
377
394
|
return None, 0
|
378
395
|
ch2 = c.zfill(3)
|
379
|
-
v2 = str(self._ranges.
|
396
|
+
v2 = str(self._ranges.get((book, int(ch2)))).zfill(3)
|
380
397
|
return (b+ch1+v1, b+ch2+v2), None
|
381
398
|
else:
|
382
399
|
c = 1
|
@@ -405,7 +422,7 @@ class Scriptures():
|
|
405
422
|
v1 = '000'
|
406
423
|
else:
|
407
424
|
v1 = '001'
|
408
|
-
v2 = str(self._ranges.
|
425
|
+
v2 = str(self._ranges.get((book, int(ch1)))).zfill(3)
|
409
426
|
return (b+ch1+v1, b+ch1+v2), None
|
410
427
|
else:
|
411
428
|
c = 1
|
@@ -420,7 +437,7 @@ class Scriptures():
|
|
420
437
|
|
421
438
|
lst = []
|
422
439
|
if rest == '': # whole book
|
423
|
-
v = self._ranges.
|
440
|
+
v = self._ranges.get((bk_num, last))
|
424
441
|
if last == 1:
|
425
442
|
rest = f'1-{v}'
|
426
443
|
else:
|
@@ -465,11 +482,11 @@ class Scriptures():
|
|
465
482
|
return None, '', 0, False, ''
|
466
483
|
if not ((0 < sb <= 66) & (sb == eb)): # book out of range
|
467
484
|
return None, '', 0, False, ''
|
468
|
-
lc = self._ranges.
|
485
|
+
lc = self._ranges.get((sb, 0), 0)
|
469
486
|
if not (0 < sc <= ec <= lc): # chapter(s) out of range
|
470
487
|
return None, '', 0, False, ''
|
471
|
-
se = self._ranges.
|
472
|
-
le = self._ranges.
|
488
|
+
se = self._ranges.get((sb, sc), 0)
|
489
|
+
le = self._ranges.get((sb, ec), 0)
|
473
490
|
minev = 1
|
474
491
|
minsv = 1
|
475
492
|
if sb == 19 and (sc in self._headings):
|
@@ -607,22 +624,22 @@ class Scriptures():
|
|
607
624
|
|
608
625
|
def serial_chapter_number(self, bcv):
|
609
626
|
try:
|
610
|
-
return
|
627
|
+
return self._chapters[(int(bcv[0:2]), int(bcv[2:5]))]
|
611
628
|
except:
|
612
629
|
self._error_report(bcv, 'OUT OF RANGE')
|
613
630
|
return None
|
614
631
|
|
615
632
|
def serial_verse_number(self, bcv):
|
616
633
|
try:
|
617
|
-
return
|
634
|
+
return self._verses[(int(bcv[0:2]), int(bcv[2:5]), int(bcv[5:]))] + 1
|
618
635
|
except:
|
619
636
|
self._error_report(bcv, 'OUT OF RANGE')
|
620
637
|
return None
|
621
638
|
|
622
639
|
def code_chapter(self, chapter):
|
623
640
|
try:
|
624
|
-
book, chapter = self.
|
625
|
-
last = self._ranges.
|
641
|
+
book, chapter = self._chapters_id[int(chapter)]
|
642
|
+
last = self._ranges.get((book, chapter))
|
626
643
|
bc = str(book).zfill(2) + str(chapter).zfill(3)
|
627
644
|
if book == 19 and chapter in self._headings: # some chapters start at verse 0
|
628
645
|
v = '000'
|
@@ -636,9 +653,9 @@ class Scriptures():
|
|
636
653
|
def code_verse(self, verse):
|
637
654
|
bcv = ''
|
638
655
|
try:
|
639
|
-
|
640
|
-
|
641
|
-
return f"('{bcv
|
656
|
+
bk, ch, vs = self._verses_id[int(verse)-1]
|
657
|
+
bcv = f"{bk:02d}{ch:03d}{vs:03d}"
|
658
|
+
return f"('{bcv}', '{bcv}')"
|
642
659
|
except:
|
643
660
|
self._error_report(verse, 'OUT OF RANGE')
|
644
661
|
return None
|
index 2500a66..e597681 100644
|
|
Binary file
|
File without changes
|
File without changes
|
File without changes
|