MongoDB connection with Motor driver to discord.py bot

34 views Asked by At

I'm attempting to connect a MonogDB database to my discord.py bot for storage of moderation, user and logging data. I'm new to this kind of thing and I'm having issues closing the connection as it keeps raising "object NoneType can't be used in 'await'expression", even though debugging print statements show it isn't a NoneType.

All referenced functions, classes and class objects/methods are defined, just removed for brevity; can provide further source code if needed.

Relevant source code:

import discord
import motor.motor_asyncio
from discord import app_commands
from pymongo.server_api import ServerApi


class DB_handler():
  uri = f'mongodb+srv://ALIXIC_AI:{secret("DB_PASSWORD")}@cluster-1.pw8s6xw.mongodb.net/?retryWrites=true&w=majority&appName=Cluster-1'

  @classmethod
  async def connect(cls):
    motor_client = motor.motor_asyncio.AsyncIOMotorClient(cls.uri, server_api=ServerApi('1'))
    try:
      await motor_client.admin.command('ping')
      conn_message = await style_format("Successfully connected to database\n", "green")
      await Utils.console_message("CONN", conn_message, "CONN")
      print(motor_client)
      return motor_client
    except Exception as e:
      e = str(e)
      conn_message = await style_format(f"Failed to connect to database: {await length_format(e)}\n")
      await Utils.console_message("CONN", conn_message, "CONN")

  @classmethod
  async def close(cls,
                  motor_client):
    if motor_client is not None:
      try:
        await motor_client.close()
        conn_message = await style_format("Safely disconnected from database\n", "green")
        await Utils.console_message("CONN", conn_message, "CONN")
      except Exception as e:
        e = str(e)
        conn_message = await style_format(f"Error while closing database connection: {await length_format(e)}", "red")
        await Utils.console_message("CONN", conn_message, "CONN")
        print()
    else:
      conn_message = await style_format("No active database connection present.\n", "red")
      await Utils.console_message("CONN", conn_message, "CONN")
      print()


@client.tree.command(name = "db_test",
                     description = "DEBUG COMMAND - Developer command to test the database connection")
@app_commands.describe()
async def db_test(interaction: discord.Interaction):
  if not await permission_check(Permissions.development, interaction.user.roles): #pyright: ignore
    message = f"You are not permitted to run this command {interaction.user.mention}"
    await Responses.handler(interaction, message)
  else:
    message = f"Testing database connection - Triggered by {interaction.user.mention}\nSee console for details"
    await Responses.handler(interaction, message)
    db_client = await DB_handler.connect()
    print(db_client)
    print(type(db_client))
    await DB_handler.close(db_client)

Console output:

2024-03-25 13:47:34 INFO     discord.client logging in using static token
2024-03-25 13:47:35 INFO     discord.gateway Shard ID None has connected to Gateway (Session ID: ff5948aeb2fa50ff7e9f8e4e3c2a394a).

2024-03-25 13:47:37 CONN     Alixic AI - Alixic#0320 successfully has connected to [AX] Alixic Incorporated

2024-03-25 13:47:37 ACTN     Uptime tracking started

2024-03-25 13:47:38  CMD     db_test
UID:  ##################     (@iigibbyz)
CID: 1142244524656173106     (#staff-comms)
2024-03-25 13:47:38 RESP     Testing database connection - Triggered by <@##################>
                             See console for details

2024-03-25 13:47:39 CONN     Successfully connected to database

AsyncIOMotorClient(MongoClient(host=['ac-cbuun0h-shard-00-02.pw8s6xw.mongodb.net:27017', 'ac-cbuun0h-shard-00-00.pw8s6xw.mongodb.net:27017', 'ac-cbuun0h-shard-00-01.pw8s6xw.mongodb.net:27017'], document_class=dict, tz_aware=False, connect=False, retrywrites=True, w='majority', appname='Cluster-1', authsource='admin', replicaset='atlas-37pqcs-shard-0', tls=True, server_api=<pymongo.server_api.ServerApi object at 0x7b0519d92170>, driver=DriverInfo(name='Motor', version='3.3.2', platform='asyncio')))
AsyncIOMotorClient(MongoClient(host=['ac-cbuun0h-shard-00-02.pw8s6xw.mongodb.net:27017', 'ac-cbuun0h-shard-00-00.pw8s6xw.mongodb.net:27017', 'ac-cbuun0h-shard-00-01.pw8s6xw.mongodb.net:27017'], document_class=dict, tz_aware=False, connect=False, retrywrites=True, w='majority', appname='Cluster-1', authsource='admin', replicaset='atlas-37pqcs-shard-0', tls=True, server_api=<pymongo.server_api.ServerApi object at 0x7b0519d92170>, driver=DriverInfo(name='Motor', version='3.3.2', platform='asyncio')))
<class 'motor.motor_asyncio.AsyncIOMotorClient'>
2024-03-25 13:47:39 CONN     Error while closing database connection: ["object NoneType can't be used in 'await'
                             expression"]

I modified both the connect and close classmethods to attempt to handle / not provide NoneTypes to no avail. As I'm new, I don't really know where else to go from there.

1

There are 1 answers

0
pabludo8 On

In your case motor_client is a AsyncIOMotorClient, as mentioned in pymongo documentation AsyncIOMotorClient.close is a normal function, not a coroutine. So when doing await motor_client.close() your code is first executing motor_client.close() which returns None and then awaiting None which raises an error. So removing await in the line await motor_client.close() should fix your problem.