diff --git a/.pylintrc b/.pylintrc index 315428d..e336a72 100644 --- a/.pylintrc +++ b/.pylintrc @@ -26,7 +26,7 @@ extension-pkg-allow-list= # be loaded. Extensions are loading into the active Python interpreter and may # run arbitrary code. (This is an alternative name to extension-pkg-allow-list # for backward compatibility.) -extension-pkg-whitelist= +extension-pkg-whitelist=seccomp # Return non-zero exit code if any of these messages/categories are detected, # even if score is above --fail-under value. Syntax same as enable. Messages @@ -156,6 +156,7 @@ enable=F, # Fatal spelling, string, nonascii-checker, + typecheck, # Specific import checks: wildcard-import, # Specific refactoring checks: diff --git a/convo.py b/convo.py index 50e9ac7..8dabefb 100644 --- a/convo.py +++ b/convo.py @@ -14,7 +14,6 @@ except ImportError: from dataobjs import PesterHistory from parsetools import convertTags, lexMessage, mecmd, colorBegin, colorEnd, smiledict import parsetools -from pnc.dep.attrdict import AttrDict PchumLog = logging.getLogger("pchumLogger") @@ -33,33 +32,33 @@ class PesterTabWindow(QtWidgets.QFrame): self.tabs.tabCloseRequested[int].connect(self.tabClose) self.tabs.tabMoved[int, int].connect(self.tabMoved) - self.shortcuts = AttrDict() - self.shortcuts.tabNext = QShortcut( + self.shortcuts = {} + self.shortcuts["tabNext"] = QShortcut( QtGui.QKeySequence("Ctrl+j"), self, context=QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut, ) - self.shortcuts.tabLast = QShortcut( + self.shortcuts["tabLast"] = QShortcut( QtGui.QKeySequence("Ctrl+k"), self, context=QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut, ) # Note that we use reversed keys here. - self.shortcuts.tabUp = QShortcut( + self.shortcuts["tabUp"] = QShortcut( QtGui.QKeySequence("Ctrl+PgDown"), self, context=QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut, ) - self.shortcuts.tabDn = QShortcut( + self.shortcuts["tabDn"] = QShortcut( QtGui.QKeySequence("Ctrl+PgUp"), self, context=QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut, ) - self.shortcuts.tabNext.activated.connect(self.nudgeTabNext) - self.shortcuts.tabUp.activated.connect(self.nudgeTabNext) - self.shortcuts.tabLast.activated.connect(self.nudgeTabLast) - self.shortcuts.tabDn.activated.connect(self.nudgeTabLast) + self.shortcuts["tabNext"].activated.connect(self.nudgeTabNext) + self.shortcuts["tabUp"].activated.connect(self.nudgeTabNext) + self.shortcuts["tabLast"].activated.connect(self.nudgeTabLast) + self.shortcuts["tabDn"].activated.connect(self.nudgeTabLast) self.initTheme(self.mainwindow.theme) self.layout = QtWidgets.QVBoxLayout() @@ -544,7 +543,7 @@ class PesterText(QtWidgets.QTextEdit): window.chatlog.log(parent.chum.handle, lexmsg) else: if ( - (window.idler.auto or window.idler.manual) + (window.idler["auto"] or window.idler["manual"]) and parent.chumopen and not parent.isBot(chum.handle) ): @@ -675,7 +674,7 @@ class PesterInput(QtWidgets.QLineEdit): self.setText(prev) elif event.key() in [QtCore.Qt.Key.Key_PageUp, QtCore.Qt.Key.Key_PageDown]: self.parent().textArea.keyPressEvent(event) - self.parent().mainwindow.idler.time = 0 + self.parent().mainwindow.idler["time"] = 0 super().keyPressEvent(event) diff --git a/pesterchum.py b/pesterchum.py index 8740729..73543c6 100755 --- a/pesterchum.py +++ b/pesterchum.py @@ -23,7 +23,6 @@ if ostools.isLinux(): import libseccomp # import console -from pnc.dep.attrdict import AttrDict from user_profile import ( userConfig, userProfile, @@ -162,8 +161,8 @@ BOTNAMES.extend(SERVICES) # Save the main app. From here, we should be able to get everything else in # order, for console use. _CONSOLE = False -_CONSOLE_ENV = AttrDict() -_CONSOLE_ENV.PAPP = None +_CONSOLE_ENV = {} +_CONSOLE_ENV["PAPP"] = None # Python 3 QString = str # Command line arguments @@ -1313,7 +1312,7 @@ class PesterWindow(MovingWindow): ), ) # For debugging - _CONSOLE_ENV.PAPP = self + _CONSOLE_ENV["PAPP"] = self # TODO: karxi: SO! At the end of this function it seems like that # object is just made into None or.../something/. Somehow, it just # DIES, and I haven't the slightest idea why. I've tried multiple ways @@ -1332,7 +1331,7 @@ class PesterWindow(MovingWindow): self.memos = CaseInsensitiveDict() self.tabconvo = None self.tabmemo = None - self.shortcuts = AttrDict() + self.shortcuts = {} self.setAutoFillBackground(False) self.setObjectName("main") @@ -1637,26 +1636,24 @@ class PesterWindow(MovingWindow): self.waitingMessages = waitingMessageHolder(self) - self.idler = AttrDict( - dict( - # autoidle - auto=False, - # setidle - manual=False, - # idlethreshold - threshold=60 * self.config.idleTime(), - # idleaction - action=self.idleaction, - # idletimer - timer=QtCore.QTimer(self), - # idleposition - pos=QtGui.QCursor.pos(), - # idletime - time=0, - ) - ) - self.idler.timer.timeout.connect(self.checkIdle) - self.idler.timer.start(1000) + self.idler = { + # autoidle + "auto": False, + # setidle + "manual": False, + # idlethreshold + "threshold": 60 * self.config.idleTime(), + # idleaction + "action": self.idleaction, + # idletimer + "timer": QtCore.QTimer(self), + # idleposition + "pos": QtGui.QCursor.pos(), + # idletime + "time": 0, + } + self.idler["timer"].timeout.connect(self.checkIdle) + self.idler["timer"].start(1000) if not self.config.defaultprofile(): self.changeProfile() @@ -2912,49 +2909,49 @@ class PesterWindow(MovingWindow): def toggleIdle(self, idle): if idle: # We checked the box to go idle. - self.idler.manual = True + self.idler["manual"] = True self.setAway.emit(True) self.randhandler.setIdle(True) self._sendIdleMsgs() else: - self.idler.manual = False + self.idler["manual"] = False self.setAway.emit(False) self.randhandler.setIdle(False) - self.idler.time = 0 + self.idler["time"] = 0 # karxi: TODO: Need to consider sticking an idle-setter here. @QtCore.pyqtSlot() def checkIdle(self): newpos = QtGui.QCursor.pos() - oldpos = self.idler.pos + oldpos = self.idler["pos"] # Save the new position. - self.idler.pos = newpos + self.idler["pos"] = newpos - if self.idler.manual: + if self.idler["manual"]: # We're already idle, because the user said to be. - self.idler.time = 0 + self.idler["time"] = 0 return - elif self.idler.auto: - self.idler.time = 0 + elif self.idler["auto"]: + self.idler["time"] = 0 if newpos != oldpos: # Cursor moved; unset idle. - self.idler.auto = False + self.idler["auto"] = False self.setAway.emit(False) self.randhandler.setIdle(False) return if newpos != oldpos: # Our cursor has moved, which means we can't be idle. - self.idler.time = 0 + self.idler["time"] = 0 return # If we got here, WE ARE NOT IDLE, but may become so - self.idler.time += 1 - if self.idler.time >= self.idler.threshold: + self.idler["time"] += 1 + if self.idler["time"] >= self.idler["threshold"]: # We've been idle for long enough to fall automatically idle. - self.idler.auto = True + self.idler["auto"] = True # We don't need this anymore. - self.idler.time = 0 + self.idler["time"] = 0 # Make it clear that we're idle. self.setAway.emit(True) self.randhandler.setIdle(True) @@ -3369,7 +3366,7 @@ class PesterWindow(MovingWindow): curidle = self.config.idleTime() if idlesetting != curidle: self.config.set("idleTime", idlesetting) - self.idler.threshold = 60 * idlesetting + self.idler["threshold"] = 60 * idlesetting # theme ghostchumsetting = self.optionmenu.ghostchum.isChecked() curghostchum = self.config.ghostchum() diff --git a/pnc/dep/attrdict.py b/pnc/dep/attrdict.py deleted file mode 100644 index dea6063..0000000 --- a/pnc/dep/attrdict.py +++ /dev/null @@ -1,146 +0,0 @@ -# Heavily modified version of the code featured at the given link -## {{{ http://code.activestate.com/recipes/473786/ (r1) -class AttrDict(dict): - """A dictionary with attribute-style access. It maps attribute access to - the real dictionary. - - Note that accesses to preexisting (e.g. class inherited) or reserved - attributes are handled as they would be normally, and will not be - overwritten. - Overload _is_reserved if you want to change this.""" - - def __init__(self, init={}): - super().__init__(init) - - def __getstate__(self): - return list(self.__dict__.items()) - - def __setstate__(self, items): - for key, val in items: - self.__dict__[key] = val - - def __repr__(self): - return f"{type(self).__name__}({super().__repr__()})" - - def __setitem__(self, name, value): - return super().__setitem__(name, value) - - def __getitem__(self, name): - return super().__getitem__(name) - - def __delitem__(self, name): - return super().__delitem__(name) - - def __getattr__(self, name): - # NOTE: __getattr__ is called if the code has already failed to access - # an attribute on this object. The rest of this code reflects this. - # We could override __getattribute__ to bypass this, but that's not - # worthwhile. - - # We don't do any special handling for reserved names. - if self._is_reserved(name): - # Fall back to normal handling, by force. - return object.__getattribute__(self, name) - - try: - # Try to __getitem__. - result = self[name] - except (KeyError, AttributeError): - # Raising KeyError here will confuse __deepcopy__, so don't do - # that. - # Throw a custom error. - raise AttributeError(f"No key/attr {name!r}") - return result - - def __setattr__(self, name, value): - # Set to the attribute first if it's defined. - # (NOTE: This isn't subject to the same checking as __getattr__.) - # Using dir() also checks non-instance definitions, so things defined - # on a class can be easily set on an instance this way. - - # Detect special/reserved names. - if name in dir(self) or self._is_reserved(name): - # Set it if it's 'special' because we aren't supposed to touch any - # of that - too many potential implementation issues. - # - # Apparently we're also not supposed to set our own dict directly - # in this particular function?... - return object.__setattr__(self, name, value) - else: - return super().__setitem__(name, value) - - def __delattr__(self, name): - # We very *specifically* use self.__dict__ here, because we couldn't - # possibly delete a value that doesn't yet *exist* in our instance's - # namespace yet! - # This shouldn't be a problem, since this type should never have - # __slots__. - if name in self.__dict__: - # See __setattr__. - return object.__delattr__(self, name) - else: - try: - del self[name] - except KeyError as err: - raise AttributeError(str(err)) - - @staticmethod - def _is_reserved(name): - """Check if an attribute name is reserved for system use.""" - # A very simple method. - result = name[:2] == name[-2:] == "__" - return result - - def copy(self): - return type(self)(self) - - __copy__ = copy - - -## end of http://code.activestate.com/recipes/473786/ }}} - - -class DefAttrDict(AttrDict): - default_factory = None - - def __init__(self, default_factory=None, *args, **kwargs): - self.default_factory = default_factory - super().__init__(*args, **kwargs) - - def __repr__(self): - return "{}({!r}, {})".format( - type(self).__name__, - self.default_factory, - # We skip normal processing here, since AttrDict provides basic - # repr for classes in general, which we don't want. - dict.__repr__(self), - ) - - def __getitem__(self, name): - try: - result = super().__getitem__(name) - except KeyError: - result = None - if self.default_factory is not None: - result = self.default_factory() - self[name] = result - return result - - def __getattr__(self, name): - try: - result = super().__getattr__(name) - except AttributeError: - # Detect special/reserved names. - if self._is_reserved(name): - # We shouldn't automatically fill these in. - # Pass this along. - raise - return result - - def copy(self): - return type(self)(self.default_factory, self) - - __copy__ = copy - - -# vim: set autoindent ts=4 sts=4 sw=4 textwidth=79 expandtab: diff --git a/pnc/unicolor.py b/pnc/unicolor.py index e2e9f9e..8334a2f 100644 --- a/pnc/unicolor.py +++ b/pnc/unicolor.py @@ -2,10 +2,6 @@ __all__ = ["Color"] # karxi: Copied from my old Textsub script. Please forgive the mess, and keep # in mind that this may be phased out in the future. - - -from pnc.dep.attrdict import AttrDict - import collections import functools import sys @@ -410,7 +406,7 @@ class Color: # All of these are effectively equivalent to the Qt-provided colors, so they # could be phased out - but there's no need to, yet. -_svg_colors = AttrDict() +_svg_colors = {} _irc_colors = {} _svg_colors.update( {