Lots of additions and fixes

This commit is contained in:
Christopher T. Johnson
2024-04-16 10:52:34 -04:00
parent 303dbe6fe0
commit 1bce000978

View File

@@ -1,4 +1,3 @@
from importlib.abc import InspectLoader
from PyQt6.QtGui import QColor, QFont from PyQt6.QtGui import QColor, QFont
from trycast import trycast from trycast import trycast
import json import json
@@ -13,6 +12,7 @@ from lib.definition import Line, Fragment
registration = { registration = {
'source': 'mw', 'source': 'mw',
'name': 'Merriam-Webster', 'name': 'Merriam-Webster',
'language': 'en-us',
} }
API = "https://www.dictionaryapi.com/api/v3/references/collegiate/json/{word}?key={key}" API = "https://www.dictionaryapi.com/api/v3/references/collegiate/json/{word}?key={key}"
@@ -67,7 +67,7 @@ class Variant(TypedDict):
prs: NotRequired[list[Pronunciation]] prs: NotRequired[list[Pronunciation]]
spl: NotRequired[str] spl: NotRequired[str]
Inflection =TypedDict('Inflection', { Inflection = TypedDict('Inflection', {
'if': NotRequired[str], 'if': NotRequired[str],
'ifc': NotRequired[str], 'ifc': NotRequired[str],
'il': NotRequired[str], 'il': NotRequired[str],
@@ -244,29 +244,29 @@ def getFirstSound(definition: Any) -> QUrl:
return url return url
return QUrl() return QUrl()
def do_prs(hwi: Any) -> list[Fragment]: def do_prs(prs: list[Pronunciation] | None) -> list[Fragment]:
assert prs is not None
r = Resources() r = Resources()
frags: list[Fragment] = [] frags: list[Fragment] = []
font = r.labelFont font = r.labelFont
linkColor = r.linkColor linkColor = r.linkColor
subduedColor = r.subduedColor subduedColor = r.subduedColor
if 'prs' not in hwi: for pr in prs:
return []
for pr in hwi['prs']:
if 'pun' in pr: if 'pun' in pr:
pun = pr['pun'] pun = pr['pun']
else: else:
pun = ' ' pun = ' '
if 'l' in pr: if 'l' in pr:
frags.append( frags.append(
Fragment(pr['l'] + pun, font, color=subduedColor) Fragment(pr['l'] + pun, r.italicFont, color=subduedColor)
) )
frag = Fragment(pr['mw'], font, color=subduedColor) frag = Fragment(pr['mw'], font, color=subduedColor)
if 'sound' in pr: if 'sound' in pr:
frag.setAudio(soundUrl(pr['sound'])) frag.setAudio(soundUrl(pr['sound']))
frag.setColor(linkColor) frag.setColor(linkColor)
frags.append(frag) frags.append(frag)
frags.append(Fragment(' ', r.phonicFont))
if 'l2' in pr: if 'l2' in pr:
frags.append( frags.append(
Fragment(pun + pr['l2'], font, color=subduedColor) Fragment(pun + pr['l2'], font, color=subduedColor)
@@ -283,33 +283,32 @@ def do_vis(vis: list[VerbalIllustration]|None,indent=0) -> list[Line]:
lines: list[Line] = [] lines: list[Line] = []
for vi in vis: for vi in vis:
line = Line() line = Line()
frag = Fragment(vi['t'], r.textFont, color=r.baseColor) frag = Fragment(vi['t'], r.textFont, color=r.subduedColor)
if indent > 0: if indent > 0:
frag.setIndent(indent) frag.setIndent(indent)
line.addFragment(frag) line.addFragment(frag)
lines.append(line) lines.append(line)
if 'aq' in vi: if 'aq' in vi:
lines += do_aq(trycast(AttributionOfQuote, vi['aq'])) lines += do_aq(trycast(AttributionOfQuote, vi['aq']))
return [] return lines
def do_uns(uns: list[list[list[Pair]]]|None, indent:int) -> list[Line]: def do_uns(uns: list[list[list[Pair]]]|None, indent:int) -> tuple[list[Fragment], list[Line]]:
assert uns is not None assert uns is not None
r = Resources() r = Resources()
lines:list[Line] = [] frags: list[Fragment] = []
lines: list[Line] = []
for note in uns: for note in uns:
for entry in note: for entry in note:
for pair in entry: for pair in entry:
if pair['objType'] == 'text': if pair['objType'] == 'text':
frag = Fragment(' \u2014'+pair['obj'], r.textFont, color=r.baseColor) frag = Fragment('\u2192 '+pair['obj'], r.textFont, color=r.baseColor)
frag.setIndent(indent) frag.setIndent(indent)
line = Line() frags.append(frag)
line.addFragment(frag)
lines.append(line)
elif pair['objType'] == 'vis': elif pair['objType'] == 'vis':
lines += do_vis(trycast(list[VerbalIllustration], pair['obj']), indent) lines += do_vis(trycast(list[VerbalIllustration], pair['obj']), indent)
elif pair['objType'] == 'ri': elif pair['objType'] == 'ri':
raise NotImplementedError("NO ri") raise NotImplementedError("NO ri")
return lines return (frags, lines)
def do_dt(dt: list[list[Pair]]|None, indent: int) -> tuple[list[Fragment], list[Line]]: def do_dt(dt: list[list[Pair]]|None, indent: int) -> tuple[list[Fragment], list[Line]]:
assert dt is not None assert dt is not None
@@ -329,9 +328,10 @@ def do_dt(dt: list[list[Pair]]|None, indent: int) -> tuple[list[Fragment], list[
line.addFragment(frag) line.addFragment(frag)
lines.append(line) lines.append(line)
elif pair['objType'] == 'vis': elif pair['objType'] == 'vis':
lines += do_vis(trycast(list[VerbalIllustration], pair['obj'])) lines += do_vis(trycast(list[VerbalIllustration], pair['obj']),indent)
elif pair['objType'] == 'uns': elif pair['objType'] == 'uns':
newLines = do_uns(trycast(list[list[list[Pair]]], pair['obj']),indent) (newFrags,newLines) = do_uns(trycast(list[list[list[Pair]]], pair['obj']),indent)
frags += newFrags
lines += newLines lines += newLines
else: else:
print(json.dumps(pair, indent=2)) print(json.dumps(pair, indent=2))
@@ -345,13 +345,13 @@ def do_sense(sense: Sense|None, indent:int=3) -> tuple[list[Fragment], list[Line
lines: list[Line] = [] lines: list[Line] = []
frags: list[Fragment] = [] frags: list[Fragment] = []
r = Resources() r = Resources()
dt = sense['dt']
(newFrags, newLines) = do_dt(trycast(list[list[Pair]], dt),indent)
frags += newFrags
lines += newLines
for k,v in sense.items(): for k,v in sense.items():
if k == 'dt' or k == 'sn': if k == 'sn':
continue continue
elif k == 'dt':
(newFrags, newLines) = do_dt(trycast(list[list[Pair]], sense['dt']), indent)
frags += newFrags
lines += newLines
elif k == 'sdsense': elif k == 'sdsense':
# XXX - This needs to expand to handle et, ins, lbs, prs, sgram, sls, vrs # XXX - This needs to expand to handle et, ins, lbs, prs, sgram, sls, vrs
sdsense = trycast(DividedSense, v) sdsense = trycast(DividedSense, v)
@@ -367,50 +367,47 @@ def do_sense(sense: Sense|None, indent:int=3) -> tuple[list[Fragment], list[Line
elif k == 'sls': elif k == 'sls':
labels = trycast(list[str], v) labels = trycast(list[str], v)
assert labels is not None assert labels is not None
frag = Fragment(", ".join(labels)+' ', r.textFont, color=r.subduedColor) frag = Fragment(", ".join(labels)+' ', r.boldFont, color=r.subduedColor)
frag.setIndent(indent)
frag.setBackground(r.subduedBackground)
frags.append(frag) frags.append(frag)
else: else:
print(k,v) print(k,v)
raise NotImplementedError(f"Unknown or unimplimented element {k}") raise NotImplementedError(f"Unknown or unimplimented element {k}")
return (frags, lines) return (frags, lines)
def do_pseq(outer: int, def do_pseq(inner: int,
inner: int, outer: int,
pseq: list[Any] ) -> tuple[list[Fragment], list[Line]]: pseq: list[Any] ) -> tuple[list[Fragment], list[Line]]:
lines: list[Line] = [] lines: list[Line] = []
frags: list[Fragment] = [] frags: list[Fragment] = []
indent = 3 # XXX - Should this be a parameter passed in?
count = 1 count = 1
r = Resources() r = Resources()
first = True newLine = False
for entry in pseq: for entry in pseq:
for pair in entry: for pair in entry:
if pair['objType'] == 'bs': if pair['objType'] == 'bs':
sense = pair['obj']['sense'] sense = pair['obj']['sense']
(newFrags, newLines) = do_sense(trycast(Sense, sense)) (newFrags, newLines) = do_sense(trycast(Sense, sense),indent=indent)
if first: frags += newFrags
frags += newFrags
first = False
else:
line = Line()
line.addFragment(newFrags)
lines.append(line)
lines += newLines lines += newLines
newLine = True
elif pair['objType'] == 'sense': elif pair['objType'] == 'sense':
if first: frag = Fragment(f"({count})", r.textFont, color=r.baseColor)
frag = Fragment(f"({count})", r.textFont, color=r.baseColor) frag.setIndent(indent)
frag.setIndent(3) if newLine:
frags.append(frag)
(newFrags, newLines) = do_sense(trycast(Sense, pair['obj']), indent=4)
frags += newFrags
first = False
else:
line = Line() line = Line()
frag = Fragment(f"({count})", r.textFont, color=r.baseColor)
frag.setIndent(3)
line.addFragment(frag) line.addFragment(frag)
(newFrags, newLines) = do_sense(trycast(Sense, pair['obj']), indent=4) else:
frags.append(frag)
(newFrags, newLines) = do_sense(trycast(Sense, pair['obj']), indent=indent+1)
if newLine:
line.addFragment(newFrags) line.addFragment(newFrags)
lines.append(line) lines.append(line)
else:
frags += newFrags
newLine = True
lines += newLines lines += newLines
count += 1 count += 1
else: else:
@@ -426,14 +423,17 @@ def do_sseq(sseq:list[list[list[Pair]]]) -> list[Line]:
frag.setIndent(1) frag.setIndent(1)
line.addFragment(frag) line.addFragment(frag)
for inner, item_i in enumerate(item_o): for inner, item_i in enumerate(item_o):
frag =Fragment(chr(ord('a')+inner), r.boldFont, color=r.baseColor) indent = 2
frag.setIndent(2) if len(item_o) > 1:
line.addFragment(frag) frag =Fragment(chr(ord('a')+inner), r.boldFont, color=r.baseColor)
frag.setIndent(2)
line.addFragment(frag)
indent = 3
for pair in item_i: for pair in item_i:
objType = pair['objType'] objType = pair['objType']
if objType == 'sense': if objType == 'sense':
sense = trycast(Sense, pair['obj']) sense = trycast(Sense, pair['obj'])
(frags, newlines) = do_sense(sense) (frags, newlines) = do_sense(sense, indent=indent)
line.addFragment(frags) line.addFragment(frags)
lines.append(line) lines.append(line)
line = Line() line = Line()
@@ -448,7 +448,7 @@ def do_sseq(sseq:list[list[list[Pair]]]) -> list[Line]:
lines += newlines lines += newlines
elif objType == 'bs': elif objType == 'bs':
sense = pair['obj']['sense'] sense = pair['obj']['sense']
(newFrags, newLines) = do_sense(trycast(Sense, sense)) (newFrags, newLines) = do_sense(trycast(Sense, sense),indent=indent)
line.addFragment(newFrags) line.addFragment(newFrags)
lines.append(line) lines.append(line)
line = Line() line = Line()
@@ -457,6 +457,60 @@ def do_sseq(sseq:list[list[list[Pair]]]) -> list[Line]:
raise NotImplementedError(f"Unknown object[{objType}] for \n{json.dumps(pair['obj'],indent=2)}") raise NotImplementedError(f"Unknown object[{objType}] for \n{json.dumps(pair['obj'],indent=2)}")
return lines return lines
def do_ins(inflections:list[Inflection]|None) -> list[Fragment]:
assert inflections is not None
r = Resources()
frags: list[Fragment] = []
sep = ''
for inflection in inflections:
if sep == '; ':
frag = Fragment('; ', font=r.boldFont, color=r.baseColor)
frags.append(frag)
elif sep != '':
frag = Fragment(sep, font=r.italicFont, color=r.baseColor)
frags.append(frag)
if 'ifc' in inflection:
text = inflection['ifc']
elif 'if' in inflection:
text = inflection['if']
else:
raise ValueError(f"Missing 'if' or 'ifc' in {inflection}")
frag = Fragment(text, r.boldFont, color=r.baseColor)
frags.append(frag)
sep = '; '
if 'il' in inflection:
sep = ' ' + inflection['il'] + ' '
if 'prs' in inflection:
newFrags = do_prs(trycast(list[Pronunciation], inflection['prs']))
frags += newFrags
if 'spl' in inflection:
raise NotImplementedError(f"We haven't implimented 'spl' for inflection: {inflection}")
return frags
def do_ets(ets:list[list[Pair]]|None) -> list[Line]:
assert ets is not None
r = Resources()
lines: list[Line] = []
for et in ets:
for pair in et:
if pair['objType'] == 'text':
line = Line()
line.addFragment(
Fragment(pair['obj'], r.textFont, color=r.baseColor)
)
lines.append(line)
elif pair['objType'] == 'et_snote':
line = Line()
line.addFragment(
Fragment('Note: '+pair['obj'], r.textFont, color=r.baseColor)
)
lines.append(line)
else:
raise NotImplementedError(f"Unknown key {pair['objType']} in et")
return lines
def do_def(entry: DefinitionSection) -> list[Line]: def do_def(entry: DefinitionSection) -> list[Line]:
assert entry is not None assert entry is not None
r = Resources() r = Resources()
@@ -505,6 +559,8 @@ def getDef(defines: Any) -> list[Line]:
for k in uses.keys(): for k in uses.keys():
used[k] = 0 used[k] = 0
ets: list[Line] = []
for count, work in enumerate(workList): for count, work in enumerate(workList):
testId = work['meta']['id'].lower().split(':')[0] testId = work['meta']['id'].lower().split(':')[0]
# #
@@ -528,8 +584,7 @@ def getDef(defines: Any) -> list[Line]:
line.addFragment(Fragment(', ' + hw, r.headerFont, color=r.baseColor)) line.addFragment(Fragment(', ' + hw, r.headerFont, color=r.baseColor))
if entries > 1: if entries > 1:
frag = Fragment(f" {count + 1} of {entries} ", r.textFont, color= r.subduedColor) frag = Fragment(f" {count + 1} of {entries} ", r.textFont, color= r.subduedColor)
# XXX - Use a resource color!!! frag.setBackground(r.subduedBackground)
frag.setBackground(QColor(Qt.GlobalColor.gray))
line.addFragment(frag) line.addFragment(frag)
if 'fl' in work: if 'fl' in work:
text = work['fl'] text = work['fl']
@@ -547,9 +602,16 @@ def getDef(defines: Any) -> list[Line]:
if hwi['hw'].find('*') >= 0: if hwi['hw'].find('*') >= 0:
hw = re.sub(r'\*', '\u00b7', hwi['hw']) hw = re.sub(r'\*', '\u00b7', hwi['hw'])
line.addFragment(Fragment(hw + ' ', r.textFont, color=r.subduedColor)) line.addFragment(Fragment(hw + ' ', r.textFont, color=r.subduedColor))
for frag in do_prs(hwi): if 'prs' in hwi:
line.addFragment(frag) newFrags = do_prs(trycast(list[Pronunciation], hwi['prs']))
if len(line.getLine()) > 0: line.addFragment(newFrags)
lines.append(line)
line = Line()
if 'ins' in work:
inflections = trycast(list[Inflection], work['ins'])
newFrags = do_ins(inflections)
line = Line()
line.addFragment(newFrags)
lines.append(line) lines.append(line)
defines = trycast(list[DefinitionSection], work['def']) defines = trycast(list[DefinitionSection], work['def'])
assert defines is not None assert defines is not None
@@ -558,6 +620,25 @@ def getDef(defines: Any) -> list[Line]:
lines += do_def(define) lines += do_def(define)
except NotImplementedError as e: except NotImplementedError as e:
print(e) print(e)
if 'et' in work:
line = Line()
line.addFragment(
Fragment(f"{work['fl']} ({used[work['fl']]})", r.labelFont, color=r.baseColor)
)
ets.append(line)
ets += do_ets(trycast(list[list[Pair]], work['et']))
for k in work.keys():
if k not in [ 'meta', 'hom', 'hwi', 'fl', 'def', 'ins', 'prs', 'et',
'date', 'shortdef']:
#raise NotImplementedError(f"Unknown key {k} in work")
print(f"Unknown key {k} in work")
if len(ets)>0:
line = Line()
line.addFragment(
Fragment('Etymology', r.labelFont, color=r.baseColor)
)
lines.append(line)
lines+=ets
return lines return lines
def parseText(frag: Fragment) -> list[Fragment]: def parseText(frag: Fragment) -> list[Fragment]:
@@ -622,10 +703,11 @@ def parseText(frag: Fragment) -> list[Fragment]:
end = text.find("}") end = text.find("}")
token = text[1:end] token = text[1:end]
frag.setText(text[end + 1 :]) frag.setText(text[end + 1 :])
newFrag = Fragment(frag)
oldFont = QFont(frag.font()) oldFont = QFont(frag.font())
if token == "bc": if token == "bc":
results.append(Fragment(": ", boldFont, color=baseColor)) newFrag = Fragment(": ", boldFont, color=baseColor)
newFrag.setIndent(frag.indent())
results.append(newFrag)
continue continue
if token in [ if token in [
"b", "b",