From 5753195f45eed68184a75a5aca081dca07eded1f Mon Sep 17 00:00:00 2001 From: Jeremy Fincher Date: Fri, 24 Sep 2004 20:05:34 +0000 Subject: [PATCH] Changed dbi.Record not to use a metaclass. --- plugins/FunDB.py | 3 +- plugins/News.py | 5 +-- plugins/Note.py | 3 +- plugins/Project.py | 3 +- plugins/Quotes.py | 7 ++-- src/dbi.py | 81 ++++++++++++++++++++-------------------------- 6 files changed, 46 insertions(+), 56 deletions(-) diff --git a/plugins/FunDB.py b/plugins/FunDB.py index 75e62f9ff..2d329d800 100755 --- a/plugins/FunDB.py +++ b/plugins/FunDB.py @@ -52,8 +52,7 @@ import supybot.privmsgs as privmsgs import supybot.registry as registry import supybot.callbacks as callbacks -class FunDBRecord(object): - __metaclass__ = dbi.Record +class FunDBRecord(dbi.Record): __fields__ = [ 'by', 'text', diff --git a/plugins/News.py b/plugins/News.py index aaf228cd8..5542f4f6e 100644 --- a/plugins/News.py +++ b/plugins/News.py @@ -48,8 +48,7 @@ import supybot.privmsgs as privmsgs import supybot.callbacks as callbacks -class NewsRecord(object): - __metaclass__ = dbi.Record +class NewsRecord(dbi.Record): __fields__ = [ 'subject', 'text', @@ -119,6 +118,8 @@ class SqliteNewsDB(object): subject, text, added_at, expires, by) db.commit() + # XXX This should change only to support id, and the old functionality + # should move out to another method. def get(self, channel, id=None, old=False): db = self._getDb(channel) cursor = db.cursor() diff --git a/plugins/Note.py b/plugins/Note.py index db1232584..4027af58f 100644 --- a/plugins/Note.py +++ b/plugins/Note.py @@ -80,8 +80,7 @@ class Ignores(registry.SpaceSeparatedListOfStrings): conf.registerUserValue(conf.users.plugins.Note, 'ignores', Ignores([], '')) -class NoteRecord(object): - __metaclass__ = dbi.Record +class NoteRecord(dbi.Record): __fields__ = [ 'frm', 'to', diff --git a/plugins/Project.py b/plugins/Project.py index 51b094d07..e7fe53a31 100644 --- a/plugins/Project.py +++ b/plugins/Project.py @@ -67,8 +67,7 @@ conf.registerChannelValue(conf.supybot.plugins.Project, 'default', registry.String('', """Determines what the default project for this channel is.""")) -class Record(object): - __metaclass__ = dbi.Record +class Record(dbi.Record): __fields__ = [ 'desc', 'by', diff --git a/plugins/Quotes.py b/plugins/Quotes.py index bfa039625..2d95b3b21 100644 --- a/plugins/Quotes.py +++ b/plugins/Quotes.py @@ -53,8 +53,7 @@ conf.registerGlobalValue(conf.supybot.plugins.Quotes, 'requireRegistration', registry.Boolean(False, """Determines whether the bot should require people trying to use this plugin to be registered.""")) -class QuoteRecord(object): - __metaclass__ = dbi.Record +class QuoteRecord(dbi.Record): __fields__ = [ 'at', 'by', @@ -136,6 +135,10 @@ class SqliteQuotesDB(object): (id, by, at, text) = cursor.fetchone() return QuoteRecord(id, by=by, at=int(at), text=text) + # XXX This needs to be modified to accept a predicate, and the creation of + # the predicate moved to the plugin. One plugin, many database + # implementations -- we don't want to burden every database implementation + # to do all this work. def search(self, channel, **kwargs): criteria = [] formats = [] diff --git a/src/dbi.py b/src/dbi.py index 0f0808c30..a7bfa138c 100644 --- a/src/dbi.py +++ b/src/dbi.py @@ -300,8 +300,13 @@ class DB(object): yield record def random(self): + # XXX This can be optimized not to deserialize each record. return random.choice(self) + def size(self): + # XXX Likewise as above. + return ilen(self) + def flush(self): self.map.flush() @@ -314,63 +319,47 @@ Mappings = { } -class Record(type): - """__fields should be a list of two-tuples, (name, converter) or - (name, (converter, default)).""" - def __new__(cls, clsname, bases, dict): - defaults = {} - converters = {} - fields = [] - for name in dict['__fields__']: +class Record(object): + def __init__(self, id=None, **kwargs): + if id is not None: + assert isinstance(id, int), 'id must be an integer.' + self.id = id + self.fields = [] + self.defaults = {} + self.converters = {} + for name in self.__fields__: if isinstance(name, tuple): (name, spec) = name else: spec = utils.safeEval - assert name != 'convert' and name != 'id' - fields.append(name) + assert name != 'id' + self.fields.append(name) if isinstance(spec, tuple): (converter, default) = spec else: converter = spec default = None - defaults[name] = default - converters[name] = converter - del dict['__fields__'] + self.defaults[name] = default + self.converters[name] = converter + seen = sets.Set() + for (name, value) in kwargs.iteritems(): + assert name in self.fields, 'name must be a record value.' + seen.add(name) + setattr(self, name, value) + for name in self.fields: + if name not in seen: + setattr(self, name, self.defaults[name]) - def __init__(self, id=None, convert=False, **kwargs): - if id is not None: - assert isinstance(id, int), 'id must be an integer.' - self.id = id - set = sets.Set() - for (name, value) in kwargs.iteritems(): - assert name in fields, 'name must be a record value.' - set.add(name) - if convert: - setattr(self, name, converters[name](value)) - else: - setattr(self, name, value) - for name in fields: - if name not in set: - setattr(self, name, defaults[name]) + def serialize(self): + return csv.join([repr(getattr(self, name)) for name in self.fields]) - def serialize(self): - return csv.join([repr(getattr(self, name)) for name in fields]) - - def deserialize(self, s): - unseenRecords = sets.Set(fields) - for (name, strValue) in zip(fields, csv.split(s)): - setattr(self, name, converters[name](strValue)) - unseenRecords.remove(name) - for name in unseenRecords: - setattr(self, record, defaults[record]) - - dict['__init__'] = __init__ - dict['serialize'] = serialize - dict['deserialize'] = deserialize - return type.__new__(cls, clsname, bases, dict) - - - + def deserialize(self, s): + unseenRecords = sets.Set(self.fields) + for (name, strValue) in zip(self.fields, csv.split(s)): + setattr(self, name, self.converters[name](strValue)) + unseenRecords.remove(name) + for name in unseenRecords: + setattr(self, record, self.defaults[record]) # vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: