mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-23 19:19:32 +01:00
Aka: Add SQLite3 backend.
This commit is contained in:
parent
fb0ef31d94
commit
18708a2678
@ -12,11 +12,8 @@ isn't any way to get around it. You can get it from [Python homepage].
|
|||||||
[Twisted] -- Version 1.2.0 or greater (unless you actually want to use Twisted,
|
[Twisted] -- Version 1.2.0 or greater (unless you actually want to use Twisted,
|
||||||
you don't actually need it)
|
you don't actually need it)
|
||||||
|
|
||||||
[SQLAlchemy] -- If you want the Aka plugin (and probably other plugins in the future)
|
|
||||||
|
|
||||||
[PySQLite]:https://code.google.com/p/pysqlite/
|
[PySQLite]:https://code.google.com/p/pysqlite/
|
||||||
[Twisted]:http://twistedmatrix.com/trac/
|
[Twisted]:http://twistedmatrix.com/trac/
|
||||||
[SQLAlchemy]:http://www.sqlalchemy.org/
|
|
||||||
|
|
||||||
For more information and help on how to use Supybot, checkout
|
For more information and help on how to use Supybot, checkout
|
||||||
the documents under [docs/], especially [GETTING_STARTED] and
|
the documents under [docs/], especially [GETTING_STARTED] and
|
||||||
|
@ -32,6 +32,7 @@ import re
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import datetime
|
import datetime
|
||||||
|
import operator
|
||||||
|
|
||||||
import supybot.conf as conf
|
import supybot.conf as conf
|
||||||
import supybot.utils as utils
|
import supybot.utils as utils
|
||||||
@ -43,18 +44,166 @@ import supybot.callbacks as callbacks
|
|||||||
from supybot.i18n import PluginInternationalization
|
from supybot.i18n import PluginInternationalization
|
||||||
_ = PluginInternationalization('Aka')
|
_ = PluginInternationalization('Aka')
|
||||||
|
|
||||||
|
try:
|
||||||
|
import sqlite3
|
||||||
|
except ImportError:
|
||||||
|
sqlite3 = None
|
||||||
try:
|
try:
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
import sqlalchemy.ext
|
import sqlalchemy.ext
|
||||||
import sqlalchemy.ext.declarative
|
import sqlalchemy.ext.declarative
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise callbacks.Error('You have to install python-sqlalchemy in order '
|
sqlalchemy = None
|
||||||
'to load this plugin.')
|
|
||||||
|
|
||||||
if sqlalchemy:
|
if not (sqlite3 or sqlalchemy):
|
||||||
|
raise callbacks.Error('You have to install python-sqlite3 or '
|
||||||
|
'python-sqlalchemy in order to load this plugin.')
|
||||||
|
|
||||||
|
available_db = {}
|
||||||
|
|
||||||
|
class Alias(object):
|
||||||
|
__slots__ = ('name', 'alias', 'locked', 'locked_by', 'locked_at')
|
||||||
|
def __init__(self, name, alias):
|
||||||
|
self.name = name
|
||||||
|
self.alias = alias
|
||||||
|
self.locked = False
|
||||||
|
self.locked_by = None
|
||||||
|
self.locked_at = None
|
||||||
|
def __repr__(self):
|
||||||
|
return "<Alias('%r', '%r')>" % (self.name, self.alias)
|
||||||
|
if sqlite3:
|
||||||
|
class SQLiteAlias(Alias):
|
||||||
|
__slots__ = ()
|
||||||
|
pass
|
||||||
|
class SQLiteAkaDB(object):
|
||||||
|
__slots__ = ('engines', 'filename', 'dbs',)
|
||||||
|
def __init__(self, filename):
|
||||||
|
self.engines = ircutils.IrcDict()
|
||||||
|
self.filename = filename.replace('sqlite3', 'sqlalchemy')
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.dbs.clear()
|
||||||
|
|
||||||
|
def get_db(self, channel):
|
||||||
|
if channel in self.engines:
|
||||||
|
engine = self.engines[channel]
|
||||||
|
else:
|
||||||
|
filename = plugins.makeChannelFilename(self.filename, channel)
|
||||||
|
exists = os.path.exists(filename)
|
||||||
|
engine = sqlite3.connect(filename, check_same_thread=False)
|
||||||
|
if not exists:
|
||||||
|
cursor = engine.cursor()
|
||||||
|
cursor.execute("""CREATE TABLE aliases (
|
||||||
|
id INTEGER NOT NULL,
|
||||||
|
name VARCHAR NOT NULL,
|
||||||
|
alias VARCHAR NOT NULL,
|
||||||
|
locked BOOLEAN NOT NULL,
|
||||||
|
locked_by VARCHAR,
|
||||||
|
locked_at DATETIME,
|
||||||
|
PRIMARY KEY (id),
|
||||||
|
UNIQUE (name))""")
|
||||||
|
engine.commit()
|
||||||
|
self.engines[channel] = engine
|
||||||
|
assert engine.execute("select 1").fetchone() == (1,)
|
||||||
|
return engine
|
||||||
|
|
||||||
|
|
||||||
|
def has_aka(self, channel, name):
|
||||||
|
name = callbacks.canonicalName(name, preserve_spaces=True)
|
||||||
|
if sys.version_info[0] < 3 and isinstance(name, str):
|
||||||
|
name = name.decode('utf8')
|
||||||
|
db = self.get_db(channel)
|
||||||
|
return self.get_db(channel).cursor() \
|
||||||
|
.execute("""SELECT COUNT() as count
|
||||||
|
FROM aliases WHERE name = ?;""", (name,)) \
|
||||||
|
.fetchone()[0]
|
||||||
|
|
||||||
|
def get_aka_list(self, channel):
|
||||||
|
cursor = self.get_db(channel).cursor()
|
||||||
|
cursor.execute("""SELECT name FROM aliases;""")
|
||||||
|
list_ = cursor.fetchall()
|
||||||
|
return list_
|
||||||
|
|
||||||
|
def get_alias(self, channel, name):
|
||||||
|
name = callbacks.canonicalName(name, preserve_spaces=True)
|
||||||
|
if sys.version_info[0] < 3 and isinstance(name, str):
|
||||||
|
name = name.decode('utf8')
|
||||||
|
cursor = self.get_db(channel).cursor()
|
||||||
|
cursor.execute("""SELECT alias FROM aliases
|
||||||
|
WHERE name = ?;""", (name,))
|
||||||
|
r = cursor.fetchone()
|
||||||
|
if r:
|
||||||
|
return r[0]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def add_aka(self, channel, name, alias):
|
||||||
|
name = callbacks.canonicalName(name, preserve_spaces=True)
|
||||||
|
if self.has_aka(channel, name):
|
||||||
|
raise AkaError(_('This Aka already exists.'))
|
||||||
|
if sys.version_info[0] < 3:
|
||||||
|
if isinstance(name, str):
|
||||||
|
name = name.decode('utf8')
|
||||||
|
if isinstance(alias, str):
|
||||||
|
alias = alias.decode('utf8')
|
||||||
|
db = self.get_db(channel)
|
||||||
|
cursor = db.cursor().execute('SELECT MAX(id) FROM aliases;')
|
||||||
|
max_id = cursor.fetchone()[0]
|
||||||
|
if max_id is None:
|
||||||
|
max_id = 0
|
||||||
|
cursor.execute("""INSERT INTO aliases VALUES (
|
||||||
|
?, ?, ?, 0, NULL, NULL);""", (str(max_id+1), name, alias))
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
def remove_aka(self, channel, name):
|
||||||
|
name = callbacks.canonicalName(name, preserve_spaces=True)
|
||||||
|
if sys.version_info[0] < 3 and isinstance(name, str):
|
||||||
|
name = name.decode('utf8')
|
||||||
|
db = self.get_db(channel)
|
||||||
|
db.cursor().execute('DELETE FROM aliases WHERE name = ?', (name,))
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
def lock_aka(self, channel, name, by):
|
||||||
|
name = callbacks.canonicalName(name, preserve_spaces=True)
|
||||||
|
if sys.version_info[0] < 3 and isinstance(name, str):
|
||||||
|
name = name.decode('utf8')
|
||||||
|
db = self.get_db(channel)
|
||||||
|
cursor = db.cursor().execute("""UPDATE aliases
|
||||||
|
SET locked=1, locked_at=?, locked_by=? WHERE name = ?""",
|
||||||
|
(datetime.datetime.now(), by, name))
|
||||||
|
if cursor.rowcount == 0:
|
||||||
|
raise AkaError(_('This Aka does not exist'))
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
def unlock_aka(self, channel, name, by):
|
||||||
|
name = callbacks.canonicalName(name, preserve_spaces=True)
|
||||||
|
if sys.version_info[0] < 3 and isinstance(name, str):
|
||||||
|
name = name.decode('utf8')
|
||||||
|
db = self.get_db(channel)
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute("""UPDATE aliases SET locked=0, locked_at=?
|
||||||
|
WHERE name = ?""", (datetime.datetime.now(), name))
|
||||||
|
if cursor.rowcount == 0:
|
||||||
|
raise AkaError(_('This Aka does not exist'))
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
def get_aka_lock(self, channel, name):
|
||||||
|
name = callbacks.canonicalName(name, preserve_spaces=True)
|
||||||
|
if sys.version_info[0] < 3 and isinstance(name, str):
|
||||||
|
name = name.decode('utf8')
|
||||||
|
cursor = self.get_db(channel).cursor()
|
||||||
|
cursor.execute("""SELECT locked, locked_by, locked_at
|
||||||
|
FROM aliases WHERE name = ?;""", (name,))
|
||||||
|
r = cursor.fetchone()
|
||||||
|
if r:
|
||||||
|
return (bool(r[0]), r[1], r[2])
|
||||||
|
else:
|
||||||
|
raise AkaError(_('This Aka does not exist'))
|
||||||
|
available_db.update({'sqlite3': SQLiteAkaDB})
|
||||||
|
elif sqlalchemy:
|
||||||
Base = sqlalchemy.ext.declarative.declarative_base()
|
Base = sqlalchemy.ext.declarative.declarative_base()
|
||||||
class Alias(Base):
|
class SQLAlchemyAlias(Alias, Base):
|
||||||
|
__slots__ = ()
|
||||||
__tablename__ = 'aliases'
|
__tablename__ = 'aliases'
|
||||||
|
|
||||||
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
|
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
|
||||||
@ -65,18 +214,10 @@ if sqlalchemy:
|
|||||||
locked_by = sqlalchemy.Column(sqlalchemy.String, nullable=True)
|
locked_by = sqlalchemy.Column(sqlalchemy.String, nullable=True)
|
||||||
locked_at = sqlalchemy.Column(sqlalchemy.DateTime, nullable=True)
|
locked_at = sqlalchemy.Column(sqlalchemy.DateTime, nullable=True)
|
||||||
|
|
||||||
def __init__(self, name, alias):
|
|
||||||
self.name = name
|
|
||||||
self.alias = alias
|
|
||||||
self.locked = False
|
|
||||||
self.locked_by = None
|
|
||||||
self.locked_at = None
|
|
||||||
def __repr__(self):
|
|
||||||
return "<Alias('%r', '%r')>" % (self.name, self.alias)
|
|
||||||
|
|
||||||
# TODO: Add table for usage statistics
|
# TODO: Add table for usage statistics
|
||||||
|
|
||||||
class SqlAlchemyAkaDB(object):
|
class SqlAlchemyAkaDB(object):
|
||||||
|
__slots__ = ('engines', 'filename', 'sqlalchemy', 'dbs')
|
||||||
def __init__(self, filename):
|
def __init__(self, filename):
|
||||||
self.engines = ircutils.IrcDict()
|
self.engines = ircutils.IrcDict()
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
@ -105,12 +246,12 @@ if sqlalchemy:
|
|||||||
name = callbacks.canonicalName(name, preserve_spaces=True)
|
name = callbacks.canonicalName(name, preserve_spaces=True)
|
||||||
if sys.version_info[0] < 3 and isinstance(name, str):
|
if sys.version_info[0] < 3 and isinstance(name, str):
|
||||||
name = name.decode('utf8')
|
name = name.decode('utf8')
|
||||||
count = self.get_db(channel).query(Alias) \
|
count = self.get_db(channel).query(SQLAlchemyAlias) \
|
||||||
.filter(Alias.name == name) \
|
.filter(SQLAlchemyAlias.name == name) \
|
||||||
.count()
|
.count()
|
||||||
return bool(count)
|
return bool(count)
|
||||||
def get_aka_list(self, channel):
|
def get_aka_list(self, channel):
|
||||||
list_ = list(self.get_db(channel).query(Alias.name))
|
list_ = list(self.get_db(channel).query(SQLAlchemyAlias.name))
|
||||||
return list_
|
return list_
|
||||||
|
|
||||||
def get_alias(self, channel, name):
|
def get_alias(self, channel, name):
|
||||||
@ -118,8 +259,8 @@ if sqlalchemy:
|
|||||||
if sys.version_info[0] < 3 and isinstance(name, str):
|
if sys.version_info[0] < 3 and isinstance(name, str):
|
||||||
name = name.decode('utf8')
|
name = name.decode('utf8')
|
||||||
try:
|
try:
|
||||||
return self.get_db(channel).query(Alias.alias) \
|
return self.get_db(channel).query(SQLAlchemyAlias.alias) \
|
||||||
.filter(Alias.name == name).one()[0]
|
.filter(SQLAlchemyAlias.name == name).one()[0]
|
||||||
except sqlalchemy.orm.exc.NoResultFound:
|
except sqlalchemy.orm.exc.NoResultFound:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -133,7 +274,7 @@ if sqlalchemy:
|
|||||||
if isinstance(alias, str):
|
if isinstance(alias, str):
|
||||||
alias = alias.decode('utf8')
|
alias = alias.decode('utf8')
|
||||||
db = self.get_db(channel)
|
db = self.get_db(channel)
|
||||||
db.add(Alias(name, alias))
|
db.add(SQLAlchemyAlias(name, alias))
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
def remove_aka(self, channel, name):
|
def remove_aka(self, channel, name):
|
||||||
@ -141,7 +282,7 @@ if sqlalchemy:
|
|||||||
if sys.version_info[0] < 3 and isinstance(name, str):
|
if sys.version_info[0] < 3 and isinstance(name, str):
|
||||||
name = name.decode('utf8')
|
name = name.decode('utf8')
|
||||||
db = self.get_db(channel)
|
db = self.get_db(channel)
|
||||||
db.query(Alias).filter(Alias.name == name).delete()
|
db.query(SQLAlchemyAlias).filter(SQLAlchemyAlias.name == name).delete()
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
def lock_aka(self, channel, name, by):
|
def lock_aka(self, channel, name, by):
|
||||||
@ -150,8 +291,8 @@ if sqlalchemy:
|
|||||||
name = name.decode('utf8')
|
name = name.decode('utf8')
|
||||||
db = self.get_db(channel)
|
db = self.get_db(channel)
|
||||||
try:
|
try:
|
||||||
aka = db.query(Alias) \
|
aka = db.query(SQLAlchemyAlias) \
|
||||||
.filter(Alias.name == name).one()
|
.filter(SQLAlchemyAlias.name == name).one()
|
||||||
except sqlalchemy.orm.exc.NoResultFound:
|
except sqlalchemy.orm.exc.NoResultFound:
|
||||||
raise AkaError(_('This Aka does not exist'))
|
raise AkaError(_('This Aka does not exist'))
|
||||||
if aka.locked:
|
if aka.locked:
|
||||||
@ -167,8 +308,8 @@ if sqlalchemy:
|
|||||||
name = name.decode('utf8')
|
name = name.decode('utf8')
|
||||||
db = self.get_db(channel)
|
db = self.get_db(channel)
|
||||||
try:
|
try:
|
||||||
aka = db.query(Alias) \
|
aka = db.query(SQLAlchemyAlias) \
|
||||||
.filter(Alias.name == name).one()
|
.filter(SQLAlchemyAlias.name == name).one()
|
||||||
except sqlalchemy.orm.exc.NoResultFound:
|
except sqlalchemy.orm.exc.NoResultFound:
|
||||||
raise AkaError(_('This Aka does not exist'))
|
raise AkaError(_('This Aka does not exist'))
|
||||||
if not aka.locked:
|
if not aka.locked:
|
||||||
@ -184,11 +325,13 @@ if sqlalchemy:
|
|||||||
name = name.decode('utf8')
|
name = name.decode('utf8')
|
||||||
try:
|
try:
|
||||||
return self.get_db(channel) \
|
return self.get_db(channel) \
|
||||||
.query(Alias.locked, Alias.locked_by, Alias.locked_at)\
|
.query(SQLAlchemyAlias.locked, SQLAlchemyAlias.locked_by, SQLAlchemyAlias.locked_at)\
|
||||||
.filter(Alias.name == name).one()
|
.filter(SQLAlchemyAlias.name == name).one()
|
||||||
except sqlalchemy.orm.exc.NoResultFound:
|
except sqlalchemy.orm.exc.NoResultFound:
|
||||||
raise AkaError(_('This Aka does not exist'))
|
raise AkaError(_('This Aka does not exist'))
|
||||||
|
|
||||||
|
available_db.update({'sqlalchemy': SqlAlchemyAkaDB})
|
||||||
|
|
||||||
|
|
||||||
def getArgs(args, required=1, optional=0, wildcard=0):
|
def getArgs(args, required=1, optional=0, wildcard=0):
|
||||||
if len(args) < required:
|
if len(args) < required:
|
||||||
@ -229,7 +372,7 @@ def findBiggestAt(alias):
|
|||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
AkaDB = plugins.DB('Aka', {'sqlalchemy': SqlAlchemyAkaDB})
|
AkaDB = plugins.DB('Aka', available_db)
|
||||||
|
|
||||||
class Aka(callbacks.Plugin):
|
class Aka(callbacks.Plugin):
|
||||||
"""Add the help for "@plugin help Aka" here
|
"""Add the help for "@plugin help Aka" here
|
||||||
|
Loading…
Reference in New Issue
Block a user