Use __slots__ for core config values.

This commit is contained in:
Valentin Lorentz 2018-09-25 18:59:46 +02:00
parent fa2c11eec1
commit 1ac7812d7a
3 changed files with 70 additions and 1 deletions

View File

@ -134,6 +134,7 @@ def registerUserValue(group, name, value):
class ValidNick(registry.String): class ValidNick(registry.String):
"""Value must be a valid IRC nick.""" """Value must be a valid IRC nick."""
__slots__ = ()
def setValue(self, v): def setValue(self, v):
if not ircutils.isNick(v): if not ircutils.isNick(v):
self.error() self.error()
@ -142,6 +143,7 @@ class ValidNick(registry.String):
class ValidNickOrEmpty(ValidNick): class ValidNickOrEmpty(ValidNick):
"""Value must be a valid IRC nick or empty.""" """Value must be a valid IRC nick or empty."""
__slots__ = ()
def setValue(self, v): def setValue(self, v):
if v != '' and not ircutils.isNick(v): if v != '' and not ircutils.isNick(v):
self.error() self.error()
@ -149,11 +151,13 @@ class ValidNickOrEmpty(ValidNick):
registry.String.setValue(self, v) registry.String.setValue(self, v)
class ValidNicks(registry.SpaceSeparatedListOf): class ValidNicks(registry.SpaceSeparatedListOf):
__slots__ = ()
Value = ValidNick Value = ValidNick
class ValidNickAllowingPercentS(ValidNick): class ValidNickAllowingPercentS(ValidNick):
"""Value must be a valid IRC nick, with the possible exception of a %s """Value must be a valid IRC nick, with the possible exception of a %s
in it.""" in it."""
__slots__ = ()
def setValue(self, v): def setValue(self, v):
# If this works, it's a valid nick, aside from the %s. # If this works, it's a valid nick, aside from the %s.
try: try:
@ -164,10 +168,12 @@ class ValidNickAllowingPercentS(ValidNick):
self.error() self.error()
class ValidNicksAllowingPercentS(ValidNicks): class ValidNicksAllowingPercentS(ValidNicks):
__slots__ = ()
Value = ValidNickAllowingPercentS Value = ValidNickAllowingPercentS
class ValidChannel(registry.String): class ValidChannel(registry.String):
"""Value must be a valid IRC channel name.""" """Value must be a valid IRC channel name."""
__slots__ = ('channel',)
def setValue(self, v): def setValue(self, v):
self.channel = v self.channel = v
if ',' in v: if ',' in v:
@ -194,6 +200,7 @@ class ValidChannel(registry.String):
class ValidHostmask(registry.String): class ValidHostmask(registry.String):
"""Value must be a valid user hostmask.""" """Value must be a valid user hostmask."""
__slots__ = ()
def setValue(self, v): def setValue(self, v):
if not ircutils.isUserHostmask(v): if not ircutils.isUserHostmask(v):
self.error() self.error()
@ -219,6 +226,7 @@ registerGlobalValue(supybot, 'ident',
# bots which are migrated from Supybot or an old version of Limnoria # bots which are migrated from Supybot or an old version of Limnoria
# (whose default value of supybot.user is the empty string). # (whose default value of supybot.user is the empty string).
class VersionIfEmpty(registry.String): class VersionIfEmpty(registry.String):
__slots__ = ()
def __call__(self): def __call__(self):
ret = registry.String.__call__(self) ret = registry.String.__call__(self)
if not ret: if not ret:
@ -231,6 +239,7 @@ registerGlobalValue(supybot, 'user',
will be generated if this is left empty."""))) will be generated if this is left empty.""")))
class Networks(registry.SpaceSeparatedSetOfStrings): class Networks(registry.SpaceSeparatedSetOfStrings):
__slots__ = ()
List = ircutils.IrcSet List = ircutils.IrcSet
registerGlobalValue(supybot, 'networks', registerGlobalValue(supybot, 'networks',
@ -238,6 +247,7 @@ registerGlobalValue(supybot, 'networks',
orderAlphabetically=True)) orderAlphabetically=True))
class Servers(registry.SpaceSeparatedListOfStrings): class Servers(registry.SpaceSeparatedListOfStrings):
__slots__ = ()
def normalize(self, s): def normalize(self, s):
if ':' not in s: if ':' not in s:
s += ':6667' s += ':6667'
@ -262,6 +272,7 @@ class Servers(registry.SpaceSeparatedListOfStrings):
class SocksProxy(registry.String): class SocksProxy(registry.String):
"""Value must be a valid hostname:port string.""" """Value must be a valid hostname:port string."""
__slots__ = ()
def setValue(self, v): def setValue(self, v):
# TODO: improve checks # TODO: improve checks
if ':' not in v: if ':' not in v:
@ -273,6 +284,7 @@ class SocksProxy(registry.String):
super(SocksProxy, self).setValue(v) super(SocksProxy, self).setValue(v)
class SpaceSeparatedSetOfChannels(registry.SpaceSeparatedListOf): class SpaceSeparatedSetOfChannels(registry.SpaceSeparatedListOf):
__slots__ = ()
sorted = True sorted = True
List = ircutils.IrcSet List = ircutils.IrcSet
Value = ValidChannel Value = ValidChannel
@ -313,10 +325,12 @@ class SpaceSeparatedSetOfChannels(registry.SpaceSeparatedListOf):
return None return None
class ValidSaslMechanism(registry.OnlySomeStrings): class ValidSaslMechanism(registry.OnlySomeStrings):
__slots__ = ()
validStrings = ('ecdsa-nist256p-challenge', 'external', 'plain', validStrings = ('ecdsa-nist256p-challenge', 'external', 'plain',
'scram-sha-256') 'scram-sha-256')
class SpaceSeparatedListOfSaslMechanisms(registry.SpaceSeparatedListOf): class SpaceSeparatedListOfSaslMechanisms(registry.SpaceSeparatedListOf):
__slots__ = ()
Value = ValidSaslMechanism Value = ValidSaslMechanism
def registerNetwork(name, password='', ssl=True, sasl_username='', def registerNetwork(name, password='', ssl=True, sasl_username='',
@ -554,6 +568,7 @@ registerChannelValue(supybot.reply, 'showSimpleSyntax',
class ValidPrefixChars(registry.String): class ValidPrefixChars(registry.String):
"""Value must contain only ~!@#$%^&*()_-+=[{}]\\|'\";:,<.>/?""" """Value must contain only ~!@#$%^&*()_-+=[{}]\\|'\";:,<.>/?"""
__slots__ = ()
def setValue(self, v): def setValue(self, v):
if any([x not in '`~!@#$%^&*()_-+=[{}]\\|\'";:,<.>/?' for x in v]): if any([x not in '`~!@#$%^&*()_-+=[{}]\\|\'";:,<.>/?' for x in v]):
self.error() self.error()
@ -698,6 +713,7 @@ registerGroup(supybot, 'commands')
class ValidQuotes(registry.Value): class ValidQuotes(registry.Value):
"""Value must consist solely of \", ', and ` characters.""" """Value must consist solely of \", ', and ` characters."""
__slots__ = ()
def setValue(self, v): def setValue(self, v):
if [c for c in v if c not in '"`\'']: if [c for c in v if c not in '"`\'']:
self.error() self.error()
@ -722,6 +738,7 @@ registerGlobalValue(supybot.commands.nested, 'maximum',
commands more nested than this."""))) commands more nested than this.""")))
class ValidBrackets(registry.OnlySomeStrings): class ValidBrackets(registry.OnlySomeStrings):
__slots__ = ()
validStrings = ('', '[]', '<>', '{}', '()') validStrings = ('', '[]', '<>', '{}', '()')
registerChannelValue(supybot.commands.nested, 'brackets', registerChannelValue(supybot.commands.nested, 'brackets',
@ -816,6 +833,7 @@ registerGlobalValue(supybot.drivers, 'poll',
driver should block waiting for input."""))) driver should block waiting for input.""")))
class ValidDriverModule(registry.OnlySomeStrings): class ValidDriverModule(registry.OnlySomeStrings):
__slots__ = ()
validStrings = ('default', 'Socket', 'Twisted') validStrings = ('default', 'Socket', 'Twisted')
registerGlobalValue(supybot.drivers, 'module', 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 # 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. # configured, it'll still make the default directories, I think.
class Directory(registry.String): class Directory(registry.String):
__slots__ = ()
def __call__(self): def __call__(self):
# ??? Should we perhaps always return an absolute path here? # ??? Should we perhaps always return an absolute path here?
v = super(Directory, self).__call__() v = super(Directory, self).__call__()
@ -857,6 +876,7 @@ class Directory(registry.String):
return os.path.join(myself, filename) return os.path.join(myself, filename)
class DataFilename(registry.String): class DataFilename(registry.String):
__slots__ = ()
def __call__(self): def __call__(self):
v = super(DataFilename, self).__call__() v = super(DataFilename, self).__call__()
dataDir = supybot.directories.data() dataDir = supybot.directories.data()
@ -867,6 +887,7 @@ class DataFilename(registry.String):
return v return v
class DataFilenameDirectory(DataFilename, Directory): class DataFilenameDirectory(DataFilename, Directory):
__slots__ = ()
def __call__(self): def __call__(self):
v = DataFilename.__call__(self) v = DataFilename.__call__(self)
v = Directory.__call__(self) v = Directory.__call__(self)
@ -924,6 +945,7 @@ registerGlobalValue(supybot.plugins, 'alwaysLoadImportant',
# supybot.databases. For stuff relating to Supybot's databases (duh!) # supybot.databases. For stuff relating to Supybot's databases (duh!)
### ###
class Databases(registry.SpaceSeparatedListOfStrings): class Databases(registry.SpaceSeparatedListOfStrings):
__slots__ = ()
def __call__(self): def __call__(self):
v = super(Databases, self).__call__() v = super(Databases, self).__call__()
if not v: 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 # 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. # will let the link occur), but for now let's just leave it as this.
class ChannelSpecific(registry.Boolean): class ChannelSpecific(registry.Boolean):
__slots__ = ()
def getChannelLink(self, channel): def getChannelLink(self, channel):
channelSpecific = supybot.databases.plugins.channelSpecific channelSpecific = supybot.databases.plugins.channelSpecific
channels = [channel] channels = [channel]
@ -1029,6 +1052,7 @@ registerChannelValue(supybot.databases.plugins.channelSpecific.link, 'allow',
class CDB(registry.Boolean): class CDB(registry.Boolean):
__slots__ = ()
def connect(self, filename): def connect(self, filename):
from . import cdb from . import cdb
basename = os.path.basename(filename) basename = os.path.basename(filename)
@ -1069,6 +1093,7 @@ registerGroup(supybot, 'protocols')
registerGroup(supybot.protocols, 'irc') registerGroup(supybot.protocols, 'irc')
class Banmask(registry.SpaceSeparatedSetOfStrings): class Banmask(registry.SpaceSeparatedSetOfStrings):
__slots__ = ('__parent', '__dict__') # __dict__ is needed to set __doc__
validStrings = ('exact', 'nick', 'user', 'host') validStrings = ('exact', 'nick', 'user', 'host')
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
assert self.validStrings, 'There must be some valid strings. ' \ assert self.validStrings, 'There must be some valid strings. ' \
@ -1204,6 +1229,7 @@ registerGlobalValue(supybot.protocols.http, 'peekSize',
class HttpProxy(registry.String): class HttpProxy(registry.String):
"""Value must be a valid hostname:port string.""" """Value must be a valid hostname:port string."""
__slots__ = ()
def setValue(self, v): def setValue(self, v):
proxies = {} proxies = {}
if v != "": if v != "":
@ -1242,6 +1268,7 @@ registerGroup(supybot.servers, 'http')
class IP(registry.String): class IP(registry.String):
"""Value must be a valid IP.""" """Value must be a valid IP."""
__slots__ = ()
def setValue(self, v): def setValue(self, v):
if v and not utils.net.isIP(v): if v and not utils.net.isIP(v):
self.error() self.error()
@ -1249,6 +1276,7 @@ class IP(registry.String):
registry.String.setValue(self, v) registry.String.setValue(self, v)
class ListOfIPs(registry.SpaceSeparatedListOfStrings): class ListOfIPs(registry.SpaceSeparatedListOfStrings):
__slots__ = ()
Value = IP Value = IP
registerGlobalValue(supybot.servers.http, 'singleStack', registerGlobalValue(supybot.servers.http, 'singleStack',
@ -1295,6 +1323,7 @@ registerGlobalValue(supybot, 'externalIP',
class SocketTimeout(registry.PositiveInteger): class SocketTimeout(registry.PositiveInteger):
"""Value must be an integer greater than supybot.drivers.poll and must be """Value must be an integer greater than supybot.drivers.poll and must be
greater than or equal to 1.""" greater than or equal to 1."""
__slots__ = ()
def setValue(self, v): def setValue(self, v):
if v < supybot.drivers.poll() or v < 1: if v < supybot.drivers.poll() or v < 1:
self.error() self.error()

View File

@ -108,6 +108,7 @@ def unWildcardHostmask(hostmask):
_invert = invertCapability _invert = invertCapability
class CapabilitySet(set): class CapabilitySet(set):
"""A subclass of set handling basic capability stuff.""" """A subclass of set handling basic capability stuff."""
__slots__ = ('__parent',)
def __init__(self, capabilities=()): def __init__(self, capabilities=()):
self.__parent = super(CapabilitySet, self) self.__parent = super(CapabilitySet, self)
self.__parent.__init__() self.__parent.__init__()
@ -155,6 +156,7 @@ class CapabilitySet(set):
antiOwner = makeAntiCapability('owner') antiOwner = makeAntiCapability('owner')
class UserCapabilitySet(CapabilitySet): class UserCapabilitySet(CapabilitySet):
"""A subclass of CapabilitySet to handle the owner capability correctly.""" """A subclass of CapabilitySet to handle the owner capability correctly."""
__slots__ = ('__parent',)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.__parent = super(UserCapabilitySet, self) self.__parent = super(UserCapabilitySet, self)
self.__parent.__init__(*args, **kwargs) self.__parent.__init__(*args, **kwargs)
@ -196,6 +198,8 @@ class UserCapabilitySet(CapabilitySet):
class IrcUser(object): class IrcUser(object):
"""This class holds the capabilities and authentications for a user.""" """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='', def __init__(self, ignore=False, password='', name='',
capabilities=(), hostmasks=None, nicks=None, capabilities=(), hostmasks=None, nicks=None,
secure=False, hashed=False): secure=False, hashed=False):
@ -368,6 +372,8 @@ class IrcUser(object):
class IrcChannel(object): class IrcChannel(object):
"""This class holds the capabilities, bans, and ignores of a channel.""" """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') defaultOff = ('op', 'halfop', 'voice', 'protected')
def __init__(self, bans=None, silences=None, exceptions=None, ignores=None, def __init__(self, bans=None, silences=None, exceptions=None, ignores=None,
capabilities=None, lobotomized=False, defaultAllow=True): capabilities=None, lobotomized=False, defaultAllow=True):
@ -491,10 +497,12 @@ class IrcChannel(object):
class Creator(object): class Creator(object):
__slots__ = ()
def badCommand(self, command, rest, lineno): def badCommand(self, command, rest, lineno):
raise ValueError('Invalid command on line %s: %s' % (lineno, command)) raise ValueError('Invalid command on line %s: %s' % (lineno, command))
class IrcUserCreator(Creator): class IrcUserCreator(Creator):
__slots__ = ('users')
u = None u = None
def __init__(self, users): def __init__(self, users):
if self.u is None: if self.u is None:
@ -563,6 +571,7 @@ class IrcUserCreator(Creator):
IrcUserCreator.u = None IrcUserCreator.u = None
class IrcChannelCreator(Creator): class IrcChannelCreator(Creator):
__slots__ = ('c', 'channels', 'hadChannel')
name = None name = None
def __init__(self, channels): def __init__(self, channels):
self.c = IrcChannel() self.c = IrcChannel()
@ -611,6 +620,8 @@ class DuplicateHostmask(ValueError):
class UsersDictionary(utils.IterableMap): class UsersDictionary(utils.IterableMap):
"""A simple serialized-to-file User Database.""" """A simple serialized-to-file User Database."""
__slots__ = ('noFlush', 'filename', 'users', '_nameCache',
'_hostmaskCache')
def __init__(self): def __init__(self):
self.noFlush = False self.noFlush = False
self.filename = None self.filename = None
@ -821,6 +832,7 @@ class UsersDictionary(utils.IterableMap):
class ChannelsDictionary(utils.IterableMap): class ChannelsDictionary(utils.IterableMap):
__slots__ = ('noFlush', 'filename', 'channels')
def __init__(self): def __init__(self):
self.noFlush = False self.noFlush = False
self.filename = None self.filename = None
@ -897,6 +909,7 @@ class ChannelsDictionary(utils.IterableMap):
class IgnoresDB(object): class IgnoresDB(object):
__slots__ = ('filename', 'hostmasks')
def __init__(self): def __init__(self):
self.filename = None self.filename = None
self.hostmasks = {} self.hostmasks = {}
@ -1145,9 +1158,11 @@ def checkCapabilities(hostmask, capabilities, requireAll=False):
### ###
class SpaceSeparatedListOfCapabilities(registry.SpaceSeparatedListOfStrings): class SpaceSeparatedListOfCapabilities(registry.SpaceSeparatedListOfStrings):
__slots__ = ()
List = CapabilitySet List = CapabilitySet
class DefaultCapabilities(SpaceSeparatedListOfCapabilities): class DefaultCapabilities(SpaceSeparatedListOfCapabilities):
__slots__ = ()
# We use a keyword argument trick here to prevent eval'ing of code that # We use a keyword argument trick here to prevent eval'ing of code that
# changes allowDefaultOwner from affecting this. It's not perfect, but # changes allowDefaultOwner from affecting this. It's not perfect, but
# it's still an improvement, raising the bar for potential crackers. # it's still an improvement, raising the bar for potential crackers.

View File

@ -191,6 +191,8 @@ def join(names):
class Group(object): class Group(object):
"""A group; it doesn't hold a value unless handled by a subclass.""" """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, def __init__(self, help='', supplyDefault=False,
orderAlphabetically=True, private=False): orderAlphabetically=True, private=False):
self._help = utils.str.normalizeWhitespace(help) self._help = utils.str.normalizeWhitespace(help)
@ -201,7 +203,6 @@ class Group(object):
self._private = private self._private = private
self._supplyDefault = supplyDefault self._supplyDefault = supplyDefault
self._orderAlphabetically = orderAlphabetically self._orderAlphabetically = orderAlphabetically
OriginalClass = self.__class__
self._wasSet = True self._wasSet = True
def __call__(self): def __call__(self):
@ -326,6 +327,8 @@ class _NoValueGiven:
class Value(Group): class Value(Group):
"""Invalid registry value. If you're getting this message, report it, """Invalid registry value. If you're getting this message, report it,
because we forgot to put a proper help string here.""" 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, def __init__(self, default, help, setDefault=True,
showDefault=True, **kwargs): showDefault=True, **kwargs):
self.__parent = super(Value, self) self.__parent = super(Value, self)
@ -421,6 +424,7 @@ class Value(Group):
class Boolean(Value): class Boolean(Value):
"""Value must be either True or False (or On or Off).""" """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.') errormsg = _('Value must be either True or False (or On or Off), not %r.')
def set(self, s): def set(self, s):
try: try:
@ -437,6 +441,7 @@ class Boolean(Value):
class Integer(Value): class Integer(Value):
"""Value must be an integer.""" """Value must be an integer."""
__slots__ = ()
errormsg = _('Value must be an integer, not %r.') errormsg = _('Value must be an integer, not %r.')
def set(self, s): def set(self, s):
try: try:
@ -446,6 +451,7 @@ class Integer(Value):
class NonNegativeInteger(Integer): class NonNegativeInteger(Integer):
"""Value must be a non-negative integer.""" """Value must be a non-negative integer."""
__slots__ = ()
errormsg = _('Value must be a non-negative integer, not %r.') errormsg = _('Value must be a non-negative integer, not %r.')
def setValue(self, v): def setValue(self, v):
if v < 0: if v < 0:
@ -454,6 +460,7 @@ class NonNegativeInteger(Integer):
class PositiveInteger(NonNegativeInteger): class PositiveInteger(NonNegativeInteger):
"""Value must be positive (non-zero) integer.""" """Value must be positive (non-zero) integer."""
__slots__ = ()
errormsg = _('Value must be positive (non-zero) integer, not %r.') errormsg = _('Value must be positive (non-zero) integer, not %r.')
def setValue(self, v): def setValue(self, v):
if not v: if not v:
@ -462,6 +469,7 @@ class PositiveInteger(NonNegativeInteger):
class Float(Value): class Float(Value):
"""Value must be a floating-point number.""" """Value must be a floating-point number."""
__slots__ = ()
errormsg = _('Value must be a floating-point number, not %r.') errormsg = _('Value must be a floating-point number, not %r.')
def set(self, s): def set(self, s):
try: try:
@ -477,6 +485,7 @@ class Float(Value):
class PositiveFloat(Float): class PositiveFloat(Float):
"""Value must be a floating-point number greater than zero.""" """Value must be a floating-point number greater than zero."""
__slots__ = ()
errormsg = _('Value must be a floating-point number greater than zero, ' errormsg = _('Value must be a floating-point number greater than zero, '
'not %r.') 'not %r.')
def setValue(self, v): def setValue(self, v):
@ -487,6 +496,7 @@ class PositiveFloat(Float):
class Probability(Float): class Probability(Float):
"""Value must be a floating point number in the range [0, 1].""" """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], ' errormsg = _('Value must be a floating point number in the range [0, 1], '
'not %r.') 'not %r.')
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -501,6 +511,7 @@ class Probability(Float):
class String(Value): class String(Value):
"""Value is not a valid Python string.""" """Value is not a valid Python string."""
__slots__ = ()
errormsg = _('Value should be a valid Python string, not %r.') errormsg = _('Value should be a valid Python string, not %r.')
def set(self, s): def set(self, s):
v = s v = s
@ -527,6 +538,8 @@ class String(Value):
return s return s
class OnlySomeStrings(String): class OnlySomeStrings(String):
__slots__ = ('__parent', '__dict__') # unfortunately, __dict__ is needed
# to set __doc__.
validStrings = () validStrings = ()
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
assert self.validStrings, 'There must be some valid strings. ' \ assert self.validStrings, 'There must be some valid strings. ' \
@ -559,6 +572,7 @@ class OnlySomeStrings(String):
self.error(v) self.error(v)
class NormalizedString(String): class NormalizedString(String):
__slots__ = ('__parent')
def __init__(self, default, *args, **kwargs): def __init__(self, default, *args, **kwargs):
default = self.normalize(default) default = self.normalize(default)
self.__parent = super(NormalizedString, self) self.__parent = super(NormalizedString, self)
@ -591,6 +605,7 @@ class NormalizedString(String):
return ret return ret
class StringSurroundedBySpaces(String): class StringSurroundedBySpaces(String):
__slots__ = ()
def setValue(self, v): def setValue(self, v):
if v and v.lstrip() == v: if v and v.lstrip() == v:
v= ' ' + v v= ' ' + v
@ -599,6 +614,7 @@ class StringSurroundedBySpaces(String):
super(StringSurroundedBySpaces, self).setValue(v) super(StringSurroundedBySpaces, self).setValue(v)
class StringWithSpaceOnRight(String): class StringWithSpaceOnRight(String):
__slots__ = ()
def setValue(self, v): def setValue(self, v):
if v and v.rstrip() == v: if v and v.rstrip() == v:
v += ' ' v += ' '
@ -606,6 +622,7 @@ class StringWithSpaceOnRight(String):
class Regexp(Value): class Regexp(Value):
"""Value must be a valid regular expression.""" """Value must be a valid regular expression."""
__slots__ = ('sr', 'value', '__parent')
errormsg = _('Value must be a valid regular expression, not %r.') errormsg = _('Value must be a valid regular expression, not %r.')
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
kwargs['setDefault'] = False kwargs['setDefault'] = False
@ -645,6 +662,7 @@ class Regexp(Value):
return self.sr return self.sr
class SeparatedListOf(Value): class SeparatedListOf(Value):
__slots__ = ()
List = list List = list
Value = Value Value = Value
sorted = False sorted = False
@ -681,23 +699,28 @@ class SeparatedListOf(Value):
return ' ' return ' '
class SpaceSeparatedListOf(SeparatedListOf): class SpaceSeparatedListOf(SeparatedListOf):
__slots__ = ()
def splitter(self, s): def splitter(self, s):
return s.split() return s.split()
joiner = ' '.join joiner = ' '.join
class SpaceSeparatedListOfStrings(SpaceSeparatedListOf): class SpaceSeparatedListOfStrings(SpaceSeparatedListOf):
__slots__ = ()
Value = String Value = String
class SpaceSeparatedSetOfStrings(SpaceSeparatedListOfStrings): class SpaceSeparatedSetOfStrings(SpaceSeparatedListOfStrings):
__slots__ = ()
List = set List = set
class CommaSeparatedListOfStrings(SeparatedListOf): class CommaSeparatedListOfStrings(SeparatedListOf):
__slots__ = ()
Value = String Value = String
def splitter(self, s): def splitter(self, s):
return re.split(r'\s*,\s*', s) return re.split(r'\s*,\s*', s)
joiner = ', '.join joiner = ', '.join
class CommaSeparatedSetOfStrings(SeparatedListOf): class CommaSeparatedSetOfStrings(SeparatedListOf):
__slots__ = ()
List = set List = set
Value = String Value = String
def splitter(self, s): def splitter(self, s):
@ -705,6 +728,7 @@ class CommaSeparatedSetOfStrings(SeparatedListOf):
joiner = ', '.join joiner = ', '.join
class TemplatedString(String): class TemplatedString(String):
__slots__ = ()
requiredTemplates = [] requiredTemplates = []
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
assert self.requiredTemplates, \ assert self.requiredTemplates, \
@ -721,6 +745,7 @@ class TemplatedString(String):
self.error(v) self.error(v)
class Json(String): class Json(String):
__slots__ = ()
# Json-serializable data # Json-serializable data
def set(self, v): def set(self, v):
self.setValue(json.loads(v)) self.setValue(json.loads(v))