Skip to content

Commit

Permalink
Merge pull request #1598 from Exirel/cli-homedir-option
Browse files Browse the repository at this point in the history
cli: add --config-dir common option
  • Loading branch information
dgw authored Sep 4, 2019
2 parents d0c0828 + ac56884 commit bff1832
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 54 deletions.
37 changes: 21 additions & 16 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,30 +62,35 @@ def build_parser():


def handle_list(options):
"""Display a list of configuration available from Sopel's homedir
"""Display a list of configurations available in 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::
config directory, without their extensions::
$ sopel-config list
default
custom
It is possible to filter by extension using the ``-e/--ext/--extension``
option; default is ``.cfg`` (the ``.`` prefix is not required).
By default, the config directory is ``~/.sopel``. To select a different
config directory, options ``--config-dir`` can be used.
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 +108,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
33 changes: 18 additions & 15 deletions sopel/cli/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,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 All @@ -152,13 +155,13 @@ def add_legacy_options(parser):
"Run the configuration wizard, but only for the "
"module configuration options "
"(deprecated, and will be removed in Sopel 8; "
"use `sopel configure --modules` instead)"))
"use ``sopel configure --modules`` instead)"))
parser.add_argument('-v', action="store_true",
dest='version_legacy',
help=(
"Show version number and exit "
"(deprecated, and will be removed in Sopel 8; "
"use -V/--version instead)"))
"use ``-V/--version`` instead)"))
parser.add_argument('-V', '--version', action='store_true',
dest='version',
help='Show version number and exit')
Expand Down Expand Up @@ -291,10 +294,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 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 @@ -347,7 +350,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 @@ -429,9 +432,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 @@ -543,9 +545,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 @@ -562,7 +562,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
39 changes: 25 additions & 14 deletions sopel/cli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,24 +78,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 @@ -250,17 +250,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 scan for config files
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 @@ -270,7 +274,7 @@ def add_common_arguments(parser):
"""
parser.add_argument(
'-c', '--config',
default=None,
default='default',
metavar='filename',
dest='config',
help=inspect.cleandoc("""
Expand All @@ -280,6 +284,11 @@ def add_common_arguments(parser):
An absolute pathname can be provided instead to use an
arbitrary location.
"""))
parser.add_argument(
'--config-dir',
default=config.DEFAULT_HOMEDIR,
dest='configdir',
help='Look for configuration files in this directory.')


def load_settings(options):
Expand Down Expand Up @@ -307,9 +316,11 @@ def load_settings(options):
.. note::
To use this function effectively, the
:func:`sopel.cli.utils.add_common_arguments` function should be used to
add the proper option to the argument parser.
This function expects that ``options`` exposes two attributes:
``config`` and ``configdir``.
The :func:`sopel.cli.utils.add_common_arguments` function should be
used to add these options to the argument parser.
"""
# Default if no options.config or no env var or if they are empty
Expand All @@ -319,7 +330,7 @@ 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(options.configdir, name)

if not os.path.isfile(filename):
raise config.ConfigurationNotFound(filename=filename)
Expand Down
Loading

0 comments on commit bff1832

Please sign in to comment.