Add database submodule for easy db access
This commit is contained in:
parent
db07cdf17b
commit
2e7b364307
5 changed files with 207 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1 +1,2 @@
|
|||
yaboli/__pycache__/
|
||||
*.db
|
||||
|
|
|
|||
25
DBTest.py
Normal file
25
DBTest.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import asyncio
|
||||
import yaboli
|
||||
|
||||
|
||||
|
||||
class ExampleDB(yaboli.Database):
|
||||
@yaboli.Database.operation
|
||||
def sample_operation(connection, *args):
|
||||
print(args)
|
||||
#return a + b
|
||||
print("returning 15...")
|
||||
return 15
|
||||
|
||||
async def run():
|
||||
db = ExampleDB("test.db")
|
||||
print(db.sample_operation)
|
||||
#print(db.sample_operation(1, 2))
|
||||
result = await db.sample_operation(1, 2)
|
||||
print(result)
|
||||
|
||||
def main():
|
||||
asyncio.get_event_loop().run_until_complete(run())
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
92
TemplateBot.py
Normal file
92
TemplateBot.py
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
"""
|
||||
Copy this template script and modify it to create a new bot.
|
||||
"""
|
||||
|
||||
import yaboli
|
||||
from yaboli.utils import *
|
||||
import sys
|
||||
|
||||
|
||||
|
||||
class YourBot(yaboli.Bot):
|
||||
"""
|
||||
Your bot's docstring
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("Your bot's name")
|
||||
|
||||
# set help and other settings here
|
||||
#self.help_general = None
|
||||
#self.help_specific = "No help available"
|
||||
#self.killable = True
|
||||
#self.kill_message = "/me *poof*"
|
||||
#self.restartable = True
|
||||
#self.restart_message = "/me temporary *poof*"
|
||||
|
||||
# Event callbacks - just fill in your code.
|
||||
# If the function contains a super(), DON'T remove it unless you know what you're doing!
|
||||
# (You can remove the function itself though.)
|
||||
# When you're done, remove all unneeded functions.
|
||||
|
||||
async def on_connected(self):
|
||||
await super().on_connected()
|
||||
|
||||
async def on_disconnected(self):
|
||||
await super().on_disconnected()
|
||||
|
||||
async def on_bounce(self, reason=None, auth_options=[], agent_id=None, ip=None):
|
||||
await super().on_bounce(reason, auth_options, agent_id, ip)
|
||||
|
||||
async def on_disconnect(self, reason):
|
||||
pass
|
||||
|
||||
async def on_hello(self, user_id, session, room_is_private, version, account=None,
|
||||
account_has_access=None, account_email_verified=None):
|
||||
pass
|
||||
|
||||
async def on_join(self, session):
|
||||
pass
|
||||
|
||||
async def on_login(self, account_id):
|
||||
pass
|
||||
|
||||
async def on_logout(self):
|
||||
pass
|
||||
|
||||
async def on_network(self, ntype, server_id, server_era):
|
||||
pass
|
||||
|
||||
async def on_nick(self, session_id, user_id, from_nick, to_nick):
|
||||
pass
|
||||
|
||||
async def on_edit_message(self, edit_id, message):
|
||||
pass
|
||||
|
||||
async def on_part(self, session):
|
||||
pass
|
||||
|
||||
async def on_ping(self, ptime, pnext):
|
||||
await super().on_ping(ptime, pnext)
|
||||
|
||||
async def on_pm_initiate(self, from_id, from_nick, from_room, pm_id):
|
||||
pass
|
||||
|
||||
async def on_send(self, message):
|
||||
await super().on_send(message) # This is where yaboli.bot reacts to commands
|
||||
|
||||
async def on_snapshot(self, user_id, session_id, version, listing, log, nick=None,
|
||||
pm_with_nick=None, pm_with_user_id=None):
|
||||
await super().on_snapshot(user_id, session_id, version, listing, log, nick, pm_with_nick,
|
||||
pm_with_user_id)
|
||||
|
||||
def main():
|
||||
if len(sys.argv) == 2:
|
||||
run_bot(YourBot, sys.argv[1])
|
||||
else:
|
||||
print("USAGE:")
|
||||
print(f" {sys.argv[0]} <room>")
|
||||
return
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -10,6 +10,7 @@ logger.setLevel(logging.INFO)
|
|||
from .bot import *
|
||||
from .connection import *
|
||||
from .controller import *
|
||||
from .database import *
|
||||
from .room import *
|
||||
from .utils import *
|
||||
|
||||
|
|
|
|||
88
yaboli/database.py
Normal file
88
yaboli/database.py
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
import asyncio
|
||||
from functools import wraps
|
||||
import sqlite3
|
||||
import threading
|
||||
|
||||
__all__ = ["Database"]
|
||||
|
||||
|
||||
|
||||
def shielded(afunc):
|
||||
#@wraps(afunc)
|
||||
async def wrapper(*args, **kwargs):
|
||||
return await asyncio.shield(afunc(*args, **kwargs))
|
||||
return wrapper
|
||||
|
||||
class PooledConnection:
|
||||
def __init__(self, pool):
|
||||
self._pool = pool
|
||||
|
||||
self.connection = None
|
||||
|
||||
async def open(self):
|
||||
self.connection = await self._pool._request()
|
||||
print(self.connection)
|
||||
|
||||
async def close(self):
|
||||
conn = self.connection
|
||||
self.connection = None
|
||||
await self._pool._return(conn)
|
||||
|
||||
async def __aenter__(self):
|
||||
await self.open()
|
||||
return self
|
||||
|
||||
async def __aexit__(self, exc_type, exc, tb):
|
||||
await self.close()
|
||||
|
||||
class Pool:
|
||||
def __init__(self, filename, size=10):
|
||||
self.filename = filename
|
||||
self.size = size
|
||||
|
||||
self._available_connections = asyncio.Queue()
|
||||
|
||||
for i in range(size):
|
||||
conn = sqlite3.connect(self.filename, check_same_thread=False)
|
||||
self._available_connections.put_nowait(conn)
|
||||
|
||||
def connection(self):
|
||||
return PooledConnection(self)
|
||||
|
||||
async def _request(self):
|
||||
return await self._available_connections.get()
|
||||
|
||||
async def _return(self, conn):
|
||||
await self._available_connections.put(conn)
|
||||
|
||||
class Database:
|
||||
def __init__(self, filename, pool_size=10, event_loop=None):
|
||||
self._filename = filename
|
||||
self._pool = Pool(filename, size=pool_size)
|
||||
self._loop = event_loop or asyncio.get_event_loop()
|
||||
|
||||
def operation(func):
|
||||
@wraps(func)
|
||||
@shielded
|
||||
async def wrapper(self, *args, **kwargs):
|
||||
async with self._pool.connection() as conn:
|
||||
return await self._run_in_thread(func, conn.connection, *args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
@staticmethod
|
||||
def _target_function(loop, future, func, *args, **kwargs):
|
||||
result = None
|
||||
try:
|
||||
result = func(*args, **kwargs)
|
||||
finally:
|
||||
loop.call_soon_threadsafe(future.set_result, result)
|
||||
|
||||
async def _run_in_thread(self, func, *args, **kwargs):
|
||||
finished = asyncio.Future()
|
||||
target_args = (self._loop, finished, func, *args)
|
||||
|
||||
thread = threading.Thread(target=self._target_function, args=target_args, kwargs=kwargs)
|
||||
thread.start()
|
||||
|
||||
await finished
|
||||
return finished.result()
|
||||
Loading…
Add table
Add a link
Reference in a new issue