Skip to content

Commit

Permalink
cli: add --config-dir common option
Browse files Browse the repository at this point in the history
  • Loading branch information
Exirel committed May 12, 2019
1 parent 6e28f98 commit 3ec64c3
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 46 deletions.
29 changes: 15 additions & 14 deletions sopel/cli/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import argparse
import os

from sopel import tools, config
from sopel import tools
from . import utils


Expand All @@ -22,11 +22,13 @@ def build_parser():
# sopel-config list
list_parser = subparsers.add_parser(
'list',
help="List available configurations from Sopel's homedir",
help="List available configurations from Sopel's config directory",
description="""
List available configurations from Sopel's homedir ({homedir})
with the extension "{ext}".
""".format(homedir=config.DEFAULT_HOMEDIR, ext='.cfg'))
List available configurations from Sopel's config directory
with the extension "{ext}". Use option --config-dir to use a
specific config directory.
""".format(ext='.cfg'))
utils.add_common_arguments(list_parser)
list_parser.add_argument(
'-e', '--ext', '--extension',
dest='extension',
Expand Down Expand Up @@ -60,13 +62,13 @@ def build_parser():


def handle_list(options):
"""Display a list of configuration available from Sopel's homedir
"""Display a list of configuration available from Sopel's config directory
:param options: parsed arguments
:type options: ``argparse.Namespace``
This command displays an unordered list of config names from Sopel's
default homedir, without their extensions::
default config directory, without their extensions::
$ sopel-config list
default
Expand All @@ -75,15 +77,16 @@ def handle_list(options):
It is possible to filter by extension using the ``-e/--ext/--extension``
option; default is ``.cfg`` (the ``.`` prefix is not required).
"""
display_path = getattr(options, 'display_path', False)
extension = getattr(options, 'extension', '.cfg')
configdir = options.configdir
display_path = options.display_path
extension = options.extension
if not extension.startswith('.'):
extension = '.' + extension
configs = utils.enumerate_configs(config.DEFAULT_HOMEDIR, extension)
configs = utils.enumerate_configs(configdir, extension)

for config_filename in configs:
if display_path:
print(os.path.join(config.DEFAULT_HOMEDIR, config_filename))
print(os.path.join(configdir, config_filename))
else:
name, _ = os.path.splitext(config_filename)
print(name)
Expand All @@ -101,9 +104,7 @@ def handle_init(options):
extension **must be** ``.cfg``.
"""
config_filename = utils.find_config(
config.DEFAULT_HOMEDIR,
getattr(options, 'config', None) or 'default')
config_filename = utils.find_config(options.configdir, options.config)
config_name, ext = os.path.splitext(config_filename)

if ext and ext != '.cfg':
Expand Down
29 changes: 16 additions & 13 deletions sopel/cli/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,10 @@ def add_legacy_options(parser):
"use `sopel restart` instead)"))
parser.add_argument("-l", '--list', action="store_true",
dest="list_configs",
help="List all config files found")
help=(
"List all config files found"
"(deprecated, and will be removed in Sopel 8; "
"use `sopel-config list` instead)"))
parser.add_argument('--quiet', action="store_true", dest="quiet",
help="Suppress all output")
parser.add_argument('-w', '--configure-all', action='store_true',
Expand Down Expand Up @@ -268,10 +271,10 @@ def print_version():
print('https://sopel.chat/')


def print_config():
"""Print list of available configurations from default homedir."""
configs = utils.enumerate_configs(config.DEFAULT_HOMEDIR)
print('Config files in %s:' % config.DEFAULT_HOMEDIR)
def print_config(configdir):
"""Print list of available configurations from default config directory."""
configs = utils.enumerate_configs(configdir)
print('Config files in %s:' % configdir)
configfile = None
for configfile in configs:
print('\t%s' % configfile)
Expand Down Expand Up @@ -324,7 +327,7 @@ def get_pid_filename(options, pid_dir):
``sopel-{basename}.pid`` instead.
"""
name = 'sopel.pid'
if options.config:
if options.config and options.config != 'default':
basename = os.path.basename(options.config)
if basename.endswith('.cfg'):
basename = basename[:-4]
Expand Down Expand Up @@ -406,9 +409,8 @@ def command_start(opts):

def command_configure(opts):
"""Sopel Configuration Wizard"""
configpath = utils.find_config(
config.DEFAULT_HOMEDIR, opts.config or 'default')
if getattr(opts, 'modules', False):
configpath = utils.find_config(opts.configdir, opts.config)
if opts.modules:
utils.plugins_wizard(configpath)
else:
utils.wizard(configpath)
Expand Down Expand Up @@ -520,9 +522,7 @@ def command_legacy(opts):
print_version()
return

# TODO: allow to use a different homedir
configpath = utils.find_config(
config.DEFAULT_HOMEDIR, opts.config or 'default')
configpath = utils.find_config(opts.configdir, opts.config)

if opts.wizard:
tools.stderr(
Expand All @@ -539,7 +539,10 @@ def command_legacy(opts):
return

if opts.list_configs:
print_config()
tools.stderr(
'WARNING: option --list is deprecated; '
'use `sopel-config list` instead')
print_config(opts.configdir)
return

# Step Two: Get the configuration file and prepare to run
Expand Down
34 changes: 22 additions & 12 deletions sopel/cli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,24 @@ def wizard(filename):
This wizard function helps the creation of a Sopel configuration file,
with its core section and its plugins' sections.
"""
homedir, basename = os.path.split(filename)
configdir, basename = os.path.split(filename)
if not basename:
raise config.ConfigurationError(
'Sopel requires a filename for its configuration, not a directory')

try:
if not os.path.isdir(homedir):
print('Creating config directory at {}'.format(homedir))
os.makedirs(homedir)
if not os.path.isdir(configdir):
print('Creating config directory at {}'.format(configdir))
os.makedirs(configdir)
print('Config directory created')
except Exception:
tools.stderr('There was a problem creating {}'.format(homedir))
tools.stderr('There was a problem creating {}'.format(configdir))
raise

name, ext = os.path.splitext(basename)
if not ext:
# Always add .cfg if filename does not have an extension
filename = os.path.join(homedir, name + '.cfg')
filename = os.path.join(configdir, name + '.cfg')
elif ext != '.cfg':
# It is possible to use a non-cfg file for Sopel
# but the wizard does not allow it at the moment
Expand Down Expand Up @@ -199,17 +199,21 @@ def add_common_arguments(parser):
:type parser: argparse.ArgumentParser
This functions adds the common arguments for Sopel's command line tools.
At the moment, this functions adds only one argument to the parser: the
argument used as the standard way to define a configuration filename.
It adds the following arguments:
* ``-c/--config``: the name of the Sopel config, or its absolute path
* ``--config-dir``: the directory to look for Sopel config
This can be used on an argument parser, or an argument subparser, to handle
these cases::
[sopel-command] -c [filename]
[sopel-command] [action] -c [filename]
[sopel-command] --config-dir [directory] -c [name]
Then, when the parser parses the command line arguments, it will expose
a ``config`` option to be used to find and load Sopel's settings.
``config`` and ``configdir`` options that can be used to find and load
Sopel's settings.
.. seealso::
Expand All @@ -219,10 +223,15 @@ def add_common_arguments(parser):
"""
parser.add_argument(
'-c', '--config',
default=None,
default='default',
metavar='filename',
dest='config',
help='Use a specific configuration file')
help='Use a specific configuration file.')
parser.add_argument(
'--config-dir',
default=config.DEFAULT_HOMEDIR,
dest='configdir',
help='Look for configuration from this Sopel config directory.')


def load_settings(options):
Expand Down Expand Up @@ -262,7 +271,8 @@ def load_settings(options):
elif 'SOPEL_CONFIG' in os.environ:
name = os.environ['SOPEL_CONFIG'] or name # use default if empty

filename = find_config(config.DEFAULT_HOMEDIR, name)
filename = find_config(
getattr(options, 'configdir', config.DEFAULT_HOMEDIR), name)

if not os.path.isfile(filename):
raise config.ConfigurationNotFound(filename=filename)
Expand Down
55 changes: 50 additions & 5 deletions test/cli/test_cli_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def test_build_parser_legacy():

