mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-12-24 03:33:11 +01:00
Use __slots__ for core config values.
This commit is contained in:
parent
fa2c11eec1
commit
1ac7812d7a
29
src/conf.py
29
src/conf.py
@ -134,6 +134,7 @@ def registerUserValue(group, name, value):
|
||||
|
||||
class ValidNick(registry.String):
|
||||
"""Value must be a valid IRC nick."""
|
||||
__slots__ = ()
|
||||
def setValue(self, v):
|
||||
if not ircutils.isNick(v):
|
||||
self.error()
|
||||
@ -142,6 +143,7 @@ class ValidNick(registry.String):
|
||||
|
||||
class ValidNickOrEmpty(ValidNick):
|
||||
"""Value must be a valid IRC nick or empty."""
|
||||
__slots__ = ()
|
||||
def setValue(self, v):
|
||||
if v != '' and not ircutils.isNick(v):
|
||||
self.error()
|
||||
@ -149,11 +151,13 @@ class ValidNickOrEmpty(ValidNick):
|
||||
registry.String.setValue(self, v)
|
||||
|
||||
class ValidNicks(registry.SpaceSeparatedListOf):
|
||||
__slots__ = ()
|
||||
Value = ValidNick
|
||||
|
||||
class ValidNickAllowingPercentS(ValidNick):
|
||||
"""Value must be a valid IRC nick, with the possible exception of a %s
|
||||
in it."""
|
||||
__slots__ = ()
|
||||
def setValue(self, v):
|
||||
# If this works, it's a valid nick, aside from the %s.
|
||||
try:
|
||||
@ -164,10 +168,12 @@ class ValidNickAllowingPercentS(ValidNick):
|
||||
self.error()
|
||||
|
||||
class ValidNicksAllowingPercentS(ValidNicks):
|
||||
__slots__ = ()
|
||||
Value = ValidNickAllowingPercentS
|
||||
|
||||
class ValidChannel(registry.String):
|
||||
"""Value must be a valid IRC channel name."""
|
||||
__slots__ = ('channel',)
|
||||
def setValue(self, v):
|
||||
self.channel = v
|
||||
if ',' in v:
|
||||
@ -194,6 +200,7 @@ class ValidChannel(registry.String):
|
||||
|
||||
class ValidHostmask(registry.String):
|
||||
"""Value must be a valid user hostmask."""
|
||||
__slots__ = ()
|
||||
def setValue(self, v):
|
||||
if not ircutils.isUserHostmask(v):
|
||||
self.error()
|
||||
@ -219,6 +226,7 @@ registerGlobalValue(supybot, 'ident',
|
||||
# bots which are migrated from Supybot or an old version of Limnoria
|
||||
# (whose default value of supybot.user is the empty string).
|
||||
class VersionIfEmpty(registry.String):
|
||||
__slots__ = ()
|
||||
def __call__(self):
|
||||
ret = registry.String.__call__(self)
|
||||
if not ret:
|
||||
@ -231,6 +239,7 @@ registerGlobalValue(supybot, 'user',
|
||||
will be generated if this is left empty.""")))
|
||||
|
||||
class Networks(registry.SpaceSeparatedSetOfStrings):
|
||||
__slots__ = ()
|
||||
List = ircutils.IrcSet
|
||||
|
||||
registerGlobalValue(supybot, 'networks',
|
||||
@ -238,6 +247,7 @@ registerGlobalValue(supybot, 'networks',
|
||||
orderAlphabetically=True))
|
||||
|
||||
class Servers(registry.SpaceSeparatedListOfStrings):
|
||||
__slots__ = ()
|
||||
def normalize(self, s):
|
||||
if ':' not in s:
|
||||
s += ':6667'
|
||||
@ -262,6 +272,7 @@ class Servers(registry.SpaceSeparatedListOfStrings):
|
||||
|
||||
class SocksProxy(registry.String):
|
||||
"""Value must be a valid hostname:port string."""
|
||||
__slots__ = ()
|
||||
def setValue(self, v):
|
||||
# TODO: improve checks
|
||||
if ':' not in v:
|
||||
@ -273,6 +284,7 @@ class SocksProxy(registry.String):
|
||||
super(SocksProxy, self).setValue(v)
|
||||
|
||||
class SpaceSeparatedSetOfChannels(registry.SpaceSeparatedListOf):
|
||||
__slots__ = ()
|
||||
sorted = True
|
||||
List = ircutils.IrcSet
|
||||
Value = ValidChannel
|
||||
@ -313,10 +325,12 @@ class SpaceSeparatedSetOfChannels(registry.SpaceSeparatedListOf):
|
||||
return None
|
||||
|
||||
class ValidSaslMechanism(registry.OnlySomeStrings):
|
||||
__slots__ = ()
|
||||
validStrings = ('ecdsa-nist256p-challenge', 'external', 'plain',
|
||||
'scram-sha-256')
|
||||
|
||||
class SpaceSeparatedListOfSaslMechanisms(registry.SpaceSeparatedListOf):
|
||||
__slots__ = ()
|
||||
Value = ValidSaslMechanism
|
||||
|
||||
def registerNetwork(name, password='', ssl=True, sasl_username='',
|
||||
@ -554,6 +568,7 @@ registerChannelValue(supybot.reply, 'showSimpleSyntax',
|
||||
|
||||
class ValidPrefixChars(registry.String):
|
||||
"""Value must contain only ~!@#$%^&*()_-+=[{}]\\|'\";:,<.>/?"""
|
||||
__slots__ = ()
|
||||
def setValue(self, v):
|
||||
if any([x not in '`~!@#$%^&*()_-+=[{}]\\|\'";:,<.>/?' for x in v]):
|
||||
self.error()
|
||||
@ -698,6 +713,7 @@ registerGroup(supybot, 'commands')
|
||||
|
||||
class ValidQuotes(registry.Value):
|
||||
"""Value must consist solely of \", ', and ` characters."""
|
||||
__slots__ = ()
|
||||
def setValue(self, v):
|
||||
if [c for c in v if c not in '"`\'']:
|
||||
self.error()
|
||||
@ -722,6 +738,7 @@ registerGlobalValue(supybot.commands.nested, 'maximum',
|
||||
commands more nested than this.""")))
|
||||
|
||||
class ValidBrackets(registry.OnlySomeStrings):
|
||||
__slots__ = ()
|
||||
validStrings = ('', '[]', '<>', '{}', '()')
|
||||
|
||||
registerChannelValue(supybot.commands.nested, 'brackets',
|
||||
@ -816,6 +833,7 @@ registerGlobalValue(supybot.drivers, 'poll',
|
||||
driver should block waiting for input.""")))
|
||||
|
||||
class ValidDriverModule(registry.OnlySomeStrings):
|
||||
__slots__ = ()
|
||||
validStrings = ('default', 'Socket', 'Twisted')
|
||||
|
||||
registerGlobalValue(supybot.drivers, 'module',
|
||||
@ -836,6 +854,7 @@ registerGlobalValue(supybot.drivers, 'maxReconnectWait',
|
||||
# XXX This shouldn't make directories willy-nilly. As it is now, if it's
|
||||
# configured, it'll still make the default directories, I think.
|
||||
class Directory(registry.String):
|
||||
__slots__ = ()
|
||||
def __call__(self):
|
||||
# ??? Should we perhaps always return an absolute path here?
|
||||
v = super(Directory, self).__call__()
|
||||
@ -857,6 +876,7 @@ class Directory(registry.String):
|
||||
return os.path.join(myself, filename)
|
||||
|
||||
class DataFilename(registry.String):
|
||||
__slots__ = ()
|
||||
def __call__(self):
|
||||
v = super(DataFilename, self).__call__()
|
||||
dataDir = supybot.directories.data()
|
||||
@ -867,6 +887,7 @@ class DataFilename(registry.String):
|
||||
return v
|
||||
|
||||
class DataFilenameDirectory(DataFilename, Directory):
|
||||
__slots__ = ()
|
||||
def __call__(self):
|
||||
v = DataFilename.__call__(self)
|
||||
v = Directory.__call__(self)
|
||||
@ -924,6 +945,7 @@ registerGlobalValue(supybot.plugins, 'alwaysLoadImportant',
|
||||
# supybot.databases. For stuff relating to Supybot's databases (duh!)
|
||||
###
|
||||
class Databases(registry.SpaceSeparatedListOfStrings):
|
||||
__slots__ = ()
|
||||
def __call__(self):
|
||||
v = super(Databases, self).__call__()
|
||||
if not v:
|
||||
@ -976,6 +998,7 @@ registerGlobalValue(supybot.databases.channels, 'filename',
|
||||
# TODO This will need to do more in the future (such as making sure link.allow
|
||||
# will let the link occur), but for now let's just leave it as this.
|
||||
class ChannelSpecific(registry.Boolean):
|
||||
__slots__ = ()
|
||||
def getChannelLink(self, channel):
|
||||
channelSpecific = supybot.databases.plugins.channelSpecific
|
||||
channels = [channel]
|
||||
@ -1029,6 +1052,7 @@ registerChannelValue(supybot.databases.plugins.channelSpecific.link, 'allow',
|
||||
|
||||
|
||||
class CDB(registry.Boolean):
|
||||
__slots__ = ()
|
||||
def connect(self, filename):
|
||||
from . import cdb
|
||||
basename = os.path.basename(filename)
|
||||
@ -1069,6 +1093,7 @@ registerGroup(supybot, 'protocols')
|
||||
registerGroup(supybot.protocols, 'irc')
|
||||
|
||||
class Banmask(registry.SpaceSeparatedSetOfStrings):
|
||||
__slots__ = ('__parent', '__dict__') # __dict__ is needed to set __doc__
|
||||
validStrings = ('exact', 'nick', 'user', 'host')
|
||||
def __init__(self, *args, **kwargs):
|
||||
assert self.validStrings, 'There must be some valid strings. ' \
|
||||
@ -1204,6 +1229,7 @@ registerGlobalValue(supybot.protocols.http, 'peekSize',
|
||||
|
||||
class HttpProxy(registry.String):
|
||||
"""Value must be a valid hostname:port string."""
|
||||
__slots__ = ()
|
||||
def setValue(self, v):
|
||||
proxies = {}
|
||||
if v != "":
|
||||
@ -1242,6 +1268,7 @@ registerGroup(supybot.servers, 'http')
|
||||
|
||||
class IP(registry.String):
|
||||
"""Value must be a valid IP."""
|
||||
__slots__ = ()
|
||||
def setValue(self, v):
|
||||
if v and not utils.net.isIP(v):
|
||||
self.error()
|
||||
@ -1249,6 +1276,7 @@ class IP(registry.String):
|
||||
registry.String.setValue(self, v)
|
||||
|
||||
class ListOfIPs(registry.SpaceSeparatedListOfStrings):
|
||||
__slots__ = ()
|
||||
Value = IP
|
||||
|
||||
registerGlobalValue(supybot.servers.http, 'singleStack',
|
||||
@ -1295,6 +1323,7 @@ registerGlobalValue(supybot, 'externalIP',
|
||||
class SocketTimeout(registry.PositiveInteger):
|
||||
"""Value must be an integer greater than supybot.drivers.poll and must be
|
||||
greater than or equal to 1."""
|
||||
__slots__ = ()
|
||||
def setValue(self, v):
|
||||
if v < supybot.drivers.poll() or v < 1:
|
||||
self.error()
|
||||
|
15
src/ircdb.py
15
src/ircdb.py
@ -108,6 +108,7 @@ def unWildcardHostmask(hostmask):
|
||||
_invert = invertCapability
|
||||
class CapabilitySet(set):
|
||||
"""A subclass of set handling basic capability stuff."""
|
||||
__slots__ = ('__parent',)
|
||||
def __init__(self, capabilities=()):
|
||||
self.__parent = super(CapabilitySet, self)
|
||||
self.__parent.__init__()
|
||||
@ -155,6 +156,7 @@ class CapabilitySet(set):
|
||||
antiOwner = makeAntiCapability('owner')
|
||||
class UserCapabilitySet(CapabilitySet):
|
||||
"""A subclass of CapabilitySet to handle the owner capability correctly."""
|
||||
__slots__ = ('__parent',)
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.__parent = super(UserCapabilitySet, self)
|
||||
self.__parent.__init__(*args, **kwargs)
|
||||
@ -196,6 +198,8 @@ class UserCapabilitySet(CapabilitySet):
|
||||
|
||||
class IrcUser(object):
|
||||
"""This class holds the capabilities and authentications for a user."""
|
||||
__slots__ = ('id', 'auth', 'name', 'ignore', 'secure', 'hashed',
|
||||
'password', 'capabilities', 'hostmasks', 'nicks', 'gpgkeys')
|
||||
def __init__(self, ignore=False, password='', name='',
|
||||
capabilities=(), hostmasks=None, nicks=None,
|
||||
secure=False, hashed=False):
|
||||
@ -368,6 +372,8 @@ class IrcUser(object):
|
||||
|
||||
class IrcChannel(object):
|
||||
"""This class holds the capabilities, bans, and ignores of a channel."""
|
||||
__slots__ = ('defaultAllow', 'expiredBans', 'bans', 'ignores', 'silences',
|
||||
'exceptions', 'capabilities', 'lobotomized')
|
||||
defaultOff = ('op', 'halfop', 'voice', 'protected')
|
||||
def __init__(self, bans=None, silences=None, exceptions=None, ignores=None,
|
||||
capabilities=None, lobotomized=False, defaultAllow=True):
|
||||
@ -491,10 +497,12 @@ class IrcChannel(object):
|
||||
|
||||
|
||||
class Creator(object):
|
||||
__slots__ = ()
|
||||
def badCommand(self, command, rest, lineno):
|
||||
raise ValueError('Invalid command on line %s: %s' % (lineno, command))
|
||||
|
||||
class IrcUserCreator(Creator):
|
||||
__slots__ = ('users')
|
||||
u = None
|
||||
def __init__(self, users):
|
||||
if self.u is None:
|
||||
@ -563,6 +571,7 @@ class IrcUserCreator(Creator):
|
||||
IrcUserCreator.u = None
|
||||
|
||||
class IrcChannelCreator(Creator):
|
||||
__slots__ = ('c', 'channels', 'hadChannel')
|
||||
name = None
|
||||
def __init__(self, channels):
|
||||
self.c = IrcChannel()
|
||||
@ -611,6 +620,8 @@ class DuplicateHostmask(ValueError):
|
||||
|
||||
class UsersDictionary(utils.IterableMap):
|
||||
"""A simple serialized-to-file User Database."""
|
||||
__slots__ = ('noFlush', 'filename', 'users', '_nameCache',
|
||||
'_hostmaskCache')
|
||||
def __init__(self):
|
||||
self.noFlush = False
|
||||
self.filename = None
|
||||
@ -821,6 +832,7 @@ class UsersDictionary(utils.IterableMap):
|
||||
|
||||
|
||||
class ChannelsDictionary(utils.IterableMap):
|
||||
__slots__ = ('noFlush', 'filename', 'channels')
|
||||
def __init__(self):
|
||||
self.noFlush = False
|
||||
self.filename = None
|
||||
@ -897,6 +909,7 @@ class ChannelsDictionary(utils.IterableMap):
|
||||
|
||||
|
||||
class IgnoresDB(object):
|
||||
__slots__ = ('filename', 'hostmasks')
|
||||
def __init__(self):
|
||||
self.filename = None
|
||||
self.hostmasks = {}
|
||||
@ -1145,9 +1158,11 @@ def checkCapabilities(hostmask, capabilities, requireAll=False):
|
||||
###
|
||||
|
||||
class SpaceSeparatedListOfCapabilities(registry.SpaceSeparatedListOfStrings):
|
||||
__slots__ = ()
|
||||
List = CapabilitySet
|
||||
|
||||
class DefaultCapabilities(SpaceSeparatedListOfCapabilities):
|
||||
__slots__ = ()
|
||||
# We use a keyword argument trick here to prevent eval'ing of code that
|
||||
# changes allowDefaultOwner from affecting this. It's not perfect, but
|
||||
# it's still an improvement, raising the bar for potential crackers.
|
||||
|
@ -191,6 +191,8 @@ def join(names):
|
||||
|
||||
class Group(object):
|
||||
"""A group; it doesn't hold a value unless handled by a subclass."""
|
||||
__slots__ = ('_help', '_name', '_added', '_children', '_lastModified',
|
||||
'_private', '_supplyDefault', '_orderAlphabetically', '_wasSet')
|
||||
def __init__(self, help='', supplyDefault=False,
|
||||
orderAlphabetically=True, private=False):
|
||||
self._help = utils.str.normalizeWhitespace(help)
|
||||
@ -201,7 +203,6 @@ class Group(object):
|
||||
self._private = private
|
||||
self._supplyDefault = supplyDefault
|
||||
self._orderAlphabetically = orderAlphabetically
|
||||
OriginalClass = self.__class__
|
||||
self._wasSet = True
|
||||
|
||||
def __call__(self):
|
||||
@ -326,6 +327,8 @@ class _NoValueGiven:
|
||||
class Value(Group):
|
||||
"""Invalid registry value. If you're getting this message, report it,
|
||||
because we forgot to put a proper help string here."""
|
||||
__slots__ = ('__parent', '_default', '_showDefault', '_help', '_callbacks',
|
||||
'value', 'channelValue', '_opSettable')
|
||||
def __init__(self, default, help, setDefault=True,
|
||||
showDefault=True, **kwargs):
|
||||
self.__parent = super(Value, self)
|
||||
@ -421,6 +424,7 @@ class Value(Group):
|
||||
|
||||
class Boolean(Value):
|
||||
"""Value must be either True or False (or On or Off)."""
|
||||
__slots__ = ()
|
||||
errormsg = _('Value must be either True or False (or On or Off), not %r.')
|
||||
def set(self, s):
|
||||
try:
|
||||
@ -437,6 +441,7 @@ class Boolean(Value):
|
||||
|
||||
class Integer(Value):
|
||||
"""Value must be an integer."""
|
||||
__slots__ = ()
|
||||
errormsg = _('Value must be an integer, not %r.')
|
||||
def set(self, s):
|
||||
try:
|
||||
@ -446,6 +451,7 @@ class Integer(Value):
|
||||
|
||||
class NonNegativeInteger(Integer):
|
||||
"""Value must be a non-negative integer."""
|
||||
__slots__ = ()
|
||||
errormsg = _('Value must be a non-negative integer, not %r.')
|
||||
def setValue(self, v):
|
||||
if v < 0:
|
||||
@ -454,6 +460,7 @@ class NonNegativeInteger(Integer):
|
||||
|
||||
class PositiveInteger(NonNegativeInteger):
|
||||
"""Value must be positive (non-zero) integer."""
|
||||
__slots__ = ()
|
||||
errormsg = _('Value must be positive (non-zero) integer, not %r.')
|
||||
def setValue(self, v):
|
||||
if not v:
|
||||
@ -462,6 +469,7 @@ class PositiveInteger(NonNegativeInteger):
|
||||
|
||||
class Float(Value):
|
||||
"""Value must be a floating-point number."""
|
||||
__slots__ = ()
|
||||
errormsg = _('Value must be a floating-point number, not %r.')
|
||||
def set(self, s):
|
||||
try:
|
||||
@ -477,6 +485,7 @@ class Float(Value):
|
||||
|
||||
class PositiveFloat(Float):
|
||||
"""Value must be a floating-point number greater than zero."""
|
||||
__slots__ = ()
|
||||
errormsg = _('Value must be a floating-point number greater than zero, '
|
||||
'not %r.')
|
||||
def setValue(self, v):
|
||||
@ -487,6 +496,7 @@ class PositiveFloat(Float):
|
||||
|
||||
class Probability(Float):
|
||||
"""Value must be a floating point number in the range [0, 1]."""
|
||||
__slots__ = ('__parent',)
|
||||
errormsg = _('Value must be a floating point number in the range [0, 1], '
|
||||
'not %r.')
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -501,6 +511,7 @@ class Probability(Float):
|
||||
|
||||
class String(Value):
|
||||
"""Value is not a valid Python string."""
|
||||
__slots__ = ()
|
||||
errormsg = _('Value should be a valid Python string, not %r.')
|
||||
def set(self, s):
|
||||
v = s
|
||||
@ -527,6 +538,8 @@ class String(Value):
|
||||
return s
|
||||
|
||||
class OnlySomeStrings(String):
|
||||
__slots__ = ('__parent', '__dict__') # unfortunately, __dict__ is needed
|
||||
# to set __doc__.
|
||||
validStrings = ()
|
||||
def __init__(self, *args, **kwargs):
|
||||
assert self.validStrings, 'There must be some valid strings. ' \
|
||||
@ -559,6 +572,7 @@ class OnlySomeStrings(String):
|
||||
self.error(v)
|
||||
|
||||
class NormalizedString(String):
|
||||
__slots__ = ('__parent')
|
||||
def __init__(self, default, *args, **kwargs):
|
||||
default = self.normalize(default)
|
||||
self.__parent = super(NormalizedString, self)
|
||||
@ -591,6 +605,7 @@ class NormalizedString(String):
|
||||
return ret
|
||||
|
||||
class StringSurroundedBySpaces(String):
|
||||
__slots__ = ()
|
||||
def setValue(self, v):
|
||||
if v and v.lstrip() == v:
|
||||
v= ' ' + v
|
||||
@ -599,6 +614,7 @@ class StringSurroundedBySpaces(String):
|
||||
super(StringSurroundedBySpaces, self).setValue(v)
|
||||
|
||||
class StringWithSpaceOnRight(String):
|
||||
__slots__ = ()
|
||||
def setValue(self, v):
|
||||
if v and v.rstrip() == v:
|
||||
v += ' '
|
||||
@ -606,6 +622,7 @@ class StringWithSpaceOnRight(String):
|
||||
|
||||
class Regexp(Value):
|
||||
"""Value must be a valid regular expression."""
|
||||
__slots__ = ('sr', 'value', '__parent')
|
||||
errormsg = _('Value must be a valid regular expression, not %r.')
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['setDefault'] = False
|
||||
@ -645,6 +662,7 @@ class Regexp(Value):
|
||||
return self.sr
|
||||
|
||||
class SeparatedListOf(Value):
|
||||
__slots__ = ()
|
||||
List = list
|
||||
Value = Value
|
||||
sorted = False
|
||||
@ -681,23 +699,28 @@ class SeparatedListOf(Value):
|
||||
return ' '
|
||||
|
||||
class SpaceSeparatedListOf(SeparatedListOf):
|
||||
__slots__ = ()
|
||||
def splitter(self, s):
|
||||
return s.split()
|
||||
joiner = ' '.join
|
||||
|
||||
class SpaceSeparatedListOfStrings(SpaceSeparatedListOf):
|
||||
__slots__ = ()
|
||||
Value = String
|
||||
|
||||
class SpaceSeparatedSetOfStrings(SpaceSeparatedListOfStrings):
|
||||
__slots__ = ()
|
||||
List = set
|
||||
|
||||
class CommaSeparatedListOfStrings(SeparatedListOf):
|
||||
__slots__ = ()
|
||||
Value = String
|
||||
def splitter(self, s):
|
||||
return re.split(r'\s*,\s*', s)
|
||||
joiner = ', '.join
|
||||
|
||||
class CommaSeparatedSetOfStrings(SeparatedListOf):
|
||||
__slots__ = ()
|
||||
List = set
|
||||
Value = String
|
||||
def splitter(self, s):
|
||||
@ -705,6 +728,7 @@ class CommaSeparatedSetOfStrings(SeparatedListOf):
|
||||
joiner = ', '.join
|
||||
|
||||
class TemplatedString(String):
|
||||
__slots__ = ()
|
||||
requiredTemplates = []
|
||||
def __init__(self, *args, **kwargs):
|
||||
assert self.requiredTemplates, \
|
||||
@ -721,6 +745,7 @@ class TemplatedString(String):
|
||||
self.error(v)
|
||||
|
||||
class Json(String):
|
||||
__slots__ = ()
|
||||
# Json-serializable data
|
||||
def set(self, v):
|
||||
self.setValue(json.loads(v))
|
||||
|
Loading…
Reference in New Issue
Block a user