Package: red-postgres
red-postgresPiccolo Postgres integration for Red-DiscordBot, although it could be used with any dpy bot as an easy wrapper for making postgres with cogs more modular.Installpipinstallred-postgresFile structure for using with cogscog-folder/
    ├── db/
    │   ├── migrations/
    │   ├── piccolo_conf.py
    │   ├── piccolo_app.py
    │   ├── tables.py
    ├── __init__.py
    ├── cog.pyCog UsageimportasynciofrompathlibimportPathfrompiccolo.engine.postgresimportPostgresEnginefromredbot.coreimportcommandsfromredbot.core.botimportRedfromred_postgresimportregister_cogfrom.db.tablesimportMyTableclassPiccoloTemplate(commands.Cog):def__init__(self,bot:Red,*args,**kwargs):super().__init__(*args,**kwargs)self.bot=botself.db:PostgresEngine=Noneasyncdefcog_load(self):asyncio.create_task(self.setup())asyncdefsetup(self):awaitself.bot.wait_until_red_ready()config=awaitself.bot.get_shared_api_tokens("piccolo")# Pass the root directory of the cogcog_root=Path(__file__).parentself.db=awaitregister_cog(cog_root,config,[MyTable])asyncdefcog_unload(self):ifself.db:awaitself.db.close_connection_pool()The shared api token config for piccolo should be the following:{"database":"database_name","host":"host ip (127.0.0.1)","port":"port (5432)","user":"user123","password":"password123"}Note: database name in your config should normally be the default "postgres", this library will automatically handle connecting your cogs to their own databaseThe register method connects to the database specified in config, creates the a new database with the name of the registering cog, registers any tables, runs any migrations, sets the new engine object to all tables, and returns the raw engine object.The name of the database will be the the name of the cog's folder, not the name of the main cog.py fileYou can then use your piccolo table methods like so:count=awaitMyTable.count()orobjects=awaitMyTable.objects().where(MyTable.text=="Hello World")The engine associated with your tables after registering the cog is connected to the database named the same as the cog that registered them, thus using this integration with multiple cogs will not interfere, as each cog will create its own database.If your cog's folder name isMyCogthen the database will be namedmy_cogPiccolo Configuration FilesYour piccolo configuration files must be setup like so. This is really only used for migrations.When migrations are run, the os environment variables are mocked in subprocess, so there should be no conflictspiccolo_conf.pyimportosfrompiccolo.conf.appsimportAppRegistryfrompiccolo.engine.postgresimportPostgresEngineDB=PostgresEngine(config={"database":os.environ.get("POSTGRES_DATABASE"),"user":os.environ.get("POSTGRES_USER"),"password":os.environ.get("POSTGRES_PASSWORD"),"host":os.environ.get("POSTGRES_HOST"),"port":os.environ.get("POSTGRES_PORT"),})APP_REGISTRY=AppRegistry(apps=["db.piccolo_app"])piccolo_app.pyimportosfrompiccolo.conf.appsimportAppConfig,table_finderCURRENT_DIRECTORY=os.path.dirname(os.path.abspath(__file__))APP_CONFIG=AppConfig(app_name="cog_name",table_classes=table_finder(["db.tables"]),migrations_folder_path=os.path.join(CURRENT_DIRECTORY,"migrations"),)fortable_classesadd in the list of tables you're usingLocal development and making migrationsHanding migrations is up to you, but one way to do it is to make migrations locally like so:importosimportsubprocessfrompathlibimportPathroot=Path(__file__).parentenv=os.environ.copy()env["PICCOLO_CONF"]="db.piccolo_conf"env["POSTGRES_HOST"]="localhost"env["POSTGRES_PORT"]="5432"env["POSTGRES_USER"]="user"env["POSTGRES_PASSWORD"]="password123!"env["POSTGRES_DATABASE"]="templatecog"env["PYTHONIOENCODING"]="utf-8"defmake():migration_result=subprocess.run(["piccolo","migrations","new",root.name,"--auto"],env=env,cwd=root,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,).stdout.decode()print(migration_result)defrun():run_result=subprocess.run(["piccolo","migrations","forward",root.name],env=env,cwd=root,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,).stdout.decode()print(run_result)if__name__=="__main__":make()run()You would have a similar file in the root of each of your cog folders, here you would create the migrations to include in your cog folder for users to run when they load up the cog.