Remove AttrDict and enable pylint typecheck message category.
The AttrDict class had Python 2 leftovers which the linter flagged and isn't really necessary anyway, plus it wasn't licensed under the GPL.
This commit is contained in:
parent
9ec4dbd088
commit
370685f6b3
5 changed files with 52 additions and 205 deletions
|
@ -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:
|
||||
|
|
23
convo.py
23
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)
|
||||
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
|
@ -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(
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue