diff --git a/scal3/color_utils.py b/scal3/color_utils.py index 4e8c7a6d1..b034af163 100644 --- a/scal3/color_utils.py +++ b/scal3/color_utils.py @@ -1,6 +1,8 @@ +from __future__ import annotations + import typing -ColorType: "typing.TypeAlias" = "tuple[int,int,int] | tuple[int,int,int,int]" +ColorType: typing.TypeAlias = "tuple[int,int,int] | tuple[int,int,int,int]" def rgbToInt(r, g, b): diff --git a/scal3/core.py b/scal3/core.py index 2969fcd69..70a9d7346 100644 --- a/scal3/core.py +++ b/scal3/core.py @@ -13,6 +13,8 @@ # # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + import os import os.path import re @@ -362,7 +364,7 @@ def validatePlugList() -> None: m -= 1 -def initPlugins(fs: "s_object.FileSystem") -> None: +def initPlugins(fs: s_object.FileSystem) -> None: # log.debug("----------------------- initPlugins") # Assert that user configuarion for plugins is OK validatePlugList() diff --git a/scal3/event_lib.py b/scal3/event_lib.py index 3d074b833..e2e9a794e 100644 --- a/scal3/event_lib.py +++ b/scal3/event_lib.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -167,10 +169,10 @@ class Smallest: def __eq__(self, other: object) -> bool: return isinstance(other, Smallest) - def __lt__(self, other: "Any") -> bool: + def __lt__(self, other: Any) -> bool: return not isinstance(other, Smallest) - def __gt__(self, other: "Any") -> bool: + def __gt__(self, other: Any) -> bool: return False def __hash__(self): @@ -330,7 +332,7 @@ def __init__(self, tname: str) -> None: self.byDesc = {} self.main = None - def register(self, cls: "type[ClassGroup]") -> "type[ClassGroup]": + def register(self, cls: type[ClassGroup]) -> type[ClassGroup]: assert cls.name cls.tname = self.tname self.append(cls) @@ -341,7 +343,7 @@ def register(self, cls: "type[ClassGroup]") -> "type[ClassGroup]": self.byName[cls.nameAlias] = cls return cls - def setMain(self, cls: "type[ClassGroup]") -> "type[ClassGroup]": + def setMain(self, cls: type[ClassGroup]) -> type[ClassGroup]: self.main = cls return cls @@ -371,7 +373,7 @@ class classes: # FIXME move this o Event class -def getEventUID(event: "Event") -> str: +def getEventUID(event: Event) -> str: import socket event_st = core.compressLongInt(hash(str(event.getData()))) @@ -416,7 +418,7 @@ def getEndJd(self) -> int: class JdOccurSet(OccurSet): name = "jdSet" - def __init__(self, jdSet: "set[int] | None" = None) -> None: + def __init__(self, jdSet: set[int] | None = None) -> None: OccurSet.__init__(self) if not jdSet: jdSet = [] @@ -491,7 +493,7 @@ def calcJdRanges(self) -> list[tuple[int, int]]: class IntervalOccurSet(OccurSet): name = "timeRange" - def __init__(self, rangeList: "list[tuple[int, int]] | None" = None) -> str: + def __init__(self, rangeList: list[tuple[int, int]] | None = None) -> str: OccurSet.__init__(self) if not rangeList: rangeList = [] @@ -643,11 +645,11 @@ def getServerString(self) -> str: def __bool__(self) -> bool: return True - def __init__(self, parent: "Event"): + def __init__(self, parent: Event): """Parent can be an event for now (maybe later a group too).""" self.parent = parent - def copy(self) -> "EventRule": + def copy(self) -> EventRule: newObj = self.__class__(self.parent) newObj.fs = getattr(self, "fs", None) newObj.copyFrom(self) @@ -663,7 +665,7 @@ def calcOccurrence( self, startJd: int, endJd: int, - event: "Event", + event: Event, ) -> OccurSet: raise NotImplementedError @@ -685,7 +687,7 @@ def calcOccurrence( self, startJd: int, endJd: int, - event: "Event", # noqa: ARG002 + event: Event, # noqa: ARG002 ) -> OccurSet: # improve performance FIXME jds = set() @@ -701,14 +703,14 @@ class MultiValueAllDayEventRule(AllDayEventRule): params = ("values",) expand = True # FIXME - def __init__(self, parent: "Event") -> None: + def __init__(self, parent: Event) -> None: EventRule.__init__(self, parent) self.values = [] - def getData(self) -> "list[Any]": + def getData(self) -> list[Any]: return self.values - def setData(self, data: "Any"): + def setData(self, data: Any): if not isinstance(data, tuple | list): data = [data] self.values = data @@ -716,7 +718,7 @@ def setData(self, data: "Any"): def __str__(self) -> str: return textNumEncode(numRangesEncode(self.values, ", ")) - def hasValue(self, value: "Any") -> bool: + def hasValue(self, value: Any) -> bool: for item in self.values: if isinstance(item, tuple | list): if item[0] <= value <= item[1]: @@ -725,7 +727,7 @@ def hasValue(self, value: "Any") -> bool: return True return False - def getValuesPlain(self) -> "list[int | tuple[int, int]]": + def getValuesPlain(self) -> list[int | tuple[int, int]]: ls = [] for item in self.values: if isinstance(item, tuple | list): @@ -734,7 +736,7 @@ def getValuesPlain(self) -> "list[int | tuple[int, int]]": ls.append(item) return ls - def setValuesPlain(self, values: "list[int | tuple[int, int]]") -> None: + def setValuesPlain(self, values: list[int | tuple[int, int]]) -> None: self.values = simplifyNumList(values) def changeCalType(self, _calType: int) -> bool: # noqa: PLR6301 @@ -750,7 +752,7 @@ class YearEventRule(MultiValueAllDayEventRule): def getServerString(self) -> str: return numRangesEncode(self.values, " ") # no comma - def __init__(self, parent: "Event") -> None: + def __init__(self, parent: Event) -> None: MultiValueAllDayEventRule.__init__(self, parent) self.values = [getSysDate(self.getCalType())[0]] @@ -760,7 +762,7 @@ def jdMatches(self, jd: int) -> bool: def newCalTypeValues( self, newCalType: int, - ) -> "list[int | tuple[int, int]]": + ) -> list[int | tuple[int, int]]: def yearConv(year): return convert(year, 7, 1, curCalType, newCalType)[0] @@ -796,7 +798,7 @@ class MonthEventRule(MultiValueAllDayEventRule): def getServerString(self) -> str: return numRangesEncode(self.values, " ") # no comma - def __init__(self, parent: "Event") -> None: + def __init__(self, parent: Event) -> None: MultiValueAllDayEventRule.__init__(self, parent) self.values = [1] @@ -813,7 +815,7 @@ class DayOfMonthEventRule(MultiValueAllDayEventRule): def getServerString(self) -> str: return numRangesEncode(self.values, " ") # no comma - def __init__(self, parent: "Event") -> None: + def __init__(self, parent: Event) -> None: MultiValueAllDayEventRule.__init__(self, parent) self.values = [1] @@ -838,7 +840,7 @@ class WeekNumberModeEventRule(EventRule): def getServerString(self) -> str: return self.weekNumMode - def __init__(self, parent: "Event") -> None: + def __init__(self, parent: Event) -> None: EventRule.__init__(self, parent) self.weekNumMode = self.EVERY_WEEK @@ -858,7 +860,7 @@ def calcOccurrence( self, startJd: int, endJd: int, - event: "Event", + event: Event, ) -> OccurSet: # improve performance FIXME startAbsWeekNum = getAbsWeekNumberFromJd(event.getStartJd()) - 1 @@ -911,14 +913,14 @@ class WeekDayEventRule(AllDayEventRule): def getServerString(self) -> str: return s_join(self.weekDayList) - def __init__(self, parent: "Event") -> None: + def __init__(self, parent: Event) -> None: EventRule.__init__(self, parent) self.weekDayList = list(range(7)) # or [] FIXME def getData(self) -> list[int]: return self.weekDayList - def setData(self, data: "int | list[int]") -> None: + def setData(self, data: int | list[int]) -> None: if isinstance(data, int): self.weekDayList = [data] elif isinstance(data, tuple | list): @@ -1017,7 +1019,7 @@ def __str__(self) -> str: ], ) - def __init__(self, parent: "Event") -> None: + def __init__(self, parent: Event) -> None: EventRule.__init__(self, parent) self.month = 1 self.wmIndex = 4 @@ -1036,7 +1038,7 @@ def calcOccurrence( self, startJd: int, endJd: int, - event: "Event", # noqa: ARG002 + event: Event, # noqa: ARG002 ) -> OccurSet: calType = self.getCalType() startYear, _startMonth, _startDay = jd_to(startJd, calType) @@ -1088,7 +1090,7 @@ def getServerString(self) -> str: def __str__(self) -> str: return dateEncode(self.date) - def __init__(self, parent: "Event") -> None: + def __init__(self, parent: Event) -> None: EventRule.__init__(self, parent) self.date = getSysDate(self.getCalType()) @@ -1112,7 +1114,7 @@ def calcOccurrence( self, startJd: int, endJd: int, - event: "Event", # noqa: ARG002 + event: Event, # noqa: ARG002 ) -> OccurSet: myJd = self.getJd() if startJd <= myJd < endJd: @@ -1136,7 +1138,7 @@ def getServerString(self) -> str: H, M, S = self.time return f"{y:04d}/{m:02d}/{d:02d} {H:02d}:{M:02d}:{S:02d}" - def __init__(self, parent: "Event") -> None: + def __init__(self, parent: Event) -> None: DateEventRule.__init__(self, parent) self.time = localtime()[3:6] @@ -1178,7 +1180,7 @@ def getData(self) -> dict[str, str]: "time": timeEncode(self.time), } - def setData(self, arg: "dict[str, str] | str") -> None: + def setData(self, arg: dict[str, str] | str) -> None: if isinstance(arg, dict): self.date = dateDecode(arg["date"]) if "time" in arg: @@ -1220,7 +1222,7 @@ def __str__(self) -> str: H, M, S = self.dayTime return f"{H:02d}:{M:02d}:{S:02d}" - def __init__(self, parent: "Event") -> None: + def __init__(self, parent: Event) -> None: EventRule.__init__(self, parent) self.dayTime = localtime()[3:6] @@ -1234,7 +1236,7 @@ def calcOccurrence( self, startJd: int, endJd: int, - event: "Event", # noqa: ARG002 + event: Event, # noqa: ARG002 ) -> OccurSet: mySec = getSecondsFromHms(*self.dayTime) return TimeListOccurSet( # FIXME @@ -1305,7 +1307,7 @@ def calcOccurrence( self, startJd: int, endJd: int, - event: "Event", # noqa: ARG002 + event: Event, # noqa: ARG002 ) -> OccurSet: daySecStart = getSecondsFromHms(*self.dayTimeStart) daySecEnd = getSecondsFromHms(*self.dayTimeEnd) @@ -1334,7 +1336,7 @@ def calcOccurrence( self, startJd: int, endJd: int, - event: "Event", # noqa: ARG002 + event: Event, # noqa: ARG002 ) -> OccurSet: return IntervalOccurSet.newFromStartEnd( max(self.getEpochFromJd(startJd), self.getEpoch()), @@ -1357,7 +1359,7 @@ def calcOccurrence( self, startJd: int, endJd: int, - event: "Event", # noqa: ARG002 + event: Event, # noqa: ARG002 ) -> OccurSet: return IntervalOccurSet.newFromStartEnd( self.getEpochFromJd(startJd), @@ -1414,7 +1416,7 @@ def getUnitSymbol(self) -> str: 3600 * 24 * 7: "w", }[self.unit] - def __init__(self, parent: "RuleContainer") -> None: + def __init__(self, parent: RuleContainer) -> None: EventRule.__init__(self, parent) self.value = 0 self.unit = 1 # seconds @@ -1445,7 +1447,7 @@ def calcOccurrence( self, startJd: int, endJd: int, - event: "Event", # noqa: ARG002 + event: Event, # noqa: ARG002 ) -> OccurSet: parentStart, ok = self.parent["start"] if not ok: @@ -1469,7 +1471,7 @@ def cycleDaysCalcOccurrence( days: int, startJd: int, endJd: int, - event: "Event", + event: Event, ) -> OccurSet: eStartJd = event.getStartJd() if startJd <= eStartJd: @@ -1504,7 +1506,7 @@ def getServerString(self) -> str: def __str__(self) -> str: return f"{self.days}" - def __init__(self, parent: "Event") -> None: + def __init__(self, parent: Event) -> None: EventRule.__init__(self, parent) self.days = 7 @@ -1518,7 +1520,7 @@ def calcOccurrence( self, startJd: int, endJd: int, - event: "Event", + event: Event, ) -> OccurSet: return cycleDaysCalcOccurrence(self.days, startJd, endJd, event) @@ -1545,7 +1547,7 @@ def getServerString(self) -> str: def __str__(self) -> str: return f"{self.weeks}" - def __init__(self, parent: "RuleContainer") -> None: + def __init__(self, parent: RuleContainer) -> None: EventRule.__init__(self, parent) self.weeks = 1 @@ -1559,7 +1561,7 @@ def calcOccurrence( self, startJd: int, endJd: int, - event: "Event", + event: Event, ) -> OccurSet: return cycleDaysCalcOccurrence( self.weeks * 7, @@ -1599,18 +1601,18 @@ def __str__(self) -> str: H, M, S = self.extraTime return f"{self.days} days, {H:02d}:{M:02d}:{S:02d}" - def __init__(self, parent: "RuleContainer") -> None: + def __init__(self, parent: RuleContainer) -> None: EventRule.__init__(self, parent) self.days = 7 self.extraTime = (0, 0, 0) - def getData(self) -> "dict[str, Any]": + def getData(self) -> dict[str, Any]: return { "days": self.days, "extraTime": timeEncode(self.extraTime), } - def setData(self, arg: "dict[str, Any]") -> None: + def setData(self, arg: dict[str, Any]) -> None: self.days = arg["days"] self.extraTime = timeDecode(arg["extraTime"]) @@ -1618,7 +1620,7 @@ def calcOccurrence( self, startJd: int, endJd: int, - event: "Event", + event: Event, ) -> OccurSet: startEpoch = self.getEpochFromJd(startJd) eventStartEpoch = event.getStartEpoch() @@ -1702,7 +1704,7 @@ def calcOccurrence( self, startJd: int, endJd: int, - event: "Event", # noqa: ARG002 + event: Event, # noqa: ARG002 ) -> OccurSet: # improve performance # FIXME return JdOccurSet( @@ -1714,7 +1716,7 @@ def getData(self) -> list[str]: def setData( self, - datesConf: "str | list[str | tuple | list]", + datesConf: str | list[str | tuple | list], ) -> None: dates = [] if isinstance(datesConf, str): @@ -1765,13 +1767,13 @@ class EventNotifier(SObj): desc = "" params = () - def __init__(self, event: "Event") -> None: + def __init__(self, event: Event) -> None: self.event = event def getCalType(self) -> str: return self.event.calType - def notify(self, finishFunc: "Callable") -> None: + def notify(self, finishFunc: Callable) -> None: pass @@ -1784,12 +1786,12 @@ class AlarmNotifier(EventNotifier): "playerCmd", ) - def __init__(self, event: "Event") -> None: + def __init__(self, event: Event) -> None: EventNotifier.__init__(self, event) self.alarmSound = "" # FIXME self.playerCmd = "mplayer" - def notify(self, finishFunc: "Callable") -> None: + def notify(self, finishFunc: Callable) -> None: from scal3.ui_gtk.event.notifier.alarm import notify notify(self, finishFunc) @@ -1806,7 +1808,7 @@ class FloatingMsgNotifier(EventNotifier): "textColor", ) - def __init__(self, event: "Event") -> None: + def __init__(self, event: Event) -> None: EventNotifier.__init__(self, event) # --- self.fillWidth = False @@ -1814,7 +1816,7 @@ def __init__(self, event: "Event") -> None: self.bgColor = (255, 255, 0) self.textColor = (0, 0, 0) - def notify(self, finishFunc: "Callable") -> None: + def notify(self, finishFunc: Callable) -> None: from scal3.ui_gtk.event.notifier.floatingMsg import notify notify(self, finishFunc) @@ -1826,12 +1828,12 @@ class WindowMsgNotifier(EventNotifier): desc = _("Message Window") # FIXME params = ("extraMessage",) - def __init__(self, event: "Event") -> None: + def __init__(self, event: Event) -> None: EventNotifier.__init__(self, event) self.extraMessage = "" # window icon, FIXME - def notify(self, finishFunc: "Callable") -> None: + def notify(self, finishFunc: Callable) -> None: from scal3.ui_gtk.event.notifier.windowMsg import notify notify(self, finishFunc) @@ -1846,12 +1848,12 @@ class CommandNotifier(EventNotifier): "pyEval", ) - def __init__(self, event: "Event") -> None: + def __init__(self, event: Event) -> None: EventNotifier.__init__(self, event) self.command = "" self.pyEval = False - def notify(self, finishFunc: "Callable") -> None: + def notify(self, finishFunc: Callable) -> None: from scal3.ui_gtk.event.command.alarm import notify notify(self, finishFunc) @@ -1890,20 +1892,20 @@ def __init__(self) -> None: def clearRules(self) -> None: self.rulesOd = OrderedDict() - def getRule(self, key: str) -> "EventRule": + def getRule(self, key: str) -> EventRule: return self.rulesOd[key] - def getRuleIfExists(self, key: str) -> "EventRule | None": + def getRuleIfExists(self, key: str) -> EventRule | None: return self.rulesOd.get(key) - def setRule(self, key: str, value: "EventRule"): + def setRule(self, key: str, value: EventRule): self.rulesOd[key] = value - def iterRulesData(self) -> "Iterator[tuple[str, Any]]": + def iterRulesData(self) -> Iterator[tuple[str, Any]]: for rule in self.rulesOd.values(): yield rule.name, rule.getData() - def getRulesData(self) -> "list[tuple[str, Any]]": + def getRulesData(self) -> list[tuple[str, Any]]: return list(self.iterRulesData()) def getRulesHash(self) -> int: @@ -1919,40 +1921,40 @@ def getRulesHash(self) -> int: def getRuleNames(self) -> list[str]: return list(self.rulesOd) - def addRule(self, rule: "EventRule") -> None: + def addRule(self, rule: EventRule) -> None: self.rulesOd[rule.name] = rule - def addNewRule(self, ruleType: str) -> "EventRule": + def addNewRule(self, ruleType: str) -> EventRule: rule = classes.rule.byName[ruleType](self) self.addRule(rule) return rule - def getAddRule(self, ruleType: str) -> "EventRule": + def getAddRule(self, ruleType: str) -> EventRule: rule = self.getRuleIfExists(ruleType) if rule is not None: return rule return self.addNewRule(ruleType) - def removeRule(self, rule: "EventRule") -> None: + def removeRule(self, rule: EventRule) -> None: del self.rulesOd[rule.name] def __delitem__(self, key: str) -> None: self.rulesOd.__delitem__(key) # returns (rule, found) where found is boolean - def __getitem__(self, key: str) -> "tuple[EventRule | None, bool]": + def __getitem__(self, key: str) -> tuple[EventRule | None, bool]: rule = self.getRuleIfExists(key) if rule is None: return None, False return rule, True - def __setitem__(self, key: str, value: "EventRule") -> None: + def __setitem__(self, key: str, value: EventRule) -> None: self.setRule(key, value) - def __iter__(self) -> "Iterator[EventRule]": + def __iter__(self) -> Iterator[EventRule]: return iter(self.rulesOd.values()) - def setRulesData(self, rulesData: "list[tuple[str, Any]]") -> None: + def setRulesData(self, rulesData: list[tuple[str, Any]]) -> None: self.clearRules() for ruleName, ruleData in rulesData: rule = classes.rule.byName[ruleName](self) @@ -1964,7 +1966,7 @@ def addRequirements(self) -> None: if name not in self.rulesOd: self.addNewRule(name) - def checkAndAddRule(self, rule: "EventRule") -> tuple[bool, str]: + def checkAndAddRule(self, rule: EventRule) -> tuple[bool, str]: ok, msg = self.checkRulesDependencies(newRule=rule) if ok: self.addRule(rule) @@ -1975,7 +1977,7 @@ def removeSomeRuleTypes(self, *rmTypes) -> None: if ruleType in self.rulesOd: del self.rulesOd[ruleType] - def checkAndRemoveRule(self, rule: "EventRule") -> tuple[bool, str]: + def checkAndRemoveRule(self, rule: EventRule) -> tuple[bool, str]: ok, msg = self.checkRulesDependencies(disabledRule=rule) if ok: self.removeRule(rule) @@ -1983,8 +1985,8 @@ def checkAndRemoveRule(self, rule: "EventRule") -> tuple[bool, str]: def checkRulesDependencies( self, - newRule: "EventRule | None" = None, - disabledRule: "EventRule | None" = None, + newRule: EventRule | None = None, + disabledRule: EventRule | None = None, ) -> tuple[bool, str]: rulesOd = self.rulesOd.copy() if newRule: @@ -2019,14 +2021,14 @@ def checkRulesDependencies( ) return (True, "") - def copyRulesFrom(self, other: "EventRule") -> None: + def copyRulesFrom(self, other: EventRule) -> None: for ruleType, rule in other.rulesOd.items(): if self.supportedRules is None or ruleType in self.supportedRules: self.getAddRule(ruleType).copyFrom(rule) def copySomeRuleTypesFrom( self, - other: "EventRule", + other: EventRule, *ruleTypes: tuple[str], ) -> None: for ruleType in ruleTypes: @@ -2473,7 +2475,7 @@ def calcEventOccurrence(self): # FIXME: too tricky! # def calcFirstOccurrenceAfterJd(self, startJd): - def checkNotify(self, finishFunc: "Callable") -> None: + def checkNotify(self, finishFunc: Callable) -> None: """To be called from notification scheduler.""" if not self.parent: return @@ -2490,7 +2492,7 @@ def checkNotify(self, finishFunc: "Callable") -> None: return self.notify(finishFunc) - def notify(self, finishFunc: "Callable") -> None: + def notify(self, finishFunc: Callable) -> None: # FIXME: get rid of self.n ?? self.n = len(self.notifiers) @@ -3887,7 +3889,7 @@ def __iter__(self): def __len__(self): return len(self.idList) - def preAdd(self, event: "Event"): + def preAdd(self, event: Event): if event.id in self.idList: raise ValueError(f"{self} already contains {event}") if event.parent not in {None, self}: @@ -3896,20 +3898,20 @@ def preAdd(self, event: "Event"): f", trying to add to {self}", ) - def postAdd(self, event: "Event"): + def postAdd(self, event: Event): event.parent = self # needed? FIXME - def insert(self, index, event: "Event"): + def insert(self, index, event: Event): self.preAdd(event) self.idList.insert(index, event.id) self.postAdd(event) - def append(self, event: "Event"): + def append(self, event: Event): self.preAdd(event) self.idList.append(event.id) self.postAdd(event) - def add(self, event: "Event") -> None: + def add(self, event: Event) -> None: if self.addEventsToBeginning: self.insert(0, event) else: @@ -3924,7 +3926,7 @@ def moveUp(self, index): def moveDown(self, index): return self.idList.insert(index + 1, self.idList.pop(index)) - def remove(self, event: "Event"): # call when moving to trash + def remove(self, event: Event): # call when moving to trash """ excludes event from this container (group or trash), not delete event data completely @@ -3956,7 +3958,7 @@ def setData(self, data) -> None: # --- iconRelativeToAbsInObj(self) - def getEventNoCache(self, eid: int) -> "Event": + def getEventNoCache(self, eid: int) -> Event: """ no caching. and no checking if group contains eid used only for sorting events. @@ -3966,7 +3968,7 @@ def getEventNoCache(self, eid: int) -> "Event": event.rulesHash = event.getRulesHash() return event - def getSortBys(self) -> "tuple[str, list[str]]": + def getSortBys(self) -> tuple[str, list[str]]: if not self.enable: return self.sortByDefault, self.sortBys @@ -3975,7 +3977,7 @@ def getSortBys(self) -> "tuple[str, list[str]]": ("time_first", _("First Occurrence Time"), False), ] - def getSortByValue(self, event: "Event", attr: str) -> "Any": + def getSortByValue(self, event: Event, attr: str) -> Any: if attr in {"time_last", "time_first"}: if event.isSingleOccur: epoch = event.getStartEpoch() @@ -4004,12 +4006,12 @@ def sort( break if isTypeDep: - def event_key(event: "Event"): + def event_key(event: Event): return (event.name, self.getSortByValue(event, attr)) else: - def event_key(event: "Event"): + def event_key(event: Event): return self.getSortByValue(event, attr) self.idList.sort( @@ -4026,8 +4028,8 @@ def __init__(self): def __add__( self, - other: "EventGroupsImportResult", - ) -> "EventGroupsImportResult": + other: EventGroupsImportResult, + ) -> EventGroupsImportResult: r = EventGroupsImportResult() r.newGroupIds = self.newGroupIds | other.newGroupIds r.newEventIds = self.newEventIds | other.newEventIds @@ -4123,7 +4125,7 @@ def getFile(cls, _id: int) -> str: return join(groupsDir, f"{_id}.json") @classmethod - def iterFiles(cls, fs: FileSystem) -> "Iterator[str]": + def iterFiles(cls, fs: FileSystem) -> Iterator[str]: for _id in range(1, lastIds.group + 1): fpath = cls.getFile(_id) if not fs.isfile(fpath): @@ -4131,10 +4133,10 @@ def iterFiles(cls, fs: FileSystem) -> "Iterator[str]": yield fpath @classmethod - def getSubclass(cls, _type: str) -> "type[EventGroup]": + def getSubclass(cls, _type: str) -> type[EventGroup]: return classes.group.byName[_type] - def getTimeZoneObj(self) -> "datetime.tzinfo": + def getTimeZoneObj(self) -> datetime.tzinfo: if self.timeZoneEnable and self.timeZone: tz = mytz.gettz(self.timeZone) if tz: @@ -4153,7 +4155,7 @@ def getEndEpoch(self) -> int: def showInCal(self) -> bool: return self.showInDCal or self.showInWCal or self.showInMCal - def __getitem__(self, key: str) -> "Event": + def __getitem__(self, key: str) -> Event: # if isinstance(key, basestring): # ruleName # return self.getRule(key) if isinstance(key, int): # eventId @@ -4162,7 +4164,7 @@ def __getitem__(self, key: str) -> "Event": f"invalid key {key!r} given to EventGroup.__getitem__", ) - def __setitem__(self, key: int, value: "Event") -> None: + def __setitem__(self, key: int, value: Event) -> None: # if isinstance(key, basestring): # ruleName # return self.setRule(key, value) if isinstance(key, int): # eventId @@ -4179,7 +4181,7 @@ def __delitem__(self, key: int) -> None: f"invalid key {key!r} given to EventGroup.__delitem__", ) - def checkEventToAdd(self, event: "Event") -> bool: + def checkEventToAdd(self, event: Event) -> bool: return event.name in self.acceptsEventTypes def __repr__(self) -> str: @@ -4188,7 +4190,7 @@ def __repr__(self) -> str: def __str__(self) -> str: return f"{self.__class__.__name__}(_id={self.id!r}, title='{self.title}')" - def __init__(self, _id: "int | None" = None) -> None: + def __init__(self, _id: int | None = None) -> None: EventContainer.__init__(self, title=self.desc) if _id is None: self.id = None @@ -4289,13 +4291,13 @@ def getSyncDurationSec(self) -> int: value, unit = self.remoteSyncDuration return value * unit - def afterSync(self, startEpoch: "int | None" = None) -> None: + def afterSync(self, startEpoch: int | None = None) -> None: endEpoch = now() if startEpoch is None: startEpoch = endEpoch self.remoteSyncData[self.remoteIds] = (startEpoch, endEpoch) - def getLastSync(self) -> "int | None": + def getLastSync(self) -> int | None: """Return a tuple (startEpoch, endEpoch) or None.""" if self.remoteIds: with suppress(KeyError): @@ -4311,7 +4313,7 @@ def setDefaults(self) -> None: def __bool__(self) -> bool: return self.enable # FIXME - def setId(self, _id: "int | None" = None) -> None: + def setId(self, _id: int | None = None) -> None: if _id is None or _id < 0: _id = lastIds.group + 1 # FIXME lastIds.group = _id @@ -4323,10 +4325,10 @@ def setId(self, _id: "int | None" = None) -> None: def setTitle(self, title: str) -> None: self.title = title - def setColor(self, color: "tuple[int, int, int]") -> None: + def setColor(self, color: tuple[int, int, int]) -> None: self.color = color - def getData(self) -> "dict[str, Any]": + def getData(self) -> dict[str, Any]: data = EventContainer.getData(self) data["type"] = self.name for attr in ( @@ -4338,7 +4340,7 @@ def getData(self) -> "dict[str, Any]": data[attr] = sorted(data[attr].items()) return data - def setData(self, data: "dict[str, Any]") -> None: + def setData(self, data: dict[str, Any]) -> None: eventCacheSize = self.eventCacheSize if "showInCal" in data: # for compatibility data["showInDCal"] = data["showInWCal"] = data["showInMCal"] = data[ @@ -4388,12 +4390,12 @@ def removeFromCache(self, eid: int) -> None: if self.eventCache.get(eid) is not None: self.eventCache.pop(eid) - def setToCache(self, event: "Event"): + def setToCache(self, event: Event): if not self.eventCache: return self.eventCache[event.id] = event - def getEvent(self, eid: int) -> "Event": + def getEvent(self, eid: int) -> Event: if eid not in self.idList: raise ValueError(f"{self} does not contain {eid!r}") if self.eventCache: @@ -4406,7 +4408,7 @@ def getEvent(self, eid: int) -> "Event": self.setToCache(event) return event - def create(self, eventType: str) -> "Event": + def create(self, eventType: str) -> Event: # if not eventType in self.acceptsEventTypes: # FIXME # raise ValueError( # f"Event type '{eventType}' not supported " @@ -4419,7 +4421,7 @@ def create(self, eventType: str) -> "Event": # ----------------------------------------------- # call when moving to trash - def remove(self, event: "Event") -> int: + def remove(self, event: Event) -> int: index = EventContainer.remove(self, event) self.removeFromCache(event.id) if event.remoteIds: @@ -4442,7 +4444,7 @@ def removeAll(self) -> None: self.occur.clear() self.occurCount = 0 - def postAdd(self, event: "Event") -> None: + def postAdd(self, event: Event) -> None: EventContainer.postAdd(self, event) self.setToCache(event) # if event.remoteIds: @@ -4453,28 +4455,28 @@ def postAdd(self, event: "Event") -> None: if self.enable: self.updateOccurrenceEvent(event) - def updateCache(self, event: "Event"): + def updateCache(self, event: Event): if self.eventCache and self.eventCache.get(event.id) is not None: self.setToCache(event) event.afterModify() - def copy(self) -> "EventGroup": + def copy(self) -> EventGroup: newGroup = SObj.copy(self) newGroup.removeAll() return newGroup - def copyFrom(self, other: "EventGroup") -> None: + def copyFrom(self, other: EventGroup) -> None: EventContainer.copyFrom(self, other) self.enable = other.enable - def copyAs(self, newGroupType: str) -> "EventGroup": + def copyAs(self, newGroupType: str) -> EventGroup: newGroup = classes.group.byName[newGroupType]() newGroup.fs = self.fs newGroup.copyFrom(self) newGroup.removeAll() return newGroup - def deepCopy(self) -> "EventGroup": + def deepCopy(self) -> EventGroup: newGroup = self.copy() for event in self: newEvent = event.copy() @@ -4482,7 +4484,7 @@ def deepCopy(self) -> "EventGroup": newGroup.append(newEvent) return newGroup - def deepConvertTo(self, newGroupType: str) -> "EventGroup": + def deepConvertTo(self, newGroupType: str) -> EventGroup: newGroup = self.copyAs(newGroupType) newEventType = newGroup.acceptsEventTypes[0] newGroup.enable = False # to prevent per-event node update @@ -4498,7 +4500,7 @@ def deepConvertTo(self, newGroupType: str) -> "EventGroup": # events with the same id"s, can not be contained by two groups return newGroup - def calcGroupOccurrences(self) -> "Iterator[tuple[Event, OccurSet]]": + def calcGroupOccurrences(self) -> Iterator[tuple[Event, OccurSet]]: startJd = self.startJd endJd = self.endJd for event in self: @@ -4515,7 +4517,7 @@ def afterModify(self) -> None: # FIXME else: self.clearCache() - def updateOccurrenceEvent(self, event: "Event") -> None: + def updateOccurrenceEvent(self, event: Event) -> None: log.debug( f"updateOccurrenceEvent: id={self.id}" f" title={self.title} eid={event.id}", @@ -4585,8 +4587,8 @@ def updateOccurrence(self) -> None: @staticmethod def _exportToIcsFpEvent( - fp: "io.TextIOBase", - event: "Event", + fp: io.TextIOBase, + event: Event, currentTimeStamp: str, ) -> None: # log.debug("exportToIcsFp", event.id) @@ -4657,12 +4659,12 @@ def _exportToIcsFpEvent( else: raise TypeError(f"invalid type {type(occur)} for occur") - def exportToIcsFp(self, fp: "io.TextIOBase") -> None: + def exportToIcsFp(self, fp: io.TextIOBase) -> None: currentTimeStamp = ics.getIcsTimeByEpoch(now()) for event in self: self._exportToIcsFpEvent(fp, event, currentTimeStamp) - def exportData(self) -> "dict[str, Any]": + def exportData(self) -> dict[str, Any]: data = self.getData() for attr in self.importExportExclude: del data[attr] @@ -4685,7 +4687,7 @@ def exportData(self) -> "dict[str, Any]": del data["idList"] return data - def loadEventIdByUuid(self) -> "dict[str, int]": + def loadEventIdByUuid(self) -> dict[str, int]: existingIds = set(self.idByUuid.values()) for eid in self.idList: if eid in existingIds: @@ -4696,7 +4698,7 @@ def loadEventIdByUuid(self) -> "dict[str, int]": self.idByUuid[event.uuid] = event.id return self.idByUuid - def appendByData(self, eventData: "dict[str, int]") -> "Event": + def appendByData(self, eventData: dict[str, int]) -> Event: event = self.create(eventData["type"]) event.setData(eventData) event.save() @@ -4705,7 +4707,7 @@ def appendByData(self, eventData: "dict[str, int]") -> "Event": def importData( self, - data: "dict[str, Any]", + data: dict[str, Any], importMode=IMPORT_MODE_APPEND, ) -> EventGroupsImportResult: """The caller must call group.save() after this.""" @@ -4793,7 +4795,7 @@ def search(self, conds): event.save() yield event - def createPatchList(self, sinceEpoch: int) -> "list[dict[str, Any]]": + def createPatchList(self, sinceEpoch: int) -> list[dict[str, Any]]: patchList = [] for event in self: @@ -4842,7 +4844,7 @@ class TaskList(EventGroup): ) sortByDefault = "start" - def getSortByValue(self, event: "Event", attr: str) -> "Any": + def getSortByValue(self, event: Event, attr: str) -> Any: if event.name in self.acceptsEventTypes: if attr == "start": return event.getStartEpoch() @@ -4850,21 +4852,21 @@ def getSortByValue(self, event: "Event", attr: str) -> "Any": return event.getEndEpoch() return EventGroup.getSortByValue(self, event, attr) - def __init__(self, _id: "int | None" = None) -> None: + def __init__(self, _id: int | None = None) -> None: EventGroup.__init__(self, _id) self.defaultDuration = (0, 1) # (value, unit) - def copyFrom(self, other: "EventGroup") -> None: + def copyFrom(self, other: EventGroup) -> None: EventGroup.copyFrom(self, other) if other.name == self.name: self.defaultDuration = other.defaultDuration[:] - def getData(self) -> "dict[str, Any]": + def getData(self) -> dict[str, Any]: data = EventGroup.getData(self) data["defaultDuration"] = durationEncode(*self.defaultDuration) return data - def setData(self, data: "dict[str, Any]") -> None: + def setData(self, data: dict[str, Any]) -> None: EventGroup.setData(self, data) if "defaultDuration" in data: self.defaultDuration = durationDecode(data["defaultDuration"]) @@ -4883,7 +4885,7 @@ class NoteBook(EventGroup): sortBys = EventGroup.sortBys + (("date", _("Date"), True),) sortByDefault = "date" - def getSortByValue(self, event: "Event", attr: str) -> "Any": + def getSortByValue(self, event: Event, attr: str) -> Any: if event.name in self.acceptsEventTypes and attr == "date": return event.getJd() return EventGroup.getSortByValue(self, event, attr) @@ -4897,7 +4899,7 @@ class YearlyGroup(EventGroup): canConvertTo = ("noteBook",) params = EventGroup.params + ("showDate",) - def __init__(self, _id: "int | None" = None) -> None: + def __init__(self, _id: int | None = None) -> None: EventGroup.__init__(self, _id) self.showDate = True @@ -4933,7 +4935,7 @@ class UniversityTerm(EventGroup): "Edit University Term and define some Courses before you add a Class/Exam", ) - def getSortByValue(self, event: "Event", attr: str) -> "Any": + def getSortByValue(self, event: Event, attr: str) -> Any: if event.name in self.acceptsEventTypes: if attr == "course": return event.courseId @@ -4960,7 +4962,7 @@ def getSortByValue(self, event: "Event", attr: str) -> "Any": return date.getJd(), dayTimeRange.getHourRange() return EventGroup.getSortByValue(self, event, attr) - def __init__(self, _id: "int | None" = None) -> None: + def __init__(self, _id: int | None = None) -> None: EventGroup.__init__(self, _id) self.classesEndDate = getSysDate(self.calType) # FIXME self.setCourses([]) # list of (courseId, courseName, courseUnits) @@ -4973,7 +4975,7 @@ def __init__(self, _id: "int | None" = None) -> None: (18, 0), ] # FIXME - def getClassBoundsFormatted(self) -> "tuple[list[str], list[float]]": + def getClassBoundsFormatted(self) -> tuple[list[str], list[float]]: count = len(self.classTimeBounds) if count < 2: return @@ -4997,7 +4999,7 @@ def getClassBoundsFormatted(self) -> "tuple[list[str], list[float]]": def getWeeklyScheduleData( self, currentWeekOnly: bool = False, - ) -> "list[list[list[dict[str, Any]]]]": + ) -> list[list[list[dict[str, Any]]]]: """ returns `data` as a nested list that: data[weekDay][classIndex] = WeeklyScheduleItem(name, weekNumMode) @@ -5056,7 +5058,7 @@ def getWeeklyScheduleData( return data - def setCourses(self, courses: "list[tuple[int, str, int]]") -> None: + def setCourses(self, courses: list[tuple[int, str, int]]) -> None: """ courses[index] == ( courseId: int, @@ -5106,13 +5108,13 @@ def setDefaults(self) -> None: # log.info(f"getNewCourseID: {self.lastCourseId=}") # return self.lastCourseId - def copyFrom(self, other: "EventGroup") -> None: + def copyFrom(self, other: EventGroup) -> None: EventGroup.copyFrom(self, other) if other.name == self.name: self.classesEndDate = other.classesEndDate[:] self.classTimeBounds = other.classTimeBounds[:] - def getData(self) -> "dict[str, Any]": + def getData(self) -> dict[str, Any]: data = EventGroup.getData(self) data.update( { @@ -5122,7 +5124,7 @@ def getData(self) -> "dict[str, Any]": ) return data - def setData(self, data: "dict[str, Any]") -> None: + def setData(self, data: dict[str, Any]) -> None: EventGroup.setData(self, data) # self.setCourses(data["courses"]) if "classesEndDate" in data: @@ -5152,7 +5154,7 @@ class LifetimeGroup(EventGroup): sortBys = EventGroup.sortBys + (("start", _("Start"), True),) params = EventGroup.params + ("showSeparateYmdInputs",) - def getSortByValue(self, event: "Event", attr: str) -> "Any": + def getSortByValue(self, event: Event, attr: str) -> Any: if event.name in self.acceptsEventTypes: if attr == "start": return event.getStartJd() @@ -5160,11 +5162,11 @@ def getSortByValue(self, event: "Event", attr: str) -> "Any": return event.getEndJd() return EventGroup.getSortByValue(self, event, attr) - def __init__(self, _id: "int | None" = None) -> None: + def __init__(self, _id: int | None = None) -> None: self.showSeparateYmdInputs = False EventGroup.__init__(self, _id) - def setData(self, data: "dict[str, Any]") -> None: + def setData(self, data: dict[str, Any]) -> None: if "showSeperatedYmdInputs" in data: # misspell in < 3.1.x data["showSeparateYmdInputs"] = data["showSeperatedYmdInputs"] @@ -5191,7 +5193,7 @@ class LargeScaleGroup(EventGroup): ) sortByDefault = "start" - def getSortByValue(self, event: "Event", attr: str) -> "Any": + def getSortByValue(self, event: Event, attr: str) -> Any: if event.name in self.acceptsEventTypes: if attr == "start": return event.start * event.scale @@ -5199,7 +5201,7 @@ def getSortByValue(self, event: "Event", attr: str) -> "Any": return event.getEnd() * event.scale return EventGroup.getSortByValue(self, event, attr) - def __init__(self, _id: "int | None" = None) -> None: + def __init__(self, _id: int | None = None) -> None: self.scale = 1 # 1, 1000, 1000**2, 1000**3 EventGroup.__init__(self, _id) @@ -5217,12 +5219,12 @@ def copyFrom(self, other: EventGroup) -> None: if other.name == self.name: self.scale = other.scale - def getData(self) -> "dict[str, Any]": + def getData(self) -> dict[str, Any]: data = EventGroup.getData(self) data["scale"] = self.scale return data - def setData(self, data: "dict[str, Any]") -> None: + def setData(self, data: dict[str, Any]) -> None: EventGroup.setData(self, data) with suppress(KeyError): self.scale = data["scale"] @@ -5264,7 +5266,7 @@ class VcsEpochBaseEvent(Event): # FIXME @classmethod - def load(cls, fs: FileSystem, *args) -> "type": + def load(cls, fs: FileSystem, *args) -> type: pass def __bool__(self) -> bool: @@ -5300,7 +5302,7 @@ class VcsCommitEvent(VcsEpochBaseEvent): "shortHash", ) - def __init__(self, parent: "EventContainer", _id: str) -> None: + def __init__(self, parent: EventContainer, _id: str) -> None: Event.__init__(self, parent=parent) self.id = _id # commit full hash # --- @@ -5317,7 +5319,7 @@ class VcsTagEvent(VcsEpochBaseEvent): desc = _("VCS Tag") params = VcsEpochBaseEvent.params + () - def __init__(self, parent: "EventContainer", _id: str) -> None: + def __init__(self, parent: EventContainer, _id: str) -> None: Event.__init__(self, parent=parent) self.id = _id # tag name self.epoch = None @@ -5332,7 +5334,7 @@ class VcsBaseEventGroup(EventGroup): "vcsBranch", ) - def __init__(self, _id: "str | None" = None) -> None: + def __init__(self, _id: str | None = None) -> None: self.vcsType = "git" self.vcsDir = "" self.vcsBranch = "main" @@ -5361,13 +5363,13 @@ def getRulesHash(self) -> int: ), ) # FIXME - def __getitem__(self, key: str) -> "Event": + def __getitem__(self, key: str) -> Event: if key in classes.rule.names: return EventGroup.__getitem__(self, key) # len(commit_id)==40 for git return self.getEvent(key) - def getVcsModule(self) -> "Any": + def getVcsModule(self) -> Any: name = toStr(self.vcsType) # if not isinstance(name, str): # raise TypeError(f"getVcsModule({name!r}): bad type {type(name)}") @@ -5394,7 +5396,7 @@ def afterModify(self) -> None: self.updateVcsModuleObj() EventGroup.afterModify(self) - def setData(self, data: "dict[str, Any]") -> None: + def setData(self, data: dict[str, Any]) -> None: EventGroup.setData(self, data) self.updateVcsModuleObj() @@ -5403,7 +5405,7 @@ class VcsEpochBaseEventGroup(VcsBaseEventGroup): myParams = VcsBaseEventGroup.myParams + ("showSeconds",) canConvertTo = VcsBaseEventGroup.canConvertTo + ("taskList",) - def __init__(self, _id: "str | None" = None) -> None: + def __init__(self, _id: str | None = None) -> None: self.showSeconds = True self.vcsIds = [] VcsBaseEventGroup.__init__(self, _id) @@ -5429,7 +5431,7 @@ def getRulesHash(self) -> int: ), ) - def deepConvertTo(self, newGroupType: str) -> "EventGroup": + def deepConvertTo(self, newGroupType: str) -> EventGroup: newGroup = self.copyAs(newGroupType) if newGroupType == "taskList": newEventType = "task" @@ -5459,7 +5461,7 @@ class VcsCommitEventGroup(VcsEpochBaseEventGroup): params = EventGroup.params + myParams paramsOrder = EventGroup.paramsOrder + myParams - def __init__(self, _id: "str | None" = None) -> None: + def __init__(self, _id: str | None = None) -> None: VcsEpochBaseEventGroup.__init__(self, _id) self.showAuthor = True self.showShortHash = True @@ -5495,7 +5497,7 @@ def updateOccurrence(self) -> None: # --- self.updateOccurrenceLog(perf_counter() - stm0) - def updateEventDesc(self, event: "Event") -> None: + def updateEventDesc(self, event: Event) -> None: mod = self.getVcsModule() if mod is None: log.info(f"VCS module {self.vcsType!r} not found") @@ -5514,7 +5516,7 @@ def updateEventDesc(self, event: "Event") -> None: event.description = "\n".join(lines) # TODO: cache commit data - def getEvent(self, commit_id: str) -> "Event": + def getEvent(self, commit_id: str) -> Event: mod = self.getVcsModule() if mod is None: log.info(f"VCS module {self.vcsType!r} not found") @@ -5538,7 +5540,7 @@ class VcsTagEventGroup(VcsEpochBaseEventGroup): params = EventGroup.params + myParams paramsOrder = EventGroup.paramsOrder + myParams - def __init__(self, _id: "str | None" = None) -> None: + def __init__(self, _id: str | None = None) -> None: VcsEpochBaseEventGroup.__init__(self, _id) self.showStat = True @@ -5569,7 +5571,7 @@ def updateOccurrence(self) -> None: # --- self.updateOccurrenceLog(perf_counter() - stm0) - def updateEventDesc(self, event: "Event") -> None: + def updateEventDesc(self, event: Event) -> None: mod = self.getVcsModule() if mod is None: log.info(f"VCS module {self.vcsType!r} not found") @@ -5588,7 +5590,7 @@ def updateEventDesc(self, event: "Event") -> None: event.description = "\n".join(lines) # TODO: cache commit data - def getEvent(self, tag: str) -> "Event": + def getEvent(self, tag: str) -> Event: tag = toStr(tag) if tag not in self.vcsIds: raise ValueError(f"No tag {tag!r}") @@ -5615,7 +5617,7 @@ def load(cls, fs: FileSystem, *args): # FIXME def __bool__(self) -> bool: return True - def __init__(self, parent: "EventContainer", jd: int) -> None: + def __init__(self, parent: EventContainer, jd: int) -> None: Event.__init__(self, parent=parent) self.id = jd # ID is Julian Day @@ -5643,7 +5645,7 @@ class VcsDailyStatEventGroup(VcsBaseEventGroup): params = EventGroup.params + myParams paramsOrder = EventGroup.paramsOrder + myParams - def __init__(self, _id: "str | None" = None) -> None: + def __init__(self, _id: str | None = None) -> None: VcsBaseEventGroup.__init__(self, _id) self.statByJd = {} @@ -5704,7 +5706,7 @@ def updateOccurrence(self) -> None: # --- self.updateOccurrenceLog(perf_counter() - stm0) - def getEvent(self, jd: int) -> "Event": + def getEvent(self, jd: int) -> Event: # cache commit data FIXME from scal3.vcs_modules import encodeShortStat @@ -5741,7 +5743,7 @@ class JsonObjectsHolder(JsonEventObj): # Only use to keep groups and accounts, but not events skipLoadNoFile = True - def __init__(self, _id: "int | None" = None) -> None: + def __init__(self, _id: int | None = None) -> None: self.fs = None self.clear() @@ -5749,7 +5751,7 @@ def clear(self) -> None: self.byId = {} self.idList = [] - def __iter__(self) -> "Iterator[Any]": + def __iter__(self) -> Iterator[Any]: for _id in self.idList: yield self.byId[_id] @@ -5759,32 +5761,32 @@ def __len__(self) -> int: def __bool__(self) -> bool: return bool(self.idList) - def index(self, _id: int) -> "Any": + def index(self, _id: int) -> Any: return self.idList.index(_id) # or get object instead of obj_id? FIXME - def __getitem__(self, _id: int) -> "Any": + def __getitem__(self, _id: int) -> Any: return self.byId.__getitem__(_id) - def byIndex(self, index: int) -> "Any": + def byIndex(self, index: int) -> Any: return self.byId[self.idList[index]] - def __setitem__(self, _id: int, obj: "Any") -> None: + def __setitem__(self, _id: int, obj: Any) -> None: return self.byId.__setitem__(_id, obj) - def insert(self, index: int, obj: "Any") -> None: + def insert(self, index: int, obj: Any) -> None: if obj.id in self.idList: raise ValueError(f"{self} already contains id={obj.id}, {obj=}") self.byId[obj.id] = obj self.idList.insert(index, obj.id) - def append(self, obj: "Any") -> None: + def append(self, obj: Any) -> None: if obj.id in self.idList: raise ValueError(f"{self} already contains id={obj.id}, {obj=}") self.byId[obj.id] = obj self.idList.append(obj.id) - def delete(self, obj: "Any") -> None: + def delete(self, obj: Any) -> None: if obj.id not in self.idList: raise ValueError(f"{self} does not contains id={obj.id}, {obj=}") try: @@ -5803,13 +5805,13 @@ def delete(self, obj: "Any") -> None: if obj.id in self.idByUuid: del self.idByUuid[obj.id] - def pop(self, index: int) -> "Any": + def pop(self, index: int) -> Any: return self.byId.pop(self.idList.pop(index)) - def moveUp(self, index: int) -> "Any": + def moveUp(self, index: int) -> Any: return self.idList.insert(index - 1, self.idList.pop(index)) - def moveDown(self, index: int) -> "Any": + def moveDown(self, index: int) -> Any: return self.idList.insert(index + 1, self.idList.pop(index)) def setData(self, data: list[int]) -> None: @@ -5839,7 +5841,7 @@ class EventGroupsHolder(JsonObjectsHolder): file = join("event", "group_list.json") childName = "group" - def __init__(self, _id: "int | None" = None) -> None: + def __init__(self, _id: int | None = None) -> None: JsonObjectsHolder.__init__(self) self.id = None self.parent = None @@ -5855,7 +5857,7 @@ def delete(self, obj: EventGroup) -> None: obj.parent = None JsonObjectsHolder.delete(self, obj) - def setData(self, data: "list[Any]") -> None: + def setData(self, data: list[Any]) -> None: self.clear() if data: JsonObjectsHolder.setData(self, data) @@ -5888,7 +5890,7 @@ def getEnableIds(self) -> list[int]: def moveToTrash( self, group: EventGroup, - trash: "EventTrash", + trash: EventTrash, ) -> None: if trash.addEventsToBeginning: trash.idList = group.idList + trash.idList @@ -5912,7 +5914,7 @@ def convertGroupTo( return newGroup # and then never use old `group` object - def exportData(self, gidList: list[int]) -> "dict[str, Any]": + def exportData(self, gidList: list[int]) -> dict[str, Any]: data = OrderedDict( [ ( @@ -5935,7 +5937,7 @@ def eventListExportData( self, idsList: list[tuple[int, int]], groupTitle: str = "", - ) -> "dict[str, Any]": + ) -> dict[str, Any]: eventsData = [] for groupId, eventId in idsList: event = self.byId[groupId][eventId] @@ -5977,7 +5979,7 @@ def eventListExportData( ], ) - def importData(self, data: "dict[str, Any]") -> "EventGroupsImportResult": + def importData(self, data: dict[str, Any]) -> EventGroupsImportResult: res = EventGroupsImportResult() for gdata in data["groups"]: guuid = gdata.get("uuid") @@ -6014,7 +6016,7 @@ def exportToIcs(self, fpath: str, gidList: list[int]) -> None: fp.write("END:VCALENDAR\n") fp.close() - def checkForOrphans(self) -> "EventGroup | None": + def checkForOrphans(self) -> EventGroup | None: fs = self.fs newGroup = EventGroup() newGroup.fs = fs @@ -6083,14 +6085,14 @@ class EventAccountsHolder(JsonObjectsHolder): file = join("event", "account_list.json") childName = "account" - def __init__(self, _id: "int | None" = None) -> None: + def __init__(self, _id: int | None = None) -> None: JsonObjectsHolder.__init__(self) self.id = None self.parent = None self.idByUuid = {} @staticmethod - def loadClass(name: str) -> "type": + def loadClass(name: str) -> type: cls = classes.account.byName.get(name) if cls is not None: return cls @@ -6107,7 +6109,7 @@ def loadClass(name: str) -> "type": ) return None - def loadData(self, _id: int) -> "dict[str, Any]": + def loadData(self, _id: int) -> dict[str, Any]: objFile = join(accountsDir, f"{_id}.json") if not self.fs.isfile(objFile): log.error( @@ -6127,7 +6129,7 @@ def loadData(self, _id: int) -> "dict[str, Any]": return data # FIXME: types - def getLoadedObj(self, obj: "DummyAccount") -> "Account": + def getLoadedObj(self, obj: DummyAccount) -> Account: _id = obj.id data = self.loadData(_id) name = data["type"] @@ -6140,7 +6142,7 @@ def getLoadedObj(self, obj: "DummyAccount") -> "Account": obj.setData(data) return obj - def replaceDummyObj(self, obj: "DummyAccount") -> "Account": + def replaceDummyObj(self, obj: DummyAccount) -> Account: _id = obj.id obj = self.getLoadedObj(obj) self.byId[_id] = obj @@ -6411,7 +6413,7 @@ def getWeekOccurrenceData(curAbsWeekNumber, groups, tfmt="HM$"): endJd = startJd + 7 data = [] - def add(group: "EventGroup", event: "Event", eData: "dict"): + def add(group: EventGroup, event: Event, eData: dict): eData["show"] = ( group.showInDCal, group.showInWCal, diff --git a/scal3/graph_utils.py b/scal3/graph_utils.py index 1a966fda9..69f42a0dc 100644 --- a/scal3/graph_utils.py +++ b/scal3/graph_utils.py @@ -1,7 +1,11 @@ -from collections.abc import Callable -from typing import Any +from __future__ import annotations -from igraph import Graph +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from collections.abc import Callable + + from igraph import Graph def colorGraph(g: Graph, vertexSortKey: Callable[[int], [Any]]): diff --git a/scal3/ics.py b/scal3/ics.py index 6e2b4ec9d..dbff2dc99 100644 --- a/scal3/ics.py +++ b/scal3/ics.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -113,7 +115,7 @@ def splitIcsValue(value: str) -> list[str]: def convertHolidayPlugToIcs( - plug: "PluginType", + plug: PluginType, startJd: int, endJd: int, namePostfix: str = "", @@ -124,7 +126,7 @@ def convertHolidayPlugToIcs( def convertBuiltinTextPlugToIcs( - plug: "PluginType", + plug: PluginType, startJd: int, endJd: int, namePostfix: str = "", diff --git a/scal3/import_config_2to3.py b/scal3/import_config_2to3.py index b884f369b..addccd289 100755 --- a/scal3/import_config_2to3.py +++ b/scal3/import_config_2to3.py @@ -18,6 +18,7 @@ # no logging in this file +from __future__ import annotations import json import logging import os diff --git a/scal3/locale_man.py b/scal3/locale_man.py index c448e57a4..290fa9550 100644 --- a/scal3/locale_man.py +++ b/scal3/locale_man.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -22,11 +24,11 @@ if typing.TYPE_CHECKING: import subprocess + from collections.abc import Callable import gettext import os import string -from collections.abc import Callable from contextlib import suppress from os.path import ( isabs, @@ -140,7 +142,7 @@ def getLangDigits( # ---------------------------------------------------------- -def tr(s: "str | int", *a, **ka) -> str: +def tr(s: str | int, *a, **ka) -> str: """String translator function.""" return numEncode(s, *a, **ka) if isinstance(s, int) else str(s) @@ -256,7 +258,7 @@ def setData(self, data: dict): langDict.sort("name") -def popen_output(cmd: "list[str] | str") -> str: +def popen_output(cmd: list[str] | str) -> str: import subprocess return subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0] # noqa: S603 @@ -346,7 +348,7 @@ def rtlSgn() -> int: def getMonthName( calType: int, month: int, - year: "int | None" = None, + year: int | None = None, abbreviate: bool = False, ) -> str: module, ok = calTypes[calType] @@ -393,7 +395,7 @@ def getAvailableDigitKeys() -> set[str]: def numEncode( num: int, - localeMode: "str | int | None" = None, + localeMode: str | int | None = None, fillZero: int = 0, negEnd: bool = False, ) -> str: @@ -434,7 +436,7 @@ def numEncode( def textNumEncode( st: str, - localeMode: "str | int | None" = None, + localeMode: str | int | None = None, changeSpecialChars: bool = True, changeDot: bool = False, ) -> str: @@ -475,7 +477,7 @@ def textNumEncode( def floatEncode( st: str, - localeMode: "str | int | None" = None, + localeMode: str | int | None = None, ): return textNumEncode( st, @@ -556,7 +558,7 @@ def addLRM(text: str) -> str: return LRM + toStr(text) -def popenDefaultLang(*args, **kwargs) -> "subprocess.Popen": +def popenDefaultLang(*args, **kwargs) -> subprocess.Popen: from subprocess import Popen os.environ["LANG"] = sysLangDefault diff --git a/scal3/plugin_type.py b/scal3/plugin_type.py index 0608aed8d..390179c19 100644 --- a/scal3/plugin_type.py +++ b/scal3/plugin_type.py @@ -1,14 +1,16 @@ +from __future__ import annotations + import typing from scal3.s_object import SObj class BasePlugin(SObj): - name: "str | None" + name: str | None external: bool loaded: bool - params: "typing.Sequence[str]" - essentialParams: "typing.Sequence[str]" + params: typing.Sequence[str] + essentialParams: typing.Sequence[str] def getArgs(self): ... diff --git a/scal3/time_utils.py b/scal3/time_utils.py index 73461e34a..1e9293e8c 100644 --- a/scal3/time_utils.py +++ b/scal3/time_utils.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -30,7 +32,7 @@ # getEpochFromJd(gregorian.to_jd(10000, 1, 1)) G10000_epoch = 253402300800 -TZ: "typing.TypeAlias" = "mytz.TimeZone | None" +TZ: typing.TypeAlias = "mytz.TimeZone | None" # jd is the integer value of Chreonological Julian Day, # which is specific to time zone @@ -68,7 +70,7 @@ def __init__(self, h=0, m=0, s=0): self.m = m self.s = s - def tuple(self) -> "tuple[int, int, int]": + def tuple(self) -> tuple[int, int, int]: return (self.h, self.m, self.s) def __format__(self, fmt=""): @@ -215,7 +217,7 @@ def getJdAndSecondsFromEpoch(epoch: int) -> tuple[int, int]: return (days + J1970, second) -durationUnitsRel: "list[tuple[int, str]]" = ( +durationUnitsRel: list[tuple[int, str]] = ( (1, "second"), (60, "minute"), (60, "hour"), @@ -223,25 +225,25 @@ def getJdAndSecondsFromEpoch(epoch: int) -> tuple[int, int]: (7, "week"), ) -durationUnitsAbs: "list[tuple[int, str]]" = [] +durationUnitsAbs: list[tuple[int, str]] = [] num = 1 for item in durationUnitsRel: num *= item[0] durationUnitsAbs.append((num, item[1])) -durationUnitValueToName: "dict[int, str]" = dict(durationUnitsAbs) -durationUnitValues: "list[int]" = [item[0] for item in durationUnitsAbs] +durationUnitValueToName: dict[int, str] = dict(durationUnitsAbs) +durationUnitValues: list[int] = [item[0] for item in durationUnitsAbs] # durationUnitNames: "list[str]" = [item[1] for item in durationUnitsAbs] def timeEncode( - tm: "tuple[int, int, int] | tuple[int, int]", + tm: tuple[int, int, int] | tuple[int, int], ) -> str: return f"{HMS(*tm)}" def simpleTimeEncode( - tm: "tuple[int, int, int] | tuple[int, int] | tuple[int]", + tm: tuple[int, int, int] | tuple[int, int] | tuple[int], ) -> str: # FIXME: how to extend HMS formatting to include this conditioning? # need a new symbol for "minute, omit if zero", like "$" for second @@ -294,7 +296,7 @@ def encodeJd(jd: int) -> str: return epochGregDateTimeEncode(getEpochFromJd(jd)) -def durationEncode(value: "int | float", unit: int) -> str: +def durationEncode(value: float, unit: int) -> str: iValue = int(value) if iValue == value: value = iValue diff --git a/scal3/ui.py b/scal3/ui.py index fcf9a43fc..48f003492 100644 --- a/scal3/ui.py +++ b/scal3/ui.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -22,7 +24,6 @@ import os.path import typing from collections import OrderedDict -from collections.abc import Callable from contextlib import suppress from dataclasses import dataclass from os.path import isabs, isdir, isfile, join @@ -50,6 +51,8 @@ from scal3.types_starcal import CellType, CompiledTimeFormat if typing.TYPE_CHECKING: + from collections.abc import Callable + from scal3.plugin_type import PluginType from scal3.s_object import SObj @@ -239,12 +242,12 @@ @dataclass(slots=True) class Font: - family: "str | None" + family: str | None bold: bool = False italic: bool = False size: float = 0 - def fromList(lst: "list | None"): + def fromList(lst: list | None): if lst is None: return return Font(*lst) @@ -312,7 +315,7 @@ def saveLiveConfLoop() -> None: # rename to saveConfLiveLoop FIXME # ------------------------------------------------------- -def parseDroppedDate(text) -> "tuple[int, int, int] | None": +def parseDroppedDate(text) -> tuple[int, int, int] | None: part = text.split("/") if len(part) != 3: return None @@ -346,7 +349,7 @@ def parseDroppedDate(text) -> "tuple[int, int, int] | None": ) # "format" must be list because we use method "index" - def formatIsValid(fmt: "list[int]"): + def formatIsValid(fmt: list[int]): for i in range(3): f = fmt[i] if not (minMax[f][0] <= part[i] <= minMax[f][1]): @@ -445,7 +448,7 @@ def __init__(self, jd: int): self.getEventsData() @property - def date(self) -> "tuple[int, int, int]": + def date(self) -> tuple[int, int, int]: return (self.year, self.month, self.day) def addPluginText(self, plug, text): @@ -455,7 +458,7 @@ def addPluginText(self, plug, text): def getPluginsData( self, firstLineOnly=False, - ) -> "list[tuple[PluginType, str]]": + ) -> list[tuple[PluginType, str]]: return [ (plug, text.split("\n")[0]) if firstLineOnly else (plug, text) for (plug, text) in self._pluginsData @@ -499,8 +502,8 @@ def getEventsData(self): def format( self, compiledFmt: CompiledTimeFormat, - calType: "int | None" = None, - tm: "tuple[int, int, int] | None" = None, + calType: int | None = None, + tm: tuple[int, int, int] | None = None, ): if calType is None: calType = calTypes.primary @@ -574,7 +577,7 @@ def registerPlugin( self, name: str, setParamsCallable: Callable[[CellType], None], - getCellGroupCallable: "Callable[[CellCache, ...], list[CellType]]", + getCellGroupCallable: Callable[[CellCache, ...], list[CellType]], # ^ FIXME: ... # `...` is `absWeekNumber` for weekCal, and `year, month` for monthCal ): @@ -642,7 +645,7 @@ def changeDate( year: int, month: int, day: int, - calType: "int | None" = None, + calType: int | None = None, ) -> None: global cell if calType is None: @@ -683,7 +686,7 @@ def getFont( scale=1.0, family=True, bold=False, -) -> "tuple[str | None, bool, bool, float]": +) -> tuple[str | None, bool, bool, float]: f = fontCustom if fontCustomEnable else fontDefaultInit return Font( family=f.family if family else None, @@ -693,7 +696,7 @@ def getFont( ) -def getParamsFont(params: dict) -> "Font | None": +def getParamsFont(params: dict) -> Font | None: font = params.get("font") if not font: return None @@ -704,7 +707,7 @@ def getParamsFont(params: dict) -> "Font | None": return font -def initFonts(fontDefaultNew: "Font") -> None: +def initFonts(fontDefaultNew: Font) -> None: global fontDefault, fontCustom fontDefault = fontDefaultNew if not fontCustom: @@ -860,7 +863,7 @@ def init() -> None: todayCell = cell = cellCache.getTodayCell() # FIXME -def withFS(obj: "SObj") -> "SObj": +def withFS(obj: SObj) -> SObj: obj.fs = fs return obj @@ -1292,10 +1295,10 @@ def getEventTagsDict(): eventTagsDesc = {t.name: t.desc for t in eventTags} # ------------------- -fs: "event_lib.FileSystem | None" = None -eventAccounts: "list[event_lib.EventAccount]" = [] -eventGroups: "list[event_lib.EventGroup]" = [] -eventTrash: "event_lib.EventTrash | None" = None +fs: event_lib.FileSystem | None = None +eventAccounts: list[event_lib.EventAccount] = [] +eventGroups: list[event_lib.EventGroup] = [] +eventTrash: event_lib.EventTrash | None = None eventNotif: EventNotificationManager | None = None @@ -1760,7 +1763,7 @@ def updateFocusTime(*_args): saveConf() -def evalParam(param: str) -> "Any": +def evalParam(param: str) -> Any: parts = param.split(".") if not parts: raise ValueError(f"invalid {param = }") diff --git a/scal3/ui_gtk/button_drawing.py b/scal3/ui_gtk/button_drawing.py index d60bdaab6..4eabd6e3b 100644 --- a/scal3/ui_gtk/button_drawing.py +++ b/scal3/ui_gtk/button_drawing.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from os.path import join from typing import TYPE_CHECKING @@ -125,7 +127,7 @@ def getImagePath(self) -> None: def draw( self, - cr: "cairo.Context", + cr: cairo.Context, w: float, h: float, ): diff --git a/scal3/ui_gtk/customize.py b/scal3/ui_gtk/customize.py index 850c91ee9..34594011d 100644 --- a/scal3/ui_gtk/customize.py +++ b/scal3/ui_gtk/customize.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -74,10 +76,10 @@ def getLoadedObj(self) -> ud.BaseCalObj: def updateVars(self) -> None: pass - def getOptionsWidget(self) -> "gtk.Widget | None": # noqa: PLR6301 + def getOptionsWidget(self) -> gtk.Widget | None: # noqa: PLR6301 return None - def getSubPages(self) -> "list[StackPage]": # noqa: PLR6301 + def getSubPages(self) -> list[StackPage]: # noqa: PLR6301 return [] def showHide(self) -> None: # noqa: PLR6301 @@ -125,7 +127,7 @@ def onKeyPress(self, arg: gtk.Widget, gevent: gdk.EventKey): def getOptionsWidget(self) -> gtk.Widget: # noqa: PLR6301 return None - def getSubPages(self) -> "list[StackPage]": # noqa: PLR6301 + def getSubPages(self) -> list[StackPage]: # noqa: PLR6301 return [] @@ -160,7 +162,7 @@ def insertItemWidget(self, _i): def newSubPageButton( item: CustomizableCalObj, - page: "StackPage", + page: StackPage, vertical: bool = False, borderWidth: int = 10, spacing: int = 10, diff --git a/scal3/ui_gtk/day_cal.py b/scal3/ui_gtk/day_cal.py index 0c2d63f44..d1d94b161 100644 --- a/scal3/ui_gtk/day_cal.py +++ b/scal3/ui_gtk/day_cal.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -86,7 +88,7 @@ class DayCal(gtk.DrawingArea, CalBase): seasonPieEnableParam = "" seasonPieGeoParam = "" - seasonPieColorsParam: "dict | None" = None + seasonPieColorsParam: dict | None = None seasonPieTextColorParam = "" myKeys = CalBase.myKeys + ( @@ -685,7 +687,7 @@ def drawAll(self, _widget=None, cr=None, cursor=True): def drawEventIcons( self, - cr: "cairo.Context", + cr: cairo.Context, c: ui.Cell, w: int, h: int, @@ -724,7 +726,7 @@ def drawEventIcons( cr.fill() @staticmethod - def getMonthName(c: "ui.Cell", calType: int, params: "dict[str, Any]"): + def getMonthName(c: ui.Cell, calType: int, params: dict[str, Any]): month = c.dates[calType][1] # type: int abbreviate = params.get("abbreviate", False) uppercase = params.get("uppercase", False) @@ -819,7 +821,7 @@ def drawSeasonPie(self, cr, w, h): cr.move_to(xc - font_w / 2, yc - font_h / 2) show_layout(cr, layout) - def drawWithContext(self, cr: "cairo.Context", _cursor: bool): + def drawWithContext(self, cr: cairo.Context, _cursor: bool): # gevent = gtk.get_current_event() w = self.get_allocation().width h = self.get_allocation().height diff --git a/scal3/ui_gtk/event/manager.py b/scal3/ui_gtk/event/manager.py index 3743e09f0..8354bc624 100644 --- a/scal3/ui_gtk/event/manager.py +++ b/scal3/ui_gtk/event/manager.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -85,7 +87,7 @@ # log.debug("Testing translator", __file__, _("About")) -EventOrGroup: "typing.TypeAlias" = "lib.Event | lib.EventGroup" +EventOrGroup: typing.TypeAlias = "lib.Event | lib.EventGroup" confPath = join(confDir, "event", "manager.json") @@ -194,7 +196,7 @@ def onConfigChange(self, *a, **kw) -> None: self.waitingDo(self.reloadEvents) # FIXME return - def onEventUpdate(self, record: "EventUpdateRecord") -> None: + def onEventUpdate(self, record: EventUpdateRecord) -> None: action = record.action if action == "r": # reload group or trash @@ -712,7 +714,7 @@ def multiSelectShiftUpDownPress(self, isDown: bool): def multiSelectShiftButtonPress( self, - path: "list[int]", + path: list[int], ) -> None: groupIndex, eventIndex = path # s_iter = self.treev.get_selection().get_selected()[1] @@ -751,7 +753,7 @@ def multiSelectTreeviewToggleSelected(self): def multiSelectTreeviewToggle( self, - _cell: "gtk.CellRendererToggle", + _cell: gtk.CellRendererToggle, pathStr: str, ): path = gtk.TreePath.new_from_string(pathStr).get_indices() @@ -797,7 +799,7 @@ def multiSelectCBSetGroup(self, groupIndex, eventIndex, active): return None return None - def multiSelectTreeviewTogglePath(self, path: "list[int]"): + def multiSelectTreeviewTogglePath(self, path: list[int]): model = self.treeModel if len(path) not in {1, 2}: raise RuntimeError(f"invalid path depth={len(path)}, {path=}") @@ -966,7 +968,7 @@ def multiSelectCancel(self, _obj=None): model.set_value(_iter, 0, False) self.multiSelectOperationFinished() - def multiSelectEventIdsDict(self) -> "dict[int, list[int]]": + def multiSelectEventIdsDict(self) -> dict[int, list[int]]: model = self.treeModel idsDict = odict() for groupIndex, eventIndexes in self.multiSelectPathDict.items(): @@ -977,7 +979,7 @@ def multiSelectEventIdsDict(self) -> "dict[int, list[int]]": ] return idsDict - def multiSelectEventIdsList(self) -> "list[tuple[int, int]]": + def multiSelectEventIdsList(self) -> list[tuple[int, int]]: model = self.treeModel idsList = [] for groupIndex, eventIndexes in self.multiSelectPathDict.items(): @@ -1005,7 +1007,7 @@ def multiSelectBulkEdit(self, _widget=None): def _do_multiSelectBulkEdit( self, dialog: gtk.Dialog, - container: "DummyEventContainer", + container: DummyEventContainer, ) -> None: dialog.doAction() dialog.destroy() @@ -1559,7 +1561,7 @@ def genRightClickMenu(self, path: list[int]) -> gtk.Menu: def openRightClickMenu( self, path: list[int], - etime: "int | None" = None, + etime: int | None = None, ) -> None: menu = self.genRightClickMenu(path) if not menu: @@ -1602,7 +1604,7 @@ def onKeyPress(self, _dialog, gevent: gdk.EventKey) -> bool: return False # return self.onTreeviewKeyPress(self.treev, gevent) - def menuKeyPressOnPath(self, path: "list[str]", gevent: "gdk.EventKey"): + def menuKeyPressOnPath(self, path: list[str], gevent: gdk.EventKey): treev = self.treev menu = self.genRightClickMenu(path) if not menu: @@ -1631,8 +1633,8 @@ def menuKeyPressOnPath(self, path: "list[str]", gevent: "gdk.EventKey"): def onTreeviewKeyPress( self, - _treev: "gtk.TreeView", - gevent: "gdk.EventKey", + _treev: gtk.TreeView, + gevent: gdk.EventKey, ) -> bool: # from scal3.time_utils import getGtkTimeFromEpoch # log.debug(gevent.time-getGtkTimeFromEpoch(now())) @@ -1694,7 +1696,7 @@ def _do_checkForOrphans(self) -> None: def onMenuBarOrphanClick(self, _menuItem: gtk.MenuItem) -> None: self.waitingDo(self._do_checkForOrphans) - def getSelectedPath(self) -> "list[int] | None": + def getSelectedPath(self) -> list[int] | None: _iter = self.treev.get_selection().get_selected()[1] if _iter is None: return @@ -1762,7 +1764,7 @@ def _do_showDescItemToggled(self) -> None: def showDescItemToggled(self, _menuItem: gtk.MenuItem) -> None: self.waitingDo(self._do_showDescItemToggled) - def treeviewCursorChangedPath(self, path: "list[int]") -> None: + def treeviewCursorChangedPath(self, path: list[int]) -> None: text = "" if len(path) == 1: group = self.getObjsByPath(path)[0] @@ -1844,7 +1846,7 @@ def setGroupEnable( self, enable: bool, group: lib.EventGroup, - path: "tuple[int] | None", + path: tuple[int] | None, ) -> bool: if path is None: groupIter = self.groupIterById[group.id] @@ -1891,8 +1893,8 @@ def onTreeviewLeftButtonPress( self, treev: gtk.TreeView, gevent: gdk.EventButton, - path: "list[int]", - col: "gtk.TreeViewColumn", + path: list[int], + col: gtk.TreeViewColumn, ) -> None: objs = self.getObjsByPath(path) @@ -1967,7 +1969,7 @@ def insertNewGroup(self, groupIndex: int) -> None: def addGroupBeforeGroup(self, _menu: gtk.Menu, path: list[int]) -> None: self.insertNewGroup(path[0]) - def addGroupBeforeSelection(self, _w: "gtk.Widget | None" = None) -> None: + def addGroupBeforeSelection(self, _w: gtk.Widget | None = None) -> None: path = self.getSelectedPath() if path is None: groupIndex = len(self.treeModel) - 1 @@ -2060,7 +2062,7 @@ def duplicateGroupWithEventsFromMenu( ) -> None: self.duplicateGroupWithEvents(path) - def duplicateSelectedObj(self, _w: "gtk.Widget | None" = None) -> None: + def duplicateSelectedObj(self, _w: gtk.Widget | None = None) -> None: path = self.getSelectedPath() if not path: return @@ -2237,7 +2239,7 @@ def moveEventToTrashByPath(self, path: list[int]) -> None: self.treeModel.remove(self.treeModel.get_iter(path)) self.addEventRowToTrash(event) - def addEventRowToTrash(self, event: "lib.Event") -> None: + def addEventRowToTrash(self, event: lib.Event) -> None: if ui.eventTrash.addEventsToBeginning: self.insertEventRow(self.trashIter, 0, event) else: @@ -2273,7 +2275,7 @@ def emptyTrash(self, _menuItem: gtk.MenuItem) -> None: self.removeIterChildren(self.trashIter) self.treeviewCursorChanged() - def editTrash(self, _menuItem: "gtk.MenuItem | None" = None) -> None: + def editTrash(self, _menuItem: gtk.MenuItem | None = None) -> None: TrashEditorDialog(transient_for=self).run() self.treeModel.set_value( self.trashIter, @@ -2532,7 +2534,7 @@ def pasteEventFromMenu( def _pasteEventToPath( self, - srcIter: "gtk.TreeIter", + srcIter: gtk.TreeIter, move: bool, targetPath: list[int], ): diff --git a/scal3/ui_gtk/event/occurrence_view.py b/scal3/ui_gtk/event/occurrence_view.py index c3d995aa4..6baae912e 100644 --- a/scal3/ui_gtk/event/occurrence_view.py +++ b/scal3/ui_gtk/event/occurrence_view.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -48,8 +50,8 @@ def __init__( self, eventSepParam: str = "", justificationParam: str = "", - fontParams: "tuple[str, str] | None" = None, - timeFontParams: "tuple[str, str] | None" = None, + fontParams: tuple[str, str] | None = None, + timeFontParams: tuple[str, str] | None = None, styleClass: str = "", wrapMode: pango.WrapMode = pango.WrapMode.WORD_CHAR, ): @@ -366,8 +368,8 @@ def addWriteEventMenuItems( self, menu, occurData: dict[str, Any], - event: "event_lib.Event", - group: "event_lib.EventGroup", + event: event_lib.Event, + group: event_lib.EventGroup, ): from scal3.ui_gtk.event.utils import menuItemFromEventGroup diff --git a/scal3/ui_gtk/event/search_events.py b/scal3/ui_gtk/event/search_events.py index b07d15b5f..76cbe8b32 100644 --- a/scal3/ui_gtk/event/search_events.py +++ b/scal3/ui_gtk/event/search_events.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from time import localtime from scal3 import logger @@ -471,8 +473,8 @@ def _do_search(self): @staticmethod def searchAndExportToJSON( - groupIds: "list[int]", - conds: "dict[str, Any]", + groupIds: list[int], + conds: dict[str, Any], fpath: str, # TODO: compact: bool, ): diff --git a/scal3/ui_gtk/gtk_ud.py b/scal3/ui_gtk/gtk_ud.py index 7f1a8fcf2..a8e0499d8 100644 --- a/scal3/ui_gtk/gtk_ud.py +++ b/scal3/ui_gtk/gtk_ud.py @@ -18,6 +18,8 @@ # ud = ui dependent # upper the "ui" module +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -28,9 +30,10 @@ from os.path import join if typing.TYPE_CHECKING: + from collections.abc import Callable + from scal3.event_update_queue import EventUpdateRecord -from collections.abc import Callable from gi.overrides.GObject import Object @@ -230,7 +233,7 @@ def updateIconSizes(self): pixcache.clear() self.lastAlphabetHeight = height - def onEventUpdate(self, _record: "EventUpdateRecord") -> None: + def onEventUpdate(self, _record: EventUpdateRecord) -> None: # ui.cellCache.clear() # causes crash, no idea why! ui.cellCache.clearEventsData() self.onDateChange() @@ -307,7 +310,7 @@ def getGtkDefaultFont(): return font -def _getLightness(c: "gdk.Color"): +def _getLightness(c: gdk.Color): maxValue = max(c.red, c.green, c.blue) if maxValue > 255: log.warning(f"_getLightness: bad color {c}") @@ -566,7 +569,7 @@ def getScreenSize(): return rect.width, rect.height -def getWorkAreaSize() -> "tuple[int, int] | None": +def getWorkAreaSize() -> tuple[int, int] | None: monitor = getMonitor() if monitor is None: return None diff --git a/scal3/ui_gtk/layout_utils.py b/scal3/ui_gtk/layout_utils.py index 585b0f85c..ee610f93d 100644 --- a/scal3/ui_gtk/layout_utils.py +++ b/scal3/ui_gtk/layout_utils.py @@ -1,5 +1,9 @@ -from collections.abc import Callable -from typing import Any +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from collections.abc import Callable def keeperCallable(obj: Any) -> Callable[[], Any]: diff --git a/scal3/ui_gtk/mainwin_items/monthCal.py b/scal3/ui_gtk/mainwin_items/monthCal.py index 5f4f64618..2ed3d68b9 100644 --- a/scal3/ui_gtk/mainwin_items/monthCal.py +++ b/scal3/ui_gtk/mainwin_items/monthCal.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -293,7 +295,7 @@ def drawAll(self, _widget=None, cursor=True): finally: win.end_draw_frame(dctx) - def drawWithContext(self, cr: "cairo.Context", cursor: bool): + def drawWithContext(self, cr: cairo.Context, cursor: bool): # gevent = gtk.get_current_event() # FIXME: must enhance (only draw few cells, not all cells) self.calcCoord() diff --git a/scal3/ui_gtk/menuitems.py b/scal3/ui_gtk/menuitems.py index 4f7a67a37..2e8735c2d 100644 --- a/scal3/ui_gtk/menuitems.py +++ b/scal3/ui_gtk/menuitems.py @@ -14,11 +14,12 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() -from collections.abc import Callable from typing import TYPE_CHECKING from scal3 import ui @@ -31,6 +32,8 @@ ) if TYPE_CHECKING: + from collections.abc import Callable + from gi.repository import GdkPixbuf """ @@ -51,10 +54,10 @@ def __init__( self, label: str = "", imageName: str = "", - pixbuf: "GdkPixbuf.Pixbuf | None" = None, + pixbuf: GdkPixbuf.Pixbuf | None = None, func: Callable | None = None, signalName="activate", - args: "tuple | None" = None, + args: tuple | None = None, ): gtk.MenuItem.__init__(self) if args is not None and not isinstance(args, tuple): diff --git a/scal3/ui_gtk/mywidgets/clock.py b/scal3/ui_gtk/mywidgets/clock.py index d14aded49..53b934a39 100644 --- a/scal3/ui_gtk/mywidgets/clock.py +++ b/scal3/ui_gtk/mywidgets/clock.py @@ -16,6 +16,8 @@ # Also avalable in /usr/share/common-licenses/LGPL on Debian systems # or /usr/share/licenses/common/LGPL/license.txt on ArchLinux +from __future__ import annotations + import time from time import localtime, strftime from typing import TYPE_CHECKING @@ -146,7 +148,7 @@ def onDraw(self, _widget=None, _event=None): finally: win.end_draw_frame(dctx) - def drawWithContext(self, cr: "cairo.Context"): + def drawWithContext(self, cr: cairo.Context): text = self.text fillColor(cr, ui.bgColor) setColor(cr, ui.textColor) diff --git a/scal3/ui_gtk/mywidgets/floatingMsg.py b/scal3/ui_gtk/mywidgets/floatingMsg.py index bbc0f1132..c88bddffc 100644 --- a/scal3/ui_gtk/mywidgets/floatingMsg.py +++ b/scal3/ui_gtk/mywidgets/floatingMsg.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from time import perf_counter from typing import TYPE_CHECKING @@ -137,7 +139,7 @@ def onExposeEvent(self, _widget, _gevent): finally: win.end_draw_frame(dctx) - def drawWithContext(self, cr: "cairo.Context"): + def drawWithContext(self, cr: cairo.Context): cr.rectangle(0, 0, screenWidth, self.height) setColor(cr, self.bgColor) cr.fill() @@ -203,7 +205,7 @@ def onExposeEvent(self, _widget, _gevent): finally: win.end_draw_frame(dctx) - def drawWithContext(self, cr: "cairo.Context"): + def drawWithContext(self, cr: cairo.Context): cr.rectangle(0, 0, self.width, self.height) setColor(cr, self.bgColor) cr.fill() diff --git a/scal3/ui_gtk/pref_utils.py b/scal3/ui_gtk/pref_utils.py index 78e062c61..73f0155ea 100644 --- a/scal3/ui_gtk/pref_utils.py +++ b/scal3/ui_gtk/pref_utils.py @@ -14,12 +14,13 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() import typing -from collections.abc import Callable from os.path import isabs, join from typing import Any @@ -39,7 +40,10 @@ set_tooltip, ) -ColorType: "typing.TypeAlias" = "tuple[int, int, int] | tuple[int, int, int, int]" +if typing.TYPE_CHECKING: + from collections.abc import Callable + +ColorType: typing.TypeAlias = "tuple[int, int, int] | tuple[int, int, int, int]" __all__ = [ "CheckColorPrefItem", @@ -208,9 +212,9 @@ def __init__( self, obj: Any, attrName: str, - items: "list[str] | None" = None, + items: list[str] | None = None, label: str = "", - labelSizeGroup: "gtk.SizeGroup | None" = None, + labelSizeGroup: gtk.SizeGroup | None = None, live: bool = False, onChangeFunc: Callable | None = None, ) -> None: @@ -258,7 +262,7 @@ def __init__( attrName: str, hasAuto: bool = False, label: str = "", - onChangeFunc: "Callable | None" = None, + onChangeFunc: Callable | None = None, ): self.obj = obj self.attrName = attrName @@ -297,13 +301,13 @@ def onFontButtonClick(self, _w: gtk.Widget) -> None: return self.fontRadio.set_active(True) - def get(self) -> "str | None": + def get(self) -> str | None: if self.hasAuto and self.autoRadio.get_active(): return None font = gfontDecode(self.fontButton.get_font_name()) return font.family - def set(self, value: "str | None") -> None: + def set(self, value: str | None) -> None: if value is None: if self.hasAuto: self.autoRadio.set_active(True) @@ -347,7 +351,7 @@ def __init__( self, obj: Any, attrName: str, - items: "list[str] | None" = None, + items: list[str] | None = None, ): """Items is a list of strings.""" self.obj = obj @@ -379,7 +383,7 @@ def __init__( self, obj: Any, attrName: str, - items: "list[tuple[str, str]] | None" = None, + items: list[tuple[str, str]] | None = None, ): """Items is a list of (imagePath, text) tuples.""" self.obj = obj @@ -443,7 +447,7 @@ def __init__( def get(self) -> ui.Font: return self._widget.get_font() - def set(self, value: "ui.Font | None") -> None: + def set(self, value: ui.Font | None) -> None: if value is None: return self._widget.set_font(value) @@ -460,7 +464,7 @@ def __init__( label: str = "", tooltip: str = "", live: bool = False, - onChangeFunc: "Callable | None" = None, + onChangeFunc: Callable | None = None, ) -> None: self.obj = obj self.attrName = attrName @@ -518,7 +522,7 @@ def __init__( attrName: str, useAlpha: bool = False, live: bool = False, - onChangeFunc: "Callable | None" = None, + onChangeFunc: Callable | None = None, ) -> None: from scal3.ui_gtk.mywidgets import MyColorButton @@ -543,7 +547,7 @@ def __init__( def get(self) -> ColorType: return self._widget.get_rgba() - def set(self, color: "ColorType | None") -> None: + def set(self, color: ColorType | None) -> None: if color is None: return self._widget.set_rgba(color) @@ -561,9 +565,9 @@ def __init__( self, checkItem: CheckPrefItem, colorItem: ColorPrefItem, - checkSizeGroup: "gtk.SizeGroup | None" = None, + checkSizeGroup: gtk.SizeGroup | None = None, live: bool = False, - onChangeFunc: "Callable | None" = None, + onChangeFunc: Callable | None = None, ) -> None: self._checkItem = checkItem self._colorItem = colorItem @@ -613,11 +617,11 @@ def __init__( self, checkItem: CheckPrefItem, fontItem: FontPrefItem, - checkSizeGroup: "gtk.SizeGroup | None" = None, + checkSizeGroup: gtk.SizeGroup | None = None, vertical: bool = False, spacing: int = 3, live: bool = False, - onChangeFunc: "Callable | None" = None, + onChangeFunc: Callable | None = None, ) -> None: self._checkItem = checkItem self._fontItem = fontItem @@ -666,15 +670,15 @@ def __init__( self, obj: Any, attrName: str, - _min: "int | float", - _max: "int | float", + _min: float, + _max: float, digits: int = 1, - step: "int | float" = 0, + step: float = 0, label: str = "", - labelSizeGroup: "gtk.SizeGroup | None" = None, + labelSizeGroup: gtk.SizeGroup | None = None, unitLabel: str = "", live: bool = False, - onChangeFunc: "Callable | None" = None, + onChangeFunc: Callable | None = None, ): self.obj = obj self.attrName = attrName @@ -706,10 +710,10 @@ def __init__( elif onChangeFunc is not None: raise ValueError("onChangeFunc is given without live=True") - def get(self) -> "int | float": + def get(self) -> float: return self._spinb.get_value() - def set(self, value: "int | float") -> None: + def set(self, value: float) -> None: self._spinb.set_value(value) # FIXME: updateWidget is triggering onChange func, can we avoid that? @@ -726,7 +730,7 @@ def __init__( attrName: str, label: str = "", live: bool = False, - onChangeFunc: "Callable | None" = None, + onChangeFunc: Callable | None = None, ): from scal3.ui_gtk.mywidgets import TextFrame @@ -768,7 +772,7 @@ def __init__( self, obj: Any, attrName: str, - _max: "int | float", + _max: float, ): _min = 0 self.obj = obj @@ -877,7 +881,7 @@ def __init__( attrName: str, label: str = "", live: bool = False, - onChangeFunc: "Callable | None" = None, + onChangeFunc: Callable | None = None, ) -> None: from scal3.ui_gtk.mywidgets.icon import IconSelectButton @@ -928,7 +932,7 @@ def __init__( obj: Any, attrName: str, texts: list[str], - label: "str | None" = None, + label: str | None = None, ) -> None: self.num = len(texts) self.obj = obj @@ -950,7 +954,7 @@ def __init__( r.join_group(first) pack(box, gtk.Label(), 1, 1) # FIXME - def get(self) -> "int | None": + def get(self) -> int | None: for i in range(self.num): if self.radios[i].get_active(): return i @@ -976,7 +980,7 @@ def __init__( vertical: bool, obj: Any, attrName: str, - items: "list[PrefItem] | None" = None, + items: list[PrefItem] | None = None, ) -> None: self.obj = obj self.attrName = attrName @@ -1019,7 +1023,7 @@ def __init__( self, obj: Any, attrName: str, - onChangeFunc: "Callable | None" = None, + onChangeFunc: Callable | None = None, ) -> None: from scal3.ui_gtk.mywidgets.direction_combo import DirectionComboBox @@ -1058,7 +1062,7 @@ def __init__( obj: Any, attrName: str, label: str = "", - onChangeFunc: "Callable | None" = None, + onChangeFunc: Callable | None = None, ) -> None: from scal3.ui_gtk.mywidgets.justification_combo import JustificationComboBox diff --git a/scal3/ui_gtk/pref_utils_extra.py b/scal3/ui_gtk/pref_utils_extra.py index 30be788ec..8fc5e6394 100644 --- a/scal3/ui_gtk/pref_utils_extra.py +++ b/scal3/ui_gtk/pref_utils_extra.py @@ -14,13 +14,14 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() -from collections.abc import Callable from contextlib import suppress -from typing import Any +from typing import TYPE_CHECKING, Any from scal3 import core, locale_man, startup from scal3.cal_types import calTypes @@ -36,6 +37,9 @@ set_tooltip, ) +if TYPE_CHECKING: + from collections.abc import Callable + __all__ = [ "AICalsPrefItem", "AICalsPrefItemToolbar", @@ -69,9 +73,9 @@ def __init__( obj: Any, ratioEnableVarName: str = "", fixedLabel: str = "", - fixedItem: "SpinPrefItem | None" = None, + fixedItem: SpinPrefItem | None = None, ratioLabel: str = "", - ratioItem: "SpinPrefItem | None" = None, + ratioItem: SpinPrefItem | None = None, vspacing: int = 0, hspacing: int = 0, borderWidth: int = 2, @@ -230,7 +234,7 @@ def __init__( obj: Any, attrName: str, live: bool = False, - onChangeFunc: "Callable | None" = None, + onChangeFunc: Callable | None = None, ) -> None: from scal3.ui_gtk.mywidgets.cal_type_combo import CalTypeCombo @@ -500,7 +504,7 @@ def __init__(self, parent): def getLeftRightAction(self): return self._leftRightAction - def setLeftRight(self, isRight: "bool | None") -> None: + def setLeftRight(self, isRight: bool | None) -> None: tb = self.leftRightItem if isRight is None: tb.setIconFile("") @@ -567,7 +571,7 @@ def __init__(self) -> None: def activeTreevFocus( self, _treev: gtk.TreeView, - _gevent: "gdk.EventFocus | None" = None, + _gevent: gdk.EventFocus | None = None, ) -> None: self.toolbar.setLeftRight(True) self.inactiveTreev.get_selection().unselect_all() @@ -575,12 +579,12 @@ def activeTreevFocus( def inactiveTreevFocus( self, _treev: gtk.TreeView, - _gevent: "gdk.EventFocus | None" = None, + _gevent: gdk.EventFocus | None = None, ) -> None: self.toolbar.setLeftRight(False) self.activeTreev.get_selection().unselect_all() - def onLeftRightClick(self, _obj: "gtk.Button | None" = None) -> None: + def onLeftRightClick(self, _obj: gtk.Button | None = None) -> None: action = self.toolbar.getLeftRightAction() if action == "activate": model, _iter = self.inactiveTreev.get_selection() @@ -592,7 +596,7 @@ def onLeftRightClick(self, _obj: "gtk.Button | None" = None) -> None: if _iter: self.inactivateIndex(model.get_path(_iter).get_indices()[0]) - def getCurrentTreeview(self) -> "gtk.TreeView | None": + def getCurrentTreeview(self) -> gtk.TreeView | None: action = self.toolbar.getLeftRightAction() if action == "inactivate": return self.activeTreev @@ -600,7 +604,7 @@ def getCurrentTreeview(self) -> "gtk.TreeView | None": return self.inactiveTreev return None - def onUpClick(self, _obj: "gtk.Button | None" = None) -> None: + def onUpClick(self, _obj: gtk.Button | None = None) -> None: treev = self.getCurrentTreeview() if not treev: return @@ -617,7 +621,7 @@ def onUpClick(self, _obj: "gtk.Button | None" = None) -> None: ) selection.select_path(gtk.TreePath.new_from_indices((i - 1,))) - def onDownClick(self, _obj: "gtk.Button | None" = None) -> None: + def onDownClick(self, _obj: gtk.Button | None = None) -> None: treev = self.getCurrentTreeview() if not treev: return diff --git a/scal3/ui_gtk/preferences.py b/scal3/ui_gtk/preferences.py index d4e24e618..8f2dfc67c 100644 --- a/scal3/ui_gtk/preferences.py +++ b/scal3/ui_gtk/preferences.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -1310,7 +1312,7 @@ def iterAllPrefItems(self): ) @staticmethod - def loadPlugin(plug: "PluginType", plugI: int) -> "PluginType": + def loadPlugin(plug: PluginType, plugI: int) -> PluginType: plug = plugin_man.loadPlugin(plug.file, enable=True) if plug: assert plug.loaded diff --git a/scal3/ui_gtk/starcal.py b/scal3/ui_gtk/starcal.py index bbb5b7eb3..e91901325 100755 --- a/scal3/ui_gtk/starcal.py +++ b/scal3/ui_gtk/starcal.py @@ -15,6 +15,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + import sys if sys.version_info[0] < 3: # noqa: UP036 @@ -602,7 +604,7 @@ def toggleWidthMaximized(self, _gevent): ui.winWidth = ww self.resize(ww, ui.winHeight) - def screenSizeChanged(self, rect: "gdk.Rectangle"): + def screenSizeChanged(self, rect: gdk.Rectangle): if ui.winMaximized: return winWidth = min(ui.winWidth, rect.width) @@ -726,7 +728,7 @@ def onDateChange(self, *a, **kw): # f"avg={ui.Cell.ocTimeSum/ui.Cell.ocTimeCount:e}" # ) - def getEventAddToMenuItem(self) -> "gtk.MenuItem | None": + def getEventAddToMenuItem(self) -> gtk.MenuItem | None: from scal3.ui_gtk.drawing import newColorCheckPixbuf if event_lib.allReadOnly: diff --git a/scal3/ui_gtk/timeline.py b/scal3/ui_gtk/timeline.py index 359385832..041ad2b8c 100644 --- a/scal3/ui_gtk/timeline.py +++ b/scal3/ui_gtk/timeline.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -514,7 +516,7 @@ def onExposeEvent(self, _widget=None, _event=None): finally: win.end_draw_frame(dctx) - def drawWithContext(self, cr: "cairo.Context"): + def drawWithContext(self, cr: cairo.Context): # t0 = perf_counter() if not self.boxEditing: self.updateData() @@ -524,7 +526,7 @@ def drawWithContext(self, cr: "cairo.Context"): # t2 = perf_counter() # log.debug(f"drawing time / data calc time: {(t2-t1)/(t1-t0):.2f}") - def getLastScrollDir(self) -> "str | None": + def getLastScrollDir(self) -> str | None: """Returns "up", "down" or "".""" if not self._lastScrollDir: return "" diff --git a/scal3/ui_gtk/toolbox.py b/scal3/ui_gtk/toolbox.py index b5bc5cc58..b042a8032 100644 --- a/scal3/ui_gtk/toolbox.py +++ b/scal3/ui_gtk/toolbox.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -64,13 +66,13 @@ def __init__( iconName: str = "", imageName: str = "", imageNameDynamic: bool = False, - onClick: "str | Callable | None" = None, + onClick: str | Callable | None = None, desc: str = "", shortDesc: str = "", enableTooltip: bool = True, continuousClick: bool = True, - onPress: "str | Callable | None" = None, - args: "tuple[Any] | None" = None, # for onClick and onPress + onPress: str | Callable | None = None, + args: tuple[Any] | None = None, # for onClick and onPress enable: bool = True, ) -> None: gtk.Button.__init__(self) @@ -199,13 +201,13 @@ class LabelToolBoxItem(BaseToolBoxItem): def __init__( self, name: str = "", - onClick: "str | Callable | None" = None, + onClick: str | Callable | None = None, desc: str = "", shortDesc: str = "", enableTooltip: bool = True, continuousClick: bool = True, - onPress: "str | Callable | None" = None, - args: "tuple[Any] | None" = None, # for onClick and onPress + onPress: str | Callable | None = None, + args: tuple[Any] | None = None, # for onClick and onPress ) -> None: gtk.Button.__init__(self) if continuousClick: @@ -361,7 +363,7 @@ def append(self, item: BaseToolBoxItem) -> BaseToolBoxItem: item.show() return item - def extend(self, items: "Iterable") -> None: + def extend(self, items: Iterable) -> None: for item in items: self.append(item) diff --git a/scal3/ui_gtk/year_wheel.py b/scal3/ui_gtk/year_wheel.py index ce0af29fe..e48028232 100644 --- a/scal3/ui_gtk/year_wheel.py +++ b/scal3/ui_gtk/year_wheel.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -154,7 +156,7 @@ def onDraw(self, _widget=None, _event=None): finally: win.end_draw_frame(dctx) - def drawWithContext(self, cr: "cairo.Context"): + def drawWithContext(self, cr: cairo.Context): width = float(self.get_allocation().width) height = float(self.get_allocation().height) dia = min(width, height) @@ -227,7 +229,7 @@ def drawWithContext(self, cr: "cairo.Context"): ) fillColor(cr, color) - def calcAngles(jd: int) -> "tuple[float, float]": + def calcAngles(jd: int) -> tuple[float, float]: angle = angle0 + 2 * pi * (jd - jd0) / yearLen # radians # angleD = angle * 180 / pi centerAngle = angle + avgDeltaAngle / 2 diff --git a/scal3/utils.py b/scal3/utils.py index 6e17226d1..1cb19c9af 100644 --- a/scal3/utils.py +++ b/scal3/utils.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see . +from __future__ import annotations + from scal3 import logger log = logger.get() @@ -24,7 +26,7 @@ from math import ceil, floor from typing import Any -Number: "typing.TypeAlias" = "int | float" +Number: typing.TypeAlias = "int | float" def ifloor(x: float) -> int: @@ -50,11 +52,11 @@ def arange( return ls -def toBytes(s: "bytes | str") -> bytes: +def toBytes(s: bytes | str) -> bytes: return s.encode("utf8") if isinstance(s, str) else bytes(s) -def toStr(s: "bytes | str") -> str: +def toStr(s: bytes | str) -> str: return str(s, "utf8") if isinstance(s, bytes) else str(s) @@ -105,7 +107,7 @@ class StrOrderedDict(dict): # and some looks like a list def __init__( self, - arg: "list | tuple | dict | None" = None, + arg: list | tuple | dict | None = None, reorderOnModify: bool = True, ) -> None: if arg is None: @@ -136,7 +138,7 @@ def items(self) -> list[tuple[str, Any]]: for key in self.keyList ] - def __getitem__(self, arg: "int | str | slice") -> Any: + def __getitem__(self, arg: int | str | slice) -> Any: if isinstance(arg, int): return dict.__getitem__(self, self.keyList[arg]) if isinstance(arg, str): @@ -152,7 +154,7 @@ def __getitem__(self, arg: "int | str | slice") -> Any: f"Bad type argument given to StrOrderedDict.__getitem__: {type(arg)}", ) - def __setitem__(self, arg: "int | str", value) -> None: + def __setitem__(self, arg: int | str, value) -> None: if isinstance(arg, int): dict.__setitem__(self, self.keyList[arg], value) elif isinstance(arg, str): @@ -173,7 +175,7 @@ def __setitem__(self, arg: "int | str", value) -> None: f": {type(arg)}", ) - def __delitem__(self, arg: "int | str | slice") -> None: + def __delitem__(self, arg: int | str | slice) -> None: if isinstance(arg, int): self.keyList.__delitem__(arg) dict.__delitem__(self, self.keyList[arg]) @@ -211,7 +213,7 @@ def insert(self, index: int, key: str, value: Any): self.keyList.insert(index, key) dict.__setitem__(self, key, value) # noqa: PLC2801 - def sort(self, attr: "str | None" = None) -> typing.Iterator: + def sort(self, attr: str | None = None) -> typing.Iterator: if attr is None: self.keyList.sort() else: @@ -243,10 +245,10 @@ class NullObj: def __setattr__(self, attr: str, value: Any) -> None: pass - def __getattr__(self, attr: str) -> "NullObj": + def __getattr__(self, attr: str) -> NullObj: return self - def __call__(self, *_a, **_kw) -> "NullObj": + def __call__(self, *_a, **_kw) -> NullObj: return self def __str__(self) -> str: @@ -335,7 +337,7 @@ def findWordByPos(text: str, pos: int) -> tuple[str, int]: def numRangesEncode( - values: "list[int | tuple[int, int] | list[int]]", + values: list[int | tuple[int, int] | list[int]], sep: str, ): parts = [] @@ -347,7 +349,7 @@ def numRangesEncode( return sep.join(parts) -def numRangesDecode(text: str) -> "list[int | tuple[int, int]]": +def numRangesDecode(text: str) -> list[int | tuple[int, int]]: values = [] for part in text.split(","): pparts = part.strip().split("-")