mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-12-23 19:22:45 +01:00
Aka: Add SQLite3 backend.
This commit is contained in:
parent
1c617ea742
commit
5aa0c8cfbd
@ -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,
|
||||
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/
|
||||
[Twisted]:http://twistedmatrix.com/trac/
|
||||
[SQLAlchemy]:http://www.sqlalchemy.org/
|
||||
|
||||
For more information and help on how to use Supybot, checkout
|
||||
the documents under [docs/], especially [GETTING_STARTED] and
|
||||
|
@ -32,6 +32,7 @@ import re
|
||||
import os
|
||||
import sys
|
||||
import datetime
|
||||
import operator
|
||||
|
||||
import supybot.conf as conf
|
||||
import supybot.utils as utils
|
||||
@ -43,18 +44,166 @@ import supybot.callbacks as callbacks
|
||||
from supybot.i18n import PluginInternationalization
|
||||
_ = PluginInternationalization('Aka')
|
||||
|
||||
try:
|
||||
import sqlite3
|
||||
except ImportError:
|
||||
sqlite3 = None
|
||||
try:
|
||||
import sqlalchemy
|
||||
import sqlalchemy.ext
|
||||
import sqlalchemy.ext.declarative
|
||||
except ImportError:
|
||||
raise callbacks.Error('You have to install python-sqlalchemy in order '
|
||||
'to load this plugin.')
|
||||
sqlalchemy = None
|
||||
|
||||
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()
|
||||
class Alias(Base):
|
||||
class SQLAlchemyAlias(Alias, Base):
|
||||
__slots__ = ()
|
||||
__tablename__ = 'aliases'
|
||||
|
||||
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
|
||||
@ -65,18 +214,10 @@ if sqlalchemy:
|
||||
locked_by = sqlalchemy.Column(sqlalchemy.String, 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
|
||||
|
||||
class SqlAlchemyAkaDB(object):
|
||||
__slots__ = ('engines', 'filename', 'sqlalchemy', 'dbs')
|
||||
def __init__(self, filename):
|
||||
self.engines = ircutils.IrcDict()
|
||||
self.filename = filename
|
||||
@ -105,12 +246,12 @@ if sqlalchemy:
|
||||
name = callbacks.canonicalName(name, preserve_spaces=True)
|
||||
if sys.version_info[0] < 3 and isinstance(name, str):
|
||||
name = name.decode('utf8')
|
||||
count = self.get_db(channel).query(Alias) \
|
||||
.filter(Alias.name == name) \
|
||||
count = self.get_db(channel).query(SQLAlchemyAlias) \
|
||||
.filter(SQLAlchemyAlias.name == name) \
|
||||
.count()
|
||||
return bool(count)
|
||||
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_
|
||||
|
||||
def get_alias(self, channel, name):
|
||||
@ -118,8 +259,8 @@ if sqlalchemy:
|
||||
if sys.version_info[0] < 3 and isinstance(name, str):
|
||||
name = name.decode('utf8')
|
||||
try:
|
||||
return self.get_db(channel).query(Alias.alias) \
|
||||
.filter(Alias.name == name).one()[0]
|
||||
return self.get_db(channel).query(SQLAlchemyAlias.alias) \
|
||||
.filter(SQLAlchemyAlias.name == name).one()[0]
|
||||
except sqlalchemy.orm.exc.NoResultFound:
|
||||
return None
|
||||
|
||||
@ -133,7 +274,7 @@ if sqlalchemy:
|
||||
if isinstance(alias, str):
|
||||
alias = alias.decode('utf8')
|
||||
db = self.get_db(channel)
|
||||
db.add(Alias(name, alias))
|
||||
db.add(SQLAlchemyAlias(name, alias))
|
||||
db.commit()
|
||||
|
||||
def remove_aka(self, channel, name):
|
||||
@ -141,7 +282,7 @@ if sqlalchemy:
|
||||
if sys.version_info[0] < 3 and isinstance(name, str):
|
||||
name = name.decode('utf8')
|
||||
db = self.get_db(channel)
|
||||
db.query(Alias).filter(Alias.name == name).delete()
|
||||
db.query(SQLAlchemyAlias).filter(SQLAlchemyAlias.name == name).delete()
|
||||
db.commit()
|
||||
|
||||
def lock_aka(self, channel, name, by):
|
||||
@ -150,8 +291,8 @@ if sqlalchemy:
|
||||
name = name.decode('utf8')
|
||||
db = self.get_db(channel)
|
||||
try:
|
||||
aka = db.query(Alias) \
|
||||
.filter(Alias.name == name).one()
|
||||
aka = db.query(SQLAlchemyAlias) \
|
||||
.filter(SQLAlchemyAlias.name == name).one()
|
||||
except sqlalchemy.orm.exc.NoResultFound:
|
||||
raise AkaError(_('This Aka does not exist'))
|
||||
if aka.locked:
|
||||
@ -167,8 +308,8 @@ if sqlalchemy:
|
||||
name = name.decode('utf8')
|
||||
db = self.get_db(channel)
|
||||
try:
|
||||
aka = db.query(Alias) \
|
||||
.filter(Alias.name == name).one()
|
||||
aka = db.query(SQLAlchemyAlias) \
|
||||
.filter(SQLAlchemyAlias.name == name).one()
|
||||
except sqlalchemy.orm.exc.NoResultFound:
|
||||
raise AkaError(_('This Aka does not exist'))
|
||||
if not aka.locked:
|
||||
@ -184,11 +325,13 @@ if sqlalchemy:
|
||||
name = name.decode('utf8')
|
||||
try:
|
||||
return self.get_db(channel) \
|
||||
.query(Alias.locked, Alias.locked_by, Alias.locked_at)\
|
||||
.filter(Alias.name == name).one()
|
||||
.query(SQLAlchemyAlias.locked, SQLAlchemyAlias.locked_by, SQLAlchemyAlias.locked_at)\
|
||||
.filter(SQLAlchemyAlias.name == name).one()
|
||||
except sqlalchemy.orm.exc.NoResultFound:
|
||||
raise AkaError(_('This Aka does not exist'))
|
||||
|
||||
available_db.update({'sqlalchemy': SqlAlchemyAkaDB})
|
||||
|
||||
|
||||
def getArgs(args, required=1, optional=0, wildcard=0):
|
||||
if len(args) < required:
|
||||
@ -229,7 +372,7 @@ def findBiggestAt(alias):
|
||||
else:
|
||||
return 0
|
||||
|
||||
AkaDB = plugins.DB('Aka', {'sqlalchemy': SqlAlchemyAkaDB})
|
||||
AkaDB = plugins.DB('Aka', available_db)
|
||||
|
||||
class Aka(callbacks.Plugin):
|
||||
"""Add the help for "@plugin help Aka" here
|
||||
|
Loading…
Reference in New Issue
Block a user