Repository: sopel-irc/sopel

Issue:
db_filename is relative to the directory where the config file resides
This should be relative to homedir. The way is currently handle makes no sense IMO.



Discussion:
If you want relative to homedir, use ~. This behavior is relatively common.
On Mar 23, 2016 6:35 PM, "Federico G. Schwindt" notifications@github.com
wrote:

> This should be relative to homedir. The way is currently handle makes no
> sense IMO.
> 
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly or view it on GitHub
> https://github.com/sopel-irc/sopel/issues/1047

I appreciate you can override it and that's what I did. However I believe this should be the default behaviour.

`~` is a de facto standard in the *nix world that represents the home directory of the user running a process. While one could argue that `.` as a reference to the current directory is equally common, and thus a path beginning `./` is clearly meant to be relative, I believe it is more common to default to a path relative to the current file. For example, configurations in nginx and apache that include other files look in the current directory first, too, not the webserver's home directory.

Long story short, it's a common convention that file references in configuration files are relative to the directory of the file they're in, unless otherwise specified by a leading `~` or `/`. For that reason, I doubt this will be changed in sopel.

@dgw I appreciate that and that is indeed the way nginx and other software handles it.
In this particular case I don't think it's correct though.
To start, the `homedir` options reads:

```
homedir
The directory in which various files are stored at runtime.

By default, this is the same directory as the config. It can not be changed at runtime.
```

So by default, if `homedir` is not defined, the directory where the configuration resides it's used.
If `homedir` is defined, however, I'd expect it to take over since `homedir` is **_the directory in which various files are stored at runtime**_. `db_filename` falls into this category AFAICT.

In fact, if you set `homedir` the only file stored outside `homedir` is the database.

If we take a look at `db_filename`:

```
db_filename
The filename for Sopel’s database.
```

There is no mention about location or being special wrt homedir.

As such I think this is incorrect. It doesn't follow how other files are stored. Having to define both _homedir_ and _db_filename_ is IMO a bug.

Oh, you're referring to the config setting `homedir`, not the concept of a user's home directory. I agree, `db_filename` should be relative to that setting, and relative to the config file if unset. Since this would change some existing configurations, it'd probably be best to have input from @embolalia too.

Yes, `homedir`. I didn't mention the user's homedir.
It's better to not [assume](http://uncyclopedia.wikia.com/wiki/Assume) :smile: 

It's also better to be specific. The initial exchange really did sound like you meant the user's homedir, especially after Max pointed out the use of `~` and you said that's what should be default behavior.

Communicating is hard sometimes. But yes, now that I know that you mean `bot.config.core.homedir` (as it's referenced in the code) and not `~` I agree, too. :smile:


Resolving patch:
diff --git a/sopel/db.py b/sopel/db.py
--- a/sopel/db.py
+++ b/sopel/db.py
@@ -1,6 +1,7 @@
 # coding=utf-8
 from __future__ import unicode_literals, absolute_import, print_function, division
 
+import errno
 import json
 import os.path
 import sys
@@ -87,8 +88,9 @@ class SopelDB(object):
     database. It simplifies those common operations, and allows direct access
     to the database, wherever the user has configured it to be.
 
-    When configured with a relative filename, it is assumed to be in the same
-    directory as the config."""
+    When configured with a relative filename, it is assumed to be in the directory
+    set (or defaulted to) in the core setting ``homedir``.
+    """
 
     def __init__(self, config):
         # MySQL - mysql://username:password@localhost/db
@@ -98,13 +100,19 @@ def __init__(self, config):
         # Handle SQLite explicitly as a default
         if db_type == 'sqlite':
             path = config.core.db_filename
-            config_dir, config_file = os.path.split(config.filename)
-            config_name, _ = os.path.splitext(config_file)
             if path is None:
-                path = os.path.join(config_dir, config_name + '.db')
+                path = os.path.join(config.core.homedir, config.basename + '.db')
             path = os.path.expanduser(path)
             if not os.path.isabs(path):
-                path = os.path.normpath(os.path.join(config_dir, path))
+                path = os.path.normpath(os.path.join(config.core.homedir, path))
+            if not os.path.isdir(os.path.dirname(path)):
+                raise OSError(
+                    errno.ENOENT,
+                    'Cannot create database file. '
+                    'No such directory: "{}". Check that configuration setting '
+                    '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


Test patch: