Skip to content

Application

The Application class is the core of every Grace bot. It manages configuration, the database engine and session, model discovery, extension discovery, and logging. Every generated project instantiates exactly one Application in bot/__init__.py, alongside the Bot that wraps it.

from grace.application import Application

app = Application()
app.load()  # sets the environment and wires up logging, models, and the database

grace.application.Application

Application()

This class is the core of the application In other words, this class that manage the database, the application environment and loads the configurations.

Source code in grace/application.py
32
33
34
35
36
37
38
def __init__(self) -> None:
    self.__token: str = str(self.config.get("discord", "token"))
    self.__engine: Union[Engine, None] = None

    self.environment: str = "development"
    self.command_sync: bool = True
    self.watch: bool = False

environment instance-attribute

environment = 'development'

command_sync instance-attribute

command_sync = True

watch instance-attribute

watch = False

metadata property

metadata

token property

token

session property

session

Instantiate the session for querying the database.

config property

config

client property

client

extension_modules property

extension_modules

Generate the extensions modules

has_database property

has_database

database_infos property

database_infos

database_exists property

database_exists

get_extension_module

get_extension_module(extension_name)

Return the extension from the given extension name

Source code in grace/application.py
102
103
104
105
106
107
108
def get_extension_module(self, extension_name) -> Union[str, None]:
    """Return the extension from the given extension name"""

    for extension in self.extension_modules:
        if extension == extension_name:
            return extension
    return None

load

load(env=None)

Sets the environment and loads all the component of the application

Source code in grace/application.py
110
111
112
113
114
115
116
117
118
119
def load(self, env: Optional[str] = None):
    """
    Sets the environment and loads all the component of the application
    """
    self.environment = env or environ.get("GRACE_ENV") or "development"
    self.config.set_environment(self.environment)

    self.load_logs()
    self.load_models()
    self.load_database()

load_models

load_models()

Import all models in the bot/models package.

Source code in grace/application.py
121
122
123
124
125
126
def load_models(self):
    """Import all models in the `bot/models` package."""
    from bot import models

    for module in find_all_importables(models):
        import_module(module)

load_logs

load_logs()
Source code in grace/application.py
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
def load_logs(self) -> None:
    file_handler: RotatingFileHandler = RotatingFileHandler(
        f"logs/{self.config.current_environment}.log", maxBytes=10000, backupCount=5
    )

    basicConfig(
        level=self.config.environment.get("log_level"),
        format="[%(asctime)s] %(funcName)s %(levelname)s %(message)s",
        handlers=[file_handler],
    )

    install(
        self.config.environment.get("log_level"),
        fmt="".join(
            [
                "[%(asctime)s] %(programname)s %(funcName)s ",
                "%(module)s %(levelname)s %(message)s",
            ]
        ),
        programname=self.config.current_environment,
    )

load_database

load_database()

Loads and connects to the database using the loaded config

Source code in grace/application.py
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
def load_database(self) -> None:
    """Loads and connects to the database using the loaded config"""

    database_uri = self.config.database_uri

    if not database_uri:
        return

    self.__engine = create_engine(
        database_uri,
        echo=self.config.environment.getboolean("sqlalchemy_echo"),
    )

    if self.database_exists:
        try:
            self.__engine.connect()
        except OperationalError as e:
            critical(f"Unable to load the 'database': {e}")

    Model.set_engine(self.__engine)

unload_database

unload_database()

Unloads the current database

Source code in grace/application.py
171
172
173
174
175
def unload_database(self):
    """Unloads the current database"""

    self.__engine = None
    self.__session = None

reload_database

reload_database()

Reload the database. This function can be used in case there's a dynamic environment change.

Source code in grace/application.py
177
178
179
180
181
182
183
184
def reload_database(self):
    """
    Reload the database. This function can be used in case
    there's a dynamic environment change.
    """

    self.unload_database()
    self.load_database()

create_database

create_database()

Creates the database for the current loaded config

Source code in grace/application.py
186
187
188
189
190
191
def create_database(self):
    """Creates the database for the current loaded config"""

    self._require_database()
    self.load_database()
    create_database(self.config.database_uri)

drop_database

drop_database()

Drops the database for the current loaded config

Source code in grace/application.py
193
194
195
196
197
198
def drop_database(self):
    """Drops the database for the current loaded config"""

    self._require_database()
    self.load_database()
    drop_database(self.config.database_uri)

create_tables

create_tables()

Creates all the tables for the current loaded database

Source code in grace/application.py
200
201
202
203
204
205
206
207
208
209
def create_tables(self):
    """Creates all the tables for the current loaded database"""

    self._require_database()

    if not self.__engine:
        raise RuntimeError("Database engine is not initialized.")

    self.load_database()
    self.metadata.create_all(self.__engine)

drop_tables

drop_tables()

Drops all the tables for the current loaded database

Source code in grace/application.py
211
212
213
214
215
216
217
218
219
220
def drop_tables(self):
    """Drops all the tables for the current loaded database"""

    self._require_database()

    if not self.__engine:
        raise RuntimeError("Database engine is not initialized.")

    self.load_database()
    self.metadata.drop_all(self.__engine)