assert isinstance(options, argparse.Namespace)
assert hasattr(options, 'config')
assert hasattr(options, 'configdir')
assert hasattr(options, 'daemonize')
assert hasattr(options, 'quiet')
assert hasattr(options, 'quit')
Expand All @@ -57,7 +58,8 @@ def test_build_parser_legacy():
assert hasattr(options, 'mod_wizard')
assert hasattr(options, 'list_configs')

assert options.config is None
assert options.config == 'default'
assert options.configdir == config.DEFAULT_HOMEDIR
assert options.daemonize is False
assert options.quiet is False
assert options.quit is False
Expand All @@ -79,6 +81,13 @@ def test_build_parser_legacy_config():
assert options.config == 'custom'


def test_build_parser_legacy_configdir():
parser = build_parser()

options = parser.parse_args(['legacy', '--config-dir', 'custom'])
assert options.configdir == 'custom'


def test_build_parser_legacy_daemonize():
parser = build_parser()
options = parser.parse_args(['legacy', '-d'])
Expand Down Expand Up @@ -167,10 +176,12 @@ def test_build_parser_start():

assert isinstance(options, argparse.Namespace)
assert hasattr(options, 'config')
assert hasattr(options, 'configdir')
assert hasattr(options, 'daemonize')
assert hasattr(options, 'quiet')

assert options.config is None
assert options.config == 'default'
assert options.configdir == config.DEFAULT_HOMEDIR
assert options.daemonize is False
assert options.quiet is False

Expand All @@ -185,6 +196,13 @@ def test_build_parser_start_config():
assert options.config == 'custom'


def test_build_parser_start_configdir():
parser = build_parser()

options = parser.parse_args(['start', '--config-dir', 'custom'])
assert options.configdir == 'custom'


def test_build_parser_start_daemonize():
parser = build_parser()

Expand All @@ -209,10 +227,12 @@ def test_build_parser_stop():

assert isinstance(options, argparse.Namespace)
assert hasattr(options, 'config')
assert hasattr(options, 'configdir')
assert hasattr(options, 'kill')
assert hasattr(options, 'quiet')

assert options.config is None
assert options.config == 'default'
assert options.configdir == config.DEFAULT_HOMEDIR
assert options.kill is False
assert options.quiet is False

Expand All @@ -227,6 +247,13 @@ def test_build_parser_stop_config():
assert options.config == 'custom'


def test_build_parser_stop_configdir():
parser = build_parser()

options = parser.parse_args(['stop', '--config-dir', 'custom'])
assert options.configdir == 'custom'


def test_build_parser_stop_kill():
parser = build_parser()

Expand All @@ -251,9 +278,11 @@ def test_build_parser_restart():

assert isinstance(options, argparse.Namespace)
assert hasattr(options, 'config')
assert hasattr(options, 'configdir')
assert hasattr(options, 'quiet')

assert options.config is None
assert options.config == 'default'
assert options.configdir == config.DEFAULT_HOMEDIR
assert options.quiet is False


Expand All @@ -267,6 +296,13 @@ def test_build_parser_restart_config():
assert options.config == 'custom'


def test_build_parser_restart_configdir():
parser = build_parser()

options = parser.parse_args(['restart', '--config-dir', 'custom'])
assert options.configdir == 'custom'


def test_build_parser_restart_quiet():
parser = build_parser()

Expand All @@ -281,9 +317,11 @@ def test_build_parser_configure():

assert isinstance(options, argparse.Namespace)
assert hasattr(options, 'config')
assert hasattr(options, 'configdir')
assert hasattr(options, 'modules')

assert options.config is None
assert options.config == 'default'
assert options.configdir == config.DEFAULT_HOMEDIR
assert options.modules is False


Expand All @@ -297,6 +335,13 @@ def test_build_parser_configure_config():
assert options.config == 'custom'


def test_build_parser_configure_configdir():
parser = build_parser()

options = parser.parse_args(['configure', '--config-dir', 'custom'])
assert options.configdir == 'custom'


def test_build_parser_configure_modules():
parser = build_parser()

Expand Down
Loading

0 comments on commit 3ec64c3

Please sign in to comment.