Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/source/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,13 @@ type of database, set :attr:`~CoreSection.db_type` to one of these values:
* ``firebird``
* ``sybase``

.. note::

In certain environments, specifying the :attr:`~CoreSection.db_url`
setting via :ref:`environment variable <Overriding individual settings>`
may be more convenient. Doing so will supersede all of the other options
described in this section.

SQLite
------

Expand Down
17 changes: 17 additions & 0 deletions sopel/config/core_section.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,23 @@ class CoreSection(StaticSection):

"""

db_url = ValidatedAttribute('db_url')
"""A raw database URL.

If this option is present, Sopel will ignore **all** other ``db_*``
settings and use this option's value only.

.. note::

Specifying this option via the ``SOPEL_CORE_DB_URL`` :ref:`environment
variable <Overriding individual settings>` may prove especially useful
in certain cloud environments, avoiding the need to split a database
URI provided by the platform at runtime into its components with a
startup script.

.. versionadded:: 8.0
"""

db_user = ValidatedAttribute('db_user')
"""The user for Sopel's database.

Expand Down
33 changes: 19 additions & 14 deletions sopel/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import traceback

from sqlalchemy import Column, create_engine, ForeignKey, Integer, String
from sqlalchemy.engine.url import URL
from sqlalchemy.engine.url import make_url, URL
from sqlalchemy.exc import OperationalError, SQLAlchemyError
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker
Expand Down Expand Up @@ -112,12 +112,17 @@ class SopelDB(object):
"""

def __init__(self, config):
# MySQL - mysql://username:password@localhost/db
# SQLite - sqlite:////home/sopel/.sopel/default.db
self.type = config.core.db_type

# Handle SQLite explicitly as a default
if self.type == 'sqlite':
if config.core.db_url is not None:
self.url = make_url(config.core.db_url)

# TODO: there's no way to get `config.core.db_type.choices`, but
# it would be nice to validate this type name somehow. Shouldn't
# affect anything, since the only thing it's ever used for is
# checking whether the configured database is 'sqlite'.
self.type = self.url.drivername.split('+', 1)[0]
elif config.core.db_type == 'sqlite':
self.type = 'sqlite'
drivername = config.core.db_driver or 'sqlite'
path = config.core.db_filename
if path is None:
path = os.path.join(config.core.homedir, config.basename + '.db')
Expand All @@ -132,10 +137,10 @@ def __init__(self, config):
'core.db_filename is valid'.format(os.path.dirname(path)),
path
)
self.filename = path
self.url = 'sqlite:///%s' % path
# Otherwise, handle all other database engines
self.url = make_url('sqlite:///' + path)
else:
self.type = config.core.db_type

query = {}
if self.type == 'mysql':
drivername = config.core.db_driver or 'mysql'
Expand All @@ -153,11 +158,11 @@ def __init__(self, config):
else:
raise Exception('Unknown db_type')

db_user = config.core.db_user
db_pass = config.core.db_pass
db_host = config.core.db_host
db_user = config.core.db_user # Sometimes empty
db_pass = config.core.db_pass # Sometimes empty
db_host = config.core.db_host # Sometimes empty
db_port = config.core.db_port # Optional
db_name = config.core.db_name # Optional, depending on DB
db_name = config.core.db_name # Sometimes optional

# Ensure we have all our variables defined
if db_user is None or db_pass is None or db_host is None:
Expand Down