Lint
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# pyright: ignore
|
||||
from .utils import query_error # isort: skip
|
||||
from .books import Book
|
||||
from .definition import Definition, Fragment, Line
|
||||
from .person import PersonDialog
|
||||
from .read import ReadDialog
|
||||
from .session import SessionDialog
|
||||
from .words import DefinitionArea, Word
|
||||
from .definition import Fragment, Line, Definition
|
||||
|
||||
@@ -1,27 +1,40 @@
|
||||
import re
|
||||
from typing import Any, Optional, Self, cast, overload
|
||||
import re
|
||||
from PyQt6.QtCore import QMargins, QPoint, QRect, QSize, QUrl, Qt, pyqtSignal
|
||||
from PyQt6.QtGui import QColor, QFont, QFontMetrics, QMouseEvent, QPaintEvent, QPainter, QResizeEvent, QTextOption, QTransform, QBrush
|
||||
from typing import Any, Callable, Optional, Self, cast, overload
|
||||
|
||||
from PyQt6.QtCore import QMargins, QPoint, QRect, QSize, Qt, QUrl, pyqtSignal
|
||||
from PyQt6.QtGui import (
|
||||
QBrush,
|
||||
QColor,
|
||||
QFont,
|
||||
QFontMetrics,
|
||||
QMouseEvent,
|
||||
QPainter,
|
||||
QPaintEvent,
|
||||
QResizeEvent,
|
||||
QTextOption,
|
||||
QTransform,
|
||||
)
|
||||
from PyQt6.QtWidgets import QWidget
|
||||
|
||||
|
||||
class Fragment:
|
||||
"""A fragment of text to be displayed"""
|
||||
|
||||
_indentAmount = 35
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
which: str|Self,
|
||||
font: QFont|None = None,
|
||||
audio: str = "",
|
||||
color: Optional[QColor] = None,
|
||||
asis: bool = False,
|
||||
self,
|
||||
which: str | Self,
|
||||
font: QFont | None = None,
|
||||
audio: str = "",
|
||||
color: Optional[QColor] = None,
|
||||
asis: bool = False,
|
||||
) -> None:
|
||||
if isinstance(which, Fragment):
|
||||
for k,v in which.__dict__.items():
|
||||
for k, v in which.__dict__.items():
|
||||
self.__dict__[k] = v
|
||||
return
|
||||
self._text:str = which
|
||||
self._text: str = which
|
||||
if font is None:
|
||||
raise TypeError("Missing required parameter 'font'")
|
||||
self._font = font
|
||||
@@ -63,13 +76,14 @@ class Fragment:
|
||||
return f"({self._position.x()}, {self._position.y()}): {self._text}"
|
||||
|
||||
@overload
|
||||
def paintEvent(self, widthSrc:int) -> QSize:
|
||||
def paintEvent(self, widthSrc: int) -> QSize:
|
||||
...
|
||||
|
||||
@overload
|
||||
def paintEvent(self, widthSrc: QPainter) -> int:
|
||||
...
|
||||
|
||||
def paintEvent(self, widthSrc) -> int|QSize:
|
||||
def paintEvent(self, widthSrc: QPainter | int) -> int | QSize:
|
||||
if isinstance(widthSrc, QPainter):
|
||||
viewportWidth = widthSrc.viewport().width()
|
||||
painter = widthSrc
|
||||
@@ -77,28 +91,21 @@ class Fragment:
|
||||
viewportWidth = widthSrc
|
||||
painter = None
|
||||
fm = QFontMetrics(self._font)
|
||||
top = (
|
||||
self._position.y()
|
||||
+ fm.descent()
|
||||
- fm.height()
|
||||
)
|
||||
top = self._position.y() + fm.descent() - fm.height()
|
||||
left = self._position.x()
|
||||
width = viewportWidth - left
|
||||
height = 2000
|
||||
rect = QRect(left, top, width, height)
|
||||
indent = self._indent * self._indentAmount
|
||||
flags = (
|
||||
Qt.AlignmentFlag.AlignLeft
|
||||
| Qt.AlignmentFlag.AlignBaseline
|
||||
)
|
||||
flags = Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignBaseline
|
||||
boundingNoWrap = fm.boundingRect(
|
||||
rect, flags|Qt.TextFlag.TextSingleLine, self._text
|
||||
rect, flags | Qt.TextFlag.TextSingleLine, self._text
|
||||
)
|
||||
bounding = fm.boundingRect(
|
||||
rect, flags|Qt.TextFlag.TextWordWrap, self._text
|
||||
rect, flags | Qt.TextFlag.TextWordWrap, self._text
|
||||
)
|
||||
text = self._text
|
||||
remainingText = ''
|
||||
remainingText = ""
|
||||
if boundingNoWrap.height() < bounding.height():
|
||||
#
|
||||
# This is not optimal, but it is only a few iterations
|
||||
@@ -107,39 +114,29 @@ class Fragment:
|
||||
char = 0
|
||||
pos = rect.x()
|
||||
while pos < rect.right():
|
||||
if text[char] == ' ':
|
||||
if text[char] == " ":
|
||||
lastSpace = char
|
||||
pos += fm.horizontalAdvance(
|
||||
text[char]
|
||||
)
|
||||
pos += fm.horizontalAdvance(text[char])
|
||||
char += 1
|
||||
if lastSpace > 0:
|
||||
remainingText = text[lastSpace+1:]
|
||||
remainingText = text[lastSpace + 1 :]
|
||||
text = text[:lastSpace]
|
||||
|
||||
size = boundingNoWrap.size()
|
||||
|
||||
boundingNoWrap = fm.boundingRect(
|
||||
rect, flags|Qt.TextFlag.TextSingleLine, text
|
||||
rect, flags | Qt.TextFlag.TextSingleLine, text
|
||||
)
|
||||
rect.setSize(boundingNoWrap.size())
|
||||
|
||||
|
||||
if remainingText != '':
|
||||
if remainingText != "":
|
||||
top += size.height()
|
||||
remainingRect = QRect(
|
||||
indent, top,
|
||||
viewportWidth - indent, height
|
||||
)
|
||||
remainingRect = QRect(indent, top, viewportWidth - indent, height)
|
||||
boundingRemaingRect = fm.boundingRect(
|
||||
remainingRect, flags | Qt.TextFlag.TextWordWrap, remainingText
|
||||
)
|
||||
|
||||
size = size.grownBy(
|
||||
QMargins(
|
||||
0,0,0, boundingRemaingRect.height()
|
||||
)
|
||||
)
|
||||
size = size.grownBy(QMargins(0, 0, 0, boundingRemaingRect.height()))
|
||||
remainingRect.setSize(boundingRemaingRect.size())
|
||||
size = size.grownBy(self._margin)
|
||||
size = size.grownBy(self._border)
|
||||
@@ -163,12 +160,14 @@ class Fragment:
|
||||
brush.setColor(self._background)
|
||||
brush.setStyle(Qt.BrushStyle.SolidPattern)
|
||||
painter.setBrush(brush)
|
||||
painter.fillRect(rect,brush)
|
||||
painter.fillRect(rect, brush)
|
||||
painter.drawText(rect, flags, text)
|
||||
if remainingText:
|
||||
if self._background.isValid():
|
||||
painter.fillRect(remainingRect, brush)
|
||||
painter.drawText(remainingRect, flags|Qt.TextFlag.TextWordWrap, remainingText)
|
||||
painter.drawText(
|
||||
remainingRect, flags | Qt.TextFlag.TextWordWrap, remainingText
|
||||
)
|
||||
painter.restore()
|
||||
return size.height()
|
||||
|
||||
@@ -310,6 +309,7 @@ class Fragment:
|
||||
def setBackground(self, color: QColor) -> None:
|
||||
self._background = color
|
||||
return
|
||||
|
||||
def setIndent(self, indent: int) -> None:
|
||||
self._indent = indent
|
||||
return
|
||||
@@ -365,8 +365,10 @@ class Fragment:
|
||||
def pixelIndent(self) -> int:
|
||||
return self._indent * self._indentAmount
|
||||
|
||||
|
||||
class Line:
|
||||
parseText = None
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._maxHeight = -1
|
||||
self._baseLine = -1
|
||||
@@ -379,11 +381,12 @@ class Line:
|
||||
"|".join([x.text() for x in self._fragments])
|
||||
+ f"|{self._maxHeight}"
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def setParseText(cls, call) -> None:
|
||||
def setParseText(cls, call: Callable) -> None:
|
||||
cls.parseText = call
|
||||
return
|
||||
|
||||
|
||||
def paintEvent(self, painter: QPainter) -> int:
|
||||
#
|
||||
# we do not have an event field because we are not a true widget
|
||||
@@ -395,12 +398,16 @@ class Line:
|
||||
lineSpacing = ls
|
||||
return lineSpacing
|
||||
|
||||
|
||||
def addFragment(self, frags: Fragment|list[Fragment],) -> None:
|
||||
def addFragment(
|
||||
self,
|
||||
frags: Fragment | list[Fragment],
|
||||
) -> None:
|
||||
SPEAKER = "\U0001F508"
|
||||
|
||||
if not isinstance(frags, list):
|
||||
frags = [frags, ]
|
||||
frags = [
|
||||
frags,
|
||||
]
|
||||
for frag in frags:
|
||||
if frag.audio().isValid():
|
||||
frag.setText(frag.text() + " " + SPEAKER)
|
||||
@@ -485,6 +492,7 @@ class Line:
|
||||
def getLineSpacing(self) -> int:
|
||||
return self._leading + self._maxHeight
|
||||
|
||||
|
||||
class Definition(QWidget):
|
||||
pronounce = pyqtSignal(str)
|
||||
|
||||
@@ -499,7 +507,7 @@ class Definition(QWidget):
|
||||
|
||||
def setWord(self, word: Any) -> None:
|
||||
self._word = word
|
||||
lines:list[Line] = word.get_def()
|
||||
lines: list[Line] = word.get_def()
|
||||
assert lines is not None
|
||||
self._lines = lines
|
||||
self._buttons: list[Fragment] = []
|
||||
|
||||
@@ -101,7 +101,7 @@ class SoundOff(QObject):
|
||||
|
||||
@pyqtSlot(QMediaPlayer.MediaStatus)
|
||||
def mediaStatus(self, status: QMediaPlayer.MediaStatus) -> None:
|
||||
#print(f"mediaStatus: {status}")
|
||||
# print(f"mediaStatus: {status}")
|
||||
if status == QMediaPlayer.MediaStatus.LoadedMedia:
|
||||
player: Optional[QMediaPlayer] = cast(QMediaPlayer, self.sender())
|
||||
assert player is not None
|
||||
@@ -110,7 +110,7 @@ class SoundOff(QObject):
|
||||
|
||||
@pyqtSlot(QMediaPlayer.PlaybackState)
|
||||
def playbackState(self, state: QMediaPlayer.PlaybackState) -> None:
|
||||
#print(f"playbackState: {state}")
|
||||
# print(f"playbackState: {state}")
|
||||
return
|
||||
|
||||
#
|
||||
@@ -164,7 +164,7 @@ class SoundOff(QObject):
|
||||
continue
|
||||
self._storage[player] = QByteArray(storage)
|
||||
crypto.addData(self._storage[player])
|
||||
#print(player, crypto.result().toHex())
|
||||
# print(player, crypto.result().toHex())
|
||||
crypto.reset()
|
||||
self._buffer[player] = QBuffer(self._storage[player])
|
||||
url = reply.request().url()
|
||||
@@ -172,5 +172,5 @@ class SoundOff(QObject):
|
||||
player.setPosition(0)
|
||||
if player.mediaStatus() == QMediaPlayer.MediaStatus.LoadedMedia:
|
||||
player.play()
|
||||
#print("play")
|
||||
# print("play")
|
||||
return
|
||||
|
||||
@@ -22,6 +22,7 @@ def query_error(query: QSqlQuery) -> NoReturn:
|
||||
)
|
||||
raise Exception(translate("MainWindow", "SQL Error"))
|
||||
|
||||
|
||||
class Resources:
|
||||
_instance = None
|
||||
nam = QNetworkAccessManager()
|
||||
@@ -39,7 +40,7 @@ class Resources:
|
||||
subduedColor: QColor
|
||||
|
||||
subduedBackground: QColor
|
||||
|
||||
|
||||
def __new__(cls: type[Self]) -> Self:
|
||||
if cls._instance:
|
||||
return cls._instance
|
||||
|
||||
54
lib/words.py
54
lib/words.py
@@ -1,40 +1,46 @@
|
||||
import importlib
|
||||
import pkgutil
|
||||
import json
|
||||
from typing import Any, TypedDict, cast
|
||||
import pkgutil
|
||||
from types import ModuleType
|
||||
from typing import Any, Iterable, TypedDict, cast
|
||||
|
||||
from PyQt6.QtCore import (
|
||||
Qt,
|
||||
pyqtSlot,
|
||||
)
|
||||
from PyQt6.QtCore import Qt, pyqtSlot
|
||||
from PyQt6.QtSql import QSqlQuery
|
||||
from PyQt6.QtWidgets import QScrollArea
|
||||
|
||||
from lib.utils import query_error
|
||||
from lib.sounds import SoundOff
|
||||
from lib.definition import Definition, Line
|
||||
from trycast import trycast
|
||||
|
||||
import plugins
|
||||
def find_plugins(ns_pkg):
|
||||
return pkgutil.iter_modules(ns_pkg.__path__, ns_pkg.__name__ + '.')
|
||||
from lib.definition import Definition, Line
|
||||
from lib.sounds import SoundOff
|
||||
from lib.utils import query_error
|
||||
|
||||
|
||||
def find_plugins(ns_pkg: ModuleType) -> Iterable[pkgutil.ModuleInfo]:
|
||||
return pkgutil.iter_modules(ns_pkg.__path__, ns_pkg.__name__ + ".")
|
||||
|
||||
|
||||
discovered_plugins = {
|
||||
# finder, name, ispkg
|
||||
importlib.import_module(name).registration['source']: importlib.import_module(name) for _, name, _ in find_plugins(plugins)
|
||||
importlib.import_module(name).registration[
|
||||
"source"
|
||||
]: importlib.import_module(name)
|
||||
for _, name, _ in find_plugins(plugins)
|
||||
}
|
||||
|
||||
API = "https://api.dictionaryapi.dev/api/v2/entries/en/{word}"
|
||||
|
||||
|
||||
class WordType(TypedDict):
|
||||
word: str
|
||||
source: str
|
||||
definition: str
|
||||
|
||||
|
||||
|
||||
class Word:
|
||||
"""All processing of a dictionary word."""
|
||||
|
||||
_words: dict[str, WordType] = {}
|
||||
|
||||
|
||||
def __init__(self, word: str) -> None:
|
||||
#
|
||||
# Have we already retrieved this word?
|
||||
@@ -79,30 +85,38 @@ class Word:
|
||||
|
||||
@pyqtSlot()
|
||||
def playSound(self) -> None:
|
||||
url = discovered_plugins[self.current['source']].getFirstSound(self.current['definition'])
|
||||
url = discovered_plugins[self.current["source"]].getFirstSound(
|
||||
self.current["definition"]
|
||||
)
|
||||
if url.isValid():
|
||||
snd = SoundOff()
|
||||
snd.playSound(url)
|
||||
return
|
||||
|
||||
def playPRS(self) -> None:
|
||||
return
|
||||
|
||||
def getWord(self) -> str:
|
||||
return cast(str, self.current["word"])
|
||||
return self.current["word"]
|
||||
|
||||
def get_html(self) -> str | None:
|
||||
src = self.current['source']
|
||||
src = self.current["source"]
|
||||
try:
|
||||
return discovered_plugins[src].getHtml(self.current)
|
||||
return cast(str, discovered_plugins[src].getHtml(self.current))
|
||||
except KeyError:
|
||||
raise Exception(f"Unknown source: {src}")
|
||||
|
||||
def get_def(self) -> list[Line]:
|
||||
src = self.current['source']
|
||||
src = self.current["source"]
|
||||
try:
|
||||
lines = discovered_plugins[src].getDef(self.current["definition"])
|
||||
lines = trycast(list[Line], lines)
|
||||
assert lines is not None
|
||||
return lines
|
||||
except KeyError:
|
||||
raise Exception(f"Unknown source: {self.current['source']}")
|
||||
|
||||
|
||||
class DefinitionArea(QScrollArea):
|
||||
def __init__(self, w: Word, *args: Any, **kwargs: Any) -> None:
|
||||
super(DefinitionArea, self).__init__(*args, *kwargs)
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
from PyQt6.QtGui import QColor, QFont
|
||||
from trycast import trycast
|
||||
import json
|
||||
import re
|
||||
from typing import Any, Literal, NotRequired, TypedDict, cast
|
||||
|
||||
from PyQt6.QtCore import QEventLoop, QUrl, Qt
|
||||
from PyQt6.QtCore import QEventLoop, Qt, QUrl
|
||||
from PyQt6.QtGui import QColor, QFont
|
||||
from PyQt6.QtNetwork import QNetworkRequest
|
||||
from trycast import trycast
|
||||
|
||||
from lib.definition import Fragment, Line
|
||||
from lib.utils import Resources
|
||||
from lib.definition import Line, Fragment
|
||||
|
||||
registration = {
|
||||
'source': 'mw',
|
||||
'name': 'Merriam-Webster',
|
||||
'language': 'en-us',
|
||||
"source": "mw",
|
||||
"name": "Merriam-Webster",
|
||||
"language": "en-us",
|
||||
}
|
||||
|
||||
API = "https://www.dictionaryapi.com/api/v3/references/collegiate/json/{word}?key={key}"
|
||||
key = "51d9df34-ee13-489e-8656-478c215e846c"
|
||||
|
||||
|
||||
class Meta(TypedDict):
|
||||
id: str
|
||||
uuid: str
|
||||
@@ -27,11 +29,13 @@ class Meta(TypedDict):
|
||||
stems: list[str]
|
||||
offensive: bool
|
||||
|
||||
|
||||
class Sound(TypedDict):
|
||||
audio: str
|
||||
ref: str
|
||||
stat: str
|
||||
|
||||
|
||||
class Pronunciation(TypedDict):
|
||||
mw: str
|
||||
l: NotRequired[str]
|
||||
@@ -39,41 +43,52 @@ class Pronunciation(TypedDict):
|
||||
pun: NotRequired[str]
|
||||
sound: NotRequired[Sound]
|
||||
|
||||
|
||||
class SubSource(TypedDict):
|
||||
source: NotRequired[str]
|
||||
aqdate: NotRequired[str]
|
||||
|
||||
|
||||
class AttributionOfQuote(TypedDict):
|
||||
auth: NotRequired[str]
|
||||
source: NotRequired[str]
|
||||
aqdate: NotRequired[str]
|
||||
subsource: NotRequired[SubSource]
|
||||
|
||||
|
||||
class VerbalIllustration(TypedDict):
|
||||
t: str
|
||||
aq: NotRequired[AttributionOfQuote]
|
||||
|
||||
|
||||
class HeadWordInformation(TypedDict):
|
||||
hw: str
|
||||
prs: NotRequired[list[Pronunciation]]
|
||||
|
||||
|
||||
class AlternanteHeadword(TypedDict):
|
||||
hw: str
|
||||
psl: NotRequired[str]
|
||||
|
||||
|
||||
class Variant(TypedDict):
|
||||
va: str
|
||||
vl: NotRequired[str]
|
||||
prs: NotRequired[list[Pronunciation]]
|
||||
spl: NotRequired[str]
|
||||
|
||||
Inflection = TypedDict('Inflection', {
|
||||
'if': NotRequired[str],
|
||||
'ifc': NotRequired[str],
|
||||
'il': NotRequired[str],
|
||||
'prs': NotRequired[list[Pronunciation]],
|
||||
'spl': NotRequired[str]
|
||||
})
|
||||
|
||||
Inflection = TypedDict(
|
||||
"Inflection",
|
||||
{
|
||||
"if": NotRequired[str],
|
||||
"ifc": NotRequired[str],
|
||||
"il": NotRequired[str],
|
||||
"prs": NotRequired[list[Pronunciation]],
|
||||
"spl": NotRequired[str],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class CrossReferenceTarget(TypedDict):
|
||||
cxl: str
|
||||
@@ -81,14 +96,17 @@ class CrossReferenceTarget(TypedDict):
|
||||
cxt: str
|
||||
cxn: NotRequired[str]
|
||||
|
||||
|
||||
class CognateCrossRef(TypedDict):
|
||||
cxl: str
|
||||
cxtis: list[CrossReferenceTarget]
|
||||
|
||||
|
||||
class Pair(TypedDict):
|
||||
objType: str
|
||||
obj: Any
|
||||
|
||||
|
||||
class DividedSense(TypedDict):
|
||||
sd: str
|
||||
dt: list[list[Pair]]
|
||||
@@ -100,6 +118,7 @@ class DividedSense(TypedDict):
|
||||
sls: NotRequired[list[str]]
|
||||
vrs: NotRequired[list[Variant]]
|
||||
|
||||
|
||||
class Sense(TypedDict):
|
||||
dt: list[list[Pair]]
|
||||
et: NotRequired[list[Pair]]
|
||||
@@ -112,55 +131,89 @@ class Sense(TypedDict):
|
||||
sn: NotRequired[str]
|
||||
vrs: NotRequired[list[Variant]]
|
||||
|
||||
class TruncatedSense(Sense): pass
|
||||
|
||||
class TruncatedSense(Sense):
|
||||
pass
|
||||
|
||||
|
||||
class BindingSubstitutePair(TypedDict):
|
||||
objType: Literal['bs']
|
||||
objType: Literal["bs"]
|
||||
obj: Sense
|
||||
|
||||
|
||||
class SensePair(TypedDict):
|
||||
objType: Literal['sense']
|
||||
objType: Literal["sense"]
|
||||
obj: Sense
|
||||
|
||||
|
||||
class DefinitionSection(TypedDict):
|
||||
vd: NotRequired[str]
|
||||
sls: NotRequired[list[str]]
|
||||
sseq: Any # list[list[Pair]]
|
||||
|
||||
Definition =TypedDict('Definition', {
|
||||
'meta': Meta,
|
||||
'hom': NotRequired[int],
|
||||
'hwi': HeadWordInformation,
|
||||
'ahws': NotRequired[list[AlternanteHeadword]],
|
||||
'vrs': NotRequired[list[Variant]],
|
||||
'fl': str,
|
||||
'lbs': NotRequired[list[str]],
|
||||
'sls': NotRequired[list[str]],
|
||||
'ins': NotRequired[list[Inflection]],
|
||||
'cxs': NotRequired[list[CognateCrossRef]],
|
||||
'def': list[DefinitionSection],
|
||||
})
|
||||
sseq: Any # list[list[Pair]]
|
||||
|
||||
|
||||
Definition = TypedDict(
|
||||
"Definition",
|
||||
{
|
||||
"ahws": NotRequired[list[AlternanteHeadword]],
|
||||
"cxs": NotRequired[list[CognateCrossRef]],
|
||||
"date": NotRequired[str],
|
||||
"def": list[DefinitionSection],
|
||||
"dros": NotRequired[Any],
|
||||
"et": NotRequired[list[Pair]],
|
||||
"fl": str,
|
||||
"hom": NotRequired[int],
|
||||
"hwi": HeadWordInformation,
|
||||
"ins": NotRequired[list[Inflection]],
|
||||
"lbs": NotRequired[list[str]],
|
||||
"meta": Meta,
|
||||
"shortdef": NotRequired[list[str]],
|
||||
"sls": NotRequired[list[str]],
|
||||
"syns": NotRequired[Any],
|
||||
"uros": NotRequired[Any],
|
||||
"vrs": NotRequired[list[Variant]],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def make_pairs(src: list[Any]) -> list[Pair]:
|
||||
result:list[Pair] = []
|
||||
iters = [iter(src)]*2
|
||||
result: list[Pair] = []
|
||||
iters = [iter(src)] * 2
|
||||
for entry in zip(*iters):
|
||||
pair0 = { 'objType': entry[0],
|
||||
'obj': entry[1],
|
||||
}
|
||||
if isinstance(pair0['obj'], list):
|
||||
result.append(cast(Pair,pair0))
|
||||
pair0 = {
|
||||
"objType": entry[0],
|
||||
"obj": entry[1],
|
||||
}
|
||||
if isinstance(pair0["obj"], list):
|
||||
result.append(cast(Pair, pair0))
|
||||
continue
|
||||
pair1 = trycast(Pair, pair0)
|
||||
if pair1 is None:
|
||||
print(pair0['objType'], type(pair0['obj']),
|
||||
json.dumps(pair0['obj'],indent=2)
|
||||
)
|
||||
print(
|
||||
pair0["objType"],
|
||||
type(pair0["obj"]),
|
||||
json.dumps(pair0["obj"], indent=2),
|
||||
)
|
||||
assert pair1 is not None
|
||||
result.append(pair1)
|
||||
return result
|
||||
|
||||
Elements = [ 'dt', 'sen', 'bs', 'pseq', 'snot', 't', 'text', 'vis', 'sens', 'uns', 'sense' ]
|
||||
|
||||
Elements = [
|
||||
"dt",
|
||||
"sen",
|
||||
"bs",
|
||||
"pseq",
|
||||
"snot",
|
||||
"t",
|
||||
"text",
|
||||
"vis",
|
||||
"sens",
|
||||
"uns",
|
||||
"sense",
|
||||
]
|
||||
|
||||
|
||||
def restructure(obj: Any) -> Any:
|
||||
if isinstance(obj, list):
|
||||
if len(obj) == 0:
|
||||
@@ -169,16 +222,16 @@ def restructure(obj: Any) -> Any:
|
||||
pairs = make_pairs(obj)
|
||||
result = []
|
||||
for pair in pairs:
|
||||
if isinstance(pair['obj'], list):
|
||||
if isinstance(pair["obj"], list):
|
||||
r2 = []
|
||||
for item in pair['obj']:
|
||||
for item in pair["obj"]:
|
||||
r2.append(restructure(item))
|
||||
pair['obj'] = r2
|
||||
elif isinstance(pair['obj'], dict):
|
||||
pair["obj"] = r2
|
||||
elif isinstance(pair["obj"], dict):
|
||||
r2 = {}
|
||||
for k,v in pair['obj'].items():
|
||||
for k, v in pair["obj"].items():
|
||||
r2[k] = restructure(v)
|
||||
pair['obj'] = r2
|
||||
pair["obj"] = r2
|
||||
result.append(pair)
|
||||
return result
|
||||
result = []
|
||||
@@ -188,18 +241,20 @@ def restructure(obj: Any) -> Any:
|
||||
elif isinstance(obj, dict):
|
||||
obj2 = cast(dict, obj)
|
||||
result = {}
|
||||
for k,v in obj2.items():
|
||||
for k, v in obj2.items():
|
||||
result[k] = restructure(v)
|
||||
return result
|
||||
else:
|
||||
return obj
|
||||
|
||||
|
||||
class WordType(TypedDict):
|
||||
word: str
|
||||
source: str
|
||||
definition: Any
|
||||
|
||||
def fetch(word:str) -> WordType:
|
||||
|
||||
def fetch(word: str) -> WordType:
|
||||
request = QNetworkRequest()
|
||||
url = QUrl(API.format(word=word, key=key))
|
||||
request.setUrl(url)
|
||||
@@ -210,17 +265,18 @@ def fetch(word:str) -> WordType:
|
||||
reply.finished.connect(loop.quit)
|
||||
loop.exec()
|
||||
content = reply.readAll()
|
||||
data = json.loads(content.data().decode('utf-8'))
|
||||
data = json.loads(content.data().decode("utf-8"))
|
||||
return {
|
||||
'word': word,
|
||||
'source': 'mw',
|
||||
'definition': data,
|
||||
"word": word,
|
||||
"source": "mw",
|
||||
"definition": data,
|
||||
}
|
||||
|
||||
def soundUrl(sound:Sound, fmt='ogg') -> QUrl:
|
||||
|
||||
def soundUrl(sound: Sound, fmt="ogg") -> QUrl:
|
||||
"""Create a URL from a PRS structure."""
|
||||
base = f"https://media.merriam-webster.com/audio/prons/en/us/{fmt}"
|
||||
audio = sound['audio']
|
||||
audio = sound["audio"]
|
||||
m = re.match(r"(bix|gg|[a-zA-Z])", audio)
|
||||
if m:
|
||||
url = base + f"/{m.group(1)}/"
|
||||
@@ -229,21 +285,23 @@ def soundUrl(sound:Sound, fmt='ogg') -> QUrl:
|
||||
url += audio + f".{fmt}"
|
||||
return QUrl(url)
|
||||
|
||||
|
||||
def getFirstSound(definition: Any) -> QUrl:
|
||||
# ahws, cats, dros, hwi, ins, ri, sdsense, sen, sense, uros, vrs
|
||||
for entry in definition:
|
||||
for v in entry.values():
|
||||
hwi = v # trycast
|
||||
hwi = v # trycast
|
||||
if hwi is None:
|
||||
continue
|
||||
if 'prs' in hwi:
|
||||
for pr in hwi['prs']:
|
||||
if 'sound' in pr:
|
||||
url = soundUrl(pr['sound'])
|
||||
if "prs" in hwi:
|
||||
for pr in hwi["prs"]:
|
||||
if "sound" in pr:
|
||||
url = soundUrl(pr["sound"])
|
||||
if url.isValid():
|
||||
return url
|
||||
return QUrl()
|
||||
|
||||
|
||||
def do_prs(prs: list[Pronunciation] | None) -> list[Fragment]:
|
||||
assert prs is not None
|
||||
r = Resources()
|
||||
@@ -253,46 +311,49 @@ def do_prs(prs: list[Pronunciation] | None) -> list[Fragment]:
|
||||
subduedColor = r.subduedColor
|
||||
|
||||
for pr in prs:
|
||||
if 'pun' in pr:
|
||||
pun = pr['pun']
|
||||
if "pun" in pr:
|
||||
pun = pr["pun"]
|
||||
else:
|
||||
pun = ' '
|
||||
if 'l' in pr:
|
||||
pun = " "
|
||||
if "l" in pr:
|
||||
frags.append(
|
||||
Fragment(pr['l'] + pun, r.italicFont, color=subduedColor)
|
||||
Fragment(pr["l"] + pun, r.italicFont, color=subduedColor)
|
||||
)
|
||||
frag = Fragment(pr['mw'], font, color=subduedColor)
|
||||
if 'sound' in pr:
|
||||
frag.setAudio(soundUrl(pr['sound']))
|
||||
frag = Fragment(pr["mw"], font, color=subduedColor)
|
||||
if "sound" in pr:
|
||||
frag.setAudio(soundUrl(pr["sound"]))
|
||||
frag.setColor(linkColor)
|
||||
frags.append(frag)
|
||||
frags.append(Fragment(' ', r.phonicFont))
|
||||
if 'l2' in pr:
|
||||
frags.append(
|
||||
Fragment(pun + pr['l2'], font, color=subduedColor)
|
||||
)
|
||||
frags.append(Fragment(" ", r.phonicFont))
|
||||
if "l2" in pr:
|
||||
frags.append(Fragment(pun + pr["l2"], font, color=subduedColor))
|
||||
return frags
|
||||
|
||||
def do_aq(aq: AttributionOfQuote|None) -> list[Line]:
|
||||
|
||||
def do_aq(aq: AttributionOfQuote | None) -> list[Line]:
|
||||
assert aq is not None
|
||||
return []
|
||||
|
||||
def do_vis(vis: list[VerbalIllustration]|None,indent=0) -> list[Line]:
|
||||
|
||||
def do_vis(vis: list[VerbalIllustration] | None, indent=0) -> list[Line]:
|
||||
assert vis is not None
|
||||
r = Resources()
|
||||
lines: list[Line] = []
|
||||
for vi in vis:
|
||||
line = Line()
|
||||
frag = Fragment(vi['t'], r.textFont, color=r.subduedColor)
|
||||
frag = Fragment(vi["t"], r.textFont, color=r.subduedColor)
|
||||
if indent > 0:
|
||||
frag.setIndent(indent)
|
||||
line.addFragment(frag)
|
||||
lines.append(line)
|
||||
if 'aq' in vi:
|
||||
lines += do_aq(trycast(AttributionOfQuote, vi['aq']))
|
||||
if "aq" in vi:
|
||||
lines += do_aq(trycast(AttributionOfQuote, vi["aq"]))
|
||||
return lines
|
||||
|
||||
def do_uns(uns: list[list[list[Pair]]]|None, indent:int) -> tuple[list[Fragment], list[Line]]:
|
||||
|
||||
def do_uns(
|
||||
uns: list[list[list[Pair]]] | None, indent: int
|
||||
) -> tuple[list[Fragment], list[Line]]:
|
||||
assert uns is not None
|
||||
r = Resources()
|
||||
frags: list[Fragment] = []
|
||||
@@ -300,17 +361,24 @@ def do_uns(uns: list[list[list[Pair]]]|None, indent:int) -> tuple[list[Fragment]
|
||||
for note in uns:
|
||||
for entry in note:
|
||||
for pair in entry:
|
||||
if pair['objType'] == 'text':
|
||||
frag = Fragment('\u2192 '+pair['obj'], r.textFont, color=r.baseColor)
|
||||
if pair["objType"] == "text":
|
||||
frag = Fragment(
|
||||
"\u2192 " + pair["obj"], r.textFont, color=r.baseColor
|
||||
)
|
||||
frag.setIndent(indent)
|
||||
frags.append(frag)
|
||||
elif pair['objType'] == 'vis':
|
||||
lines += do_vis(trycast(list[VerbalIllustration], pair['obj']), indent)
|
||||
elif pair['objType'] == 'ri':
|
||||
elif pair["objType"] == "vis":
|
||||
lines += do_vis(
|
||||
trycast(list[VerbalIllustration], pair["obj"]), indent
|
||||
)
|
||||
elif pair["objType"] == "ri":
|
||||
raise NotImplementedError("NO ri")
|
||||
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
|
||||
frags: list[Fragment] = []
|
||||
lines: list[Line] = []
|
||||
@@ -318,8 +386,8 @@ def do_dt(dt: list[list[Pair]]|None, indent: int) -> tuple[list[Fragment], list[
|
||||
first = True
|
||||
for entry in dt:
|
||||
for pair in entry:
|
||||
if pair['objType'] == 'text':
|
||||
frag = Fragment(pair['obj'], r.textFont, color=r.baseColor)
|
||||
if pair["objType"] == "text":
|
||||
frag = Fragment(pair["obj"], r.textFont, color=r.baseColor)
|
||||
frag.setIndent(indent)
|
||||
if first:
|
||||
frags.append(frag)
|
||||
@@ -327,73 +395,93 @@ def do_dt(dt: list[list[Pair]]|None, indent: int) -> tuple[list[Fragment], list[
|
||||
line = Line()
|
||||
line.addFragment(frag)
|
||||
lines.append(line)
|
||||
elif pair['objType'] == 'vis':
|
||||
lines += do_vis(trycast(list[VerbalIllustration], pair['obj']),indent)
|
||||
elif pair['objType'] == 'uns':
|
||||
(newFrags,newLines) = do_uns(trycast(list[list[list[Pair]]], pair['obj']),indent)
|
||||
elif pair["objType"] == "vis":
|
||||
lines += do_vis(
|
||||
trycast(list[VerbalIllustration], pair["obj"]), indent
|
||||
)
|
||||
elif pair["objType"] == "uns":
|
||||
(newFrags, newLines) = do_uns(
|
||||
trycast(list[list[list[Pair]]], pair["obj"]), indent
|
||||
)
|
||||
frags += newFrags
|
||||
lines += newLines
|
||||
else:
|
||||
print(json.dumps(pair, indent=2))
|
||||
raise NotImplementedError(f"Unknown or unimplimented element {pair['objType']}")
|
||||
raise NotImplementedError(
|
||||
f"Unknown or unimplimented element {pair['objType']}"
|
||||
)
|
||||
first = False
|
||||
return (frags, lines)
|
||||
|
||||
def do_sense(sense: Sense|None, indent:int=3) -> tuple[list[Fragment], list[Line]]:
|
||||
|
||||
def do_sense(
|
||||
sense: Sense | None, indent: int = 3
|
||||
) -> tuple[list[Fragment], list[Line]]:
|
||||
if sense is None:
|
||||
return ([],[])
|
||||
return ([], [])
|
||||
lines: list[Line] = []
|
||||
frags: list[Fragment] = []
|
||||
r = Resources()
|
||||
for k,v in sense.items():
|
||||
if k == 'sn':
|
||||
for k, v in sense.items():
|
||||
if k == "sn":
|
||||
continue
|
||||
elif k == 'dt':
|
||||
(newFrags, newLines) = do_dt(trycast(list[list[Pair]], sense['dt']), indent)
|
||||
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
|
||||
sdsense = trycast(DividedSense, v)
|
||||
assert sdsense is not None
|
||||
frag = Fragment(sdsense['sd']+' ', r.italicFont, color=r.baseColor)
|
||||
frag = Fragment(
|
||||
sdsense["sd"] + " ", r.italicFont, color=r.baseColor
|
||||
)
|
||||
frag.setIndent(indent)
|
||||
line = Line()
|
||||
line.addFragment(frag)
|
||||
(newFrags, newLines) = do_dt(trycast(list[list[Pair]], sdsense['dt']), indent=indent)
|
||||
(newFrags, newLines) = do_dt(
|
||||
trycast(list[list[Pair]], sdsense["dt"]), indent=indent
|
||||
)
|
||||
line.addFragment(newFrags)
|
||||
lines.append(line)
|
||||
lines += newLines
|
||||
elif k == 'sls':
|
||||
elif k == "sls":
|
||||
labels = trycast(list[str], v)
|
||||
assert labels is not None
|
||||
frag = Fragment(", ".join(labels)+' ', r.boldFont, color=r.subduedColor)
|
||||
frag = Fragment(
|
||||
", ".join(labels) + " ", r.boldFont, color=r.subduedColor
|
||||
)
|
||||
frag.setIndent(indent)
|
||||
frag.setBackground(r.subduedBackground)
|
||||
frags.append(frag)
|
||||
else:
|
||||
print(k,v)
|
||||
print(k, v)
|
||||
raise NotImplementedError(f"Unknown or unimplimented element {k}")
|
||||
return (frags, lines)
|
||||
|
||||
def do_pseq(inner: int,
|
||||
outer: int,
|
||||
pseq: list[Any] ) -> tuple[list[Fragment], list[Line]]:
|
||||
|
||||
def do_pseq(
|
||||
inner: int, outer: int, pseq: list[Any]
|
||||
) -> tuple[list[Fragment], list[Line]]:
|
||||
lines: list[Line] = []
|
||||
frags: list[Fragment] = []
|
||||
indent = 3 # XXX - Should this be a parameter passed in?
|
||||
indent = 3 # XXX - Should this be a parameter passed in?
|
||||
count = 1
|
||||
r = Resources()
|
||||
newLine = False
|
||||
for entry in pseq:
|
||||
for pair in entry:
|
||||
if pair['objType'] == 'bs':
|
||||
sense = pair['obj']['sense']
|
||||
(newFrags, newLines) = do_sense(trycast(Sense, sense),indent=indent)
|
||||
if pair["objType"] == "bs":
|
||||
sense = pair["obj"]["sense"]
|
||||
(newFrags, newLines) = do_sense(
|
||||
trycast(Sense, sense), indent=indent
|
||||
)
|
||||
frags += newFrags
|
||||
lines += newLines
|
||||
newLine = True
|
||||
elif pair['objType'] == 'sense':
|
||||
elif pair["objType"] == "sense":
|
||||
frag = Fragment(f"({count})", r.textFont, color=r.baseColor)
|
||||
frag.setIndent(indent)
|
||||
if newLine:
|
||||
@@ -401,7 +489,9 @@ def do_pseq(inner: int,
|
||||
line.addFragment(frag)
|
||||
else:
|
||||
frags.append(frag)
|
||||
(newFrags, newLines) = do_sense(trycast(Sense, pair['obj']), indent=indent+1)
|
||||
(newFrags, newLines) = do_sense(
|
||||
trycast(Sense, pair["obj"]), indent=indent + 1
|
||||
)
|
||||
if newLine:
|
||||
line.addFragment(newFrags)
|
||||
lines.append(line)
|
||||
@@ -411,139 +501,156 @@ def do_pseq(inner: int,
|
||||
lines += newLines
|
||||
count += 1
|
||||
else:
|
||||
raise NotImplementedError(f"Unknown object type {pair['objType']}")
|
||||
raise NotImplementedError(
|
||||
f"Unknown object type {pair['objType']}"
|
||||
)
|
||||
return (frags, lines)
|
||||
|
||||
def do_sseq(sseq:list[list[list[Pair]]]) -> list[Line]:
|
||||
|
||||
def do_sseq(sseq: list[list[list[Pair]]]) -> list[Line]:
|
||||
lines: list[Line] = []
|
||||
r = Resources()
|
||||
for outer, item_o in enumerate(sseq):
|
||||
line = Line()
|
||||
frag =Fragment(str(outer+1), r.boldFont, color=r.baseColor)
|
||||
frag = Fragment(str(outer + 1), r.boldFont, color=r.baseColor)
|
||||
frag.setIndent(1)
|
||||
line.addFragment(frag)
|
||||
for inner, item_i in enumerate(item_o):
|
||||
indent = 2
|
||||
if len(item_o) > 1:
|
||||
frag =Fragment(chr(ord('a')+inner), r.boldFont, color=r.baseColor)
|
||||
frag = Fragment(
|
||||
chr(ord("a") + inner), r.boldFont, color=r.baseColor
|
||||
)
|
||||
frag.setIndent(2)
|
||||
line.addFragment(frag)
|
||||
indent = 3
|
||||
for pair in item_i:
|
||||
objType = pair['objType']
|
||||
if objType == 'sense':
|
||||
sense = trycast(Sense, pair['obj'])
|
||||
objType = pair["objType"]
|
||||
if objType == "sense":
|
||||
sense = trycast(Sense, pair["obj"])
|
||||
(frags, newlines) = do_sense(sense, indent=indent)
|
||||
line.addFragment(frags)
|
||||
lines.append(line)
|
||||
line = Line()
|
||||
lines += newlines
|
||||
elif objType == 'sen':
|
||||
elif objType == "sen":
|
||||
raise NotImplementedError(f"sen unimplimented")
|
||||
elif objType == 'pseq':
|
||||
(frags, newlines) = do_pseq(inner, outer, pair['obj'])
|
||||
elif objType == "pseq":
|
||||
(frags, newlines) = do_pseq(inner, outer, pair["obj"])
|
||||
line.addFragment(frags)
|
||||
lines.append(line)
|
||||
line = Line()
|
||||
lines += newlines
|
||||
elif objType == 'bs':
|
||||
sense = pair['obj']['sense']
|
||||
(newFrags, newLines) = do_sense(trycast(Sense, sense),indent=indent)
|
||||
elif objType == "bs":
|
||||
sense = pair["obj"]["sense"]
|
||||
(newFrags, newLines) = do_sense(
|
||||
trycast(Sense, sense), indent=indent
|
||||
)
|
||||
line.addFragment(newFrags)
|
||||
lines.append(line)
|
||||
line = Line()
|
||||
lines += newLines
|
||||
else:
|
||||
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
|
||||
|
||||
def do_ins(inflections:list[Inflection]|None) -> list[Fragment]:
|
||||
|
||||
def do_ins(inflections: list[Inflection] | None) -> list[Fragment]:
|
||||
assert inflections is not None
|
||||
r = Resources()
|
||||
frags: list[Fragment] = []
|
||||
sep = ''
|
||||
sep = ""
|
||||
for inflection in inflections:
|
||||
if sep == '; ':
|
||||
frag = Fragment('; ', font=r.boldFont, color=r.baseColor)
|
||||
if sep == "; ":
|
||||
frag = Fragment("; ", font=r.boldFont, color=r.baseColor)
|
||||
frags.append(frag)
|
||||
elif sep != '':
|
||||
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']
|
||||
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']))
|
||||
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}")
|
||||
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]:
|
||||
|
||||
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':
|
||||
if pair["objType"] == "text":
|
||||
line = Line()
|
||||
line.addFragment(
|
||||
Fragment(pair['obj'], r.textFont, color=r.baseColor)
|
||||
Fragment(pair["obj"], r.textFont, color=r.baseColor)
|
||||
)
|
||||
lines.append(line)
|
||||
elif pair['objType'] == 'et_snote':
|
||||
elif pair["objType"] == "et_snote":
|
||||
line = Line()
|
||||
line.addFragment(
|
||||
Fragment('Note: '+pair['obj'], r.textFont, color=r.baseColor)
|
||||
Fragment(
|
||||
"Note: " + pair["obj"], r.textFont, color=r.baseColor
|
||||
)
|
||||
)
|
||||
lines.append(line)
|
||||
else:
|
||||
raise NotImplementedError(f"Unknown key {pair['objType']} in et")
|
||||
raise NotImplementedError(
|
||||
f"Unknown key {pair['objType']} in et"
|
||||
)
|
||||
return lines
|
||||
|
||||
|
||||
def do_def(entry: DefinitionSection) -> list[Line]:
|
||||
assert entry is not None
|
||||
r = Resources()
|
||||
lines: list[Line] = []
|
||||
if 'vd' in entry:
|
||||
if "vd" in entry:
|
||||
line = Line()
|
||||
line.addFragment(
|
||||
Fragment(entry['vd'], r.italicFont, color = r.linkColor)
|
||||
)
|
||||
line.addFragment(Fragment(entry["vd"], r.italicFont, color=r.linkColor))
|
||||
lines.append(line)
|
||||
#
|
||||
# sseg is required
|
||||
#
|
||||
sseq = entry['sseq']
|
||||
sseq = entry["sseq"]
|
||||
lines += do_sseq(sseq)
|
||||
return lines
|
||||
|
||||
|
||||
def getDef(defines: Any) -> list[Line]:
|
||||
Line.setParseText(parseText)
|
||||
workList = restructure(defines)
|
||||
workList = trycast(list[Definition], workList)
|
||||
assert workList is not None
|
||||
# workList = trycast(list[Definition], workList)
|
||||
# assert workList is not None
|
||||
r = Resources()
|
||||
lines:list[Line] = []
|
||||
lines: list[Line] = []
|
||||
|
||||
#
|
||||
# No need to figure it out each time it is used
|
||||
#
|
||||
entries = 0
|
||||
id = workList[0]['meta']['id'].lower().split(':')[0]
|
||||
uses: dict[str,int] = {}
|
||||
id = workList[0]["meta"]["id"].lower().split(":")[0]
|
||||
uses: dict[str, int] = {}
|
||||
for entry in workList:
|
||||
testId = entry['meta']['id'].lower().split(':')[0]
|
||||
testId = entry["meta"]["id"].lower().split(":")[0]
|
||||
if testId == id:
|
||||
entries += 1
|
||||
#
|
||||
@@ -551,10 +658,10 @@ def getDef(defines: Any) -> list[Line]:
|
||||
# to capture the count of each FL
|
||||
#
|
||||
try:
|
||||
uses[entry['fl']] = uses.get(entry['fl'], 0) + 1
|
||||
uses[entry["fl"]] = uses.get(entry["fl"], 0) + 1
|
||||
except KeyError:
|
||||
pass
|
||||
del(entry)
|
||||
del entry
|
||||
used: dict[str, int] = {}
|
||||
for k in uses.keys():
|
||||
used[k] = 0
|
||||
@@ -562,7 +669,7 @@ def getDef(defines: Any) -> list[Line]:
|
||||
ets: list[Line] = []
|
||||
|
||||
for count, work in enumerate(workList):
|
||||
testId = work['meta']['id'].lower().split(':')[0]
|
||||
testId = work["meta"]["id"].lower().split(":")[0]
|
||||
#
|
||||
# Skip entries which are not part of the primary definition
|
||||
#
|
||||
@@ -572,25 +679,29 @@ def getDef(defines: Any) -> list[Line]:
|
||||
# Create the First line from the hwi, [ahws] and fl
|
||||
#
|
||||
line = Line()
|
||||
hwi = trycast(HeadWordInformation, work['hwi'])
|
||||
hwi = trycast(HeadWordInformation, work["hwi"])
|
||||
assert hwi is not None
|
||||
hw = re.sub(r'\*', '', hwi['hw'])
|
||||
hw = re.sub(r"\*", "", hwi["hw"])
|
||||
line.addFragment(Fragment(hw, r.headerFont, color=r.baseColor))
|
||||
if 'ahws' in work:
|
||||
ahws = trycast(list[AlternanteHeadword], work['ahws'])
|
||||
if "ahws" in work:
|
||||
ahws = trycast(list[AlternanteHeadword], work["ahws"])
|
||||
assert ahws is not None
|
||||
for ahw in ahws:
|
||||
hw = re.sub(r'\*', '', ahw['hw'])
|
||||
line.addFragment(Fragment(', ' + hw, r.headerFont, color=r.baseColor))
|
||||
if entries > 1:
|
||||
frag = Fragment(f" {count + 1} of {entries} ", r.textFont, color= r.subduedColor)
|
||||
hw = re.sub(r"\*", "", ahw["hw"])
|
||||
line.addFragment(
|
||||
Fragment(", " + hw, r.headerFont, color=r.baseColor)
|
||||
)
|
||||
if entries > 1:
|
||||
frag = Fragment(
|
||||
f" {count + 1} of {entries} ", r.textFont, color=r.subduedColor
|
||||
)
|
||||
frag.setBackground(r.subduedBackground)
|
||||
line.addFragment(frag)
|
||||
if 'fl' in work:
|
||||
text = work['fl']
|
||||
if "fl" in work:
|
||||
text = work["fl"]
|
||||
used[text] += 1
|
||||
if uses[text] > 1:
|
||||
text += f' ({used[text]})'
|
||||
text += f" ({used[text]})"
|
||||
line.addFragment(Fragment(text, r.labelFont, color=r.baseColor))
|
||||
lines.append(line)
|
||||
|
||||
@@ -599,48 +710,63 @@ def getDef(defines: Any) -> list[Line]:
|
||||
# While 'prs' is optional, the headword is not. This gets us what we want.
|
||||
#
|
||||
line = Line()
|
||||
if hwi['hw'].find('*') >= 0:
|
||||
hw = re.sub(r'\*', '\u00b7', hwi['hw'])
|
||||
line.addFragment(Fragment(hw + ' ', r.textFont, color=r.subduedColor))
|
||||
if 'prs' in hwi:
|
||||
newFrags = do_prs(trycast(list[Pronunciation], hwi['prs']))
|
||||
if hwi["hw"].find("*") >= 0:
|
||||
hw = re.sub(r"\*", "\u00b7", hwi["hw"])
|
||||
line.addFragment(
|
||||
Fragment(hw + " ", r.textFont, color=r.subduedColor)
|
||||
)
|
||||
if "prs" in hwi:
|
||||
newFrags = do_prs(trycast(list[Pronunciation], hwi["prs"]))
|
||||
line.addFragment(newFrags)
|
||||
lines.append(line)
|
||||
line = Line()
|
||||
if 'ins' in work:
|
||||
inflections = trycast(list[Inflection], work['ins'])
|
||||
if "ins" in work:
|
||||
inflections = trycast(list[Inflection], work["ins"])
|
||||
newFrags = do_ins(inflections)
|
||||
line = Line()
|
||||
line.addFragment(newFrags)
|
||||
lines.append(line)
|
||||
defines = trycast(list[DefinitionSection], work['def'])
|
||||
defines = trycast(list[DefinitionSection], work["def"])
|
||||
assert defines is not None
|
||||
for define in defines:
|
||||
try:
|
||||
lines += do_def(define)
|
||||
except NotImplementedError as e:
|
||||
print(e)
|
||||
if 'et' in work:
|
||||
if "et" in work:
|
||||
line = Line()
|
||||
line.addFragment(
|
||||
Fragment(f"{work['fl']} ({used[work['fl']]})", r.labelFont, color=r.baseColor)
|
||||
Fragment(
|
||||
f"{work['fl']} ({used[work['fl']]})",
|
||||
r.labelFont,
|
||||
color=r.baseColor,
|
||||
)
|
||||
)
|
||||
ets.append(line)
|
||||
ets += do_ets(trycast(list[list[Pair]], work['et']))
|
||||
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")
|
||||
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:
|
||||
if len(ets) > 0:
|
||||
line = Line()
|
||||
line.addFragment(
|
||||
Fragment('Etymology', r.labelFont, color=r.baseColor)
|
||||
)
|
||||
line.addFragment(Fragment("Etymology", r.labelFont, color=r.baseColor))
|
||||
lines.append(line)
|
||||
lines+=ets
|
||||
lines += ets
|
||||
return lines
|
||||
|
||||
|
||||
def parseText(frag: Fragment) -> list[Fragment]:
|
||||
org = frag.text()
|
||||
if frag.asis():
|
||||
@@ -660,7 +786,7 @@ def parseText(frag: Fragment) -> list[Fragment]:
|
||||
smallCapsFont = QFont(textFont)
|
||||
smallCapsFont.setCapitalization(QFont.Capitalization.SmallCaps)
|
||||
scriptFont = QFont(textFont)
|
||||
scriptFont.setPixelSize(int(scriptFont.pixelSize()/4))
|
||||
scriptFont.setPixelSize(int(scriptFont.pixelSize() / 4))
|
||||
boldItalicFont = QFont(boldFont)
|
||||
boldItalicFont.setItalic(True)
|
||||
boldSmallCapsFont = QFont(smallCapsFont)
|
||||
@@ -822,4 +948,3 @@ def parseText(frag: Fragment) -> list[Fragment]:
|
||||
raise NotImplementedError(
|
||||
f"Unable to locate a known token {token} in {org}"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user