Source code for score.cli.conf

# vim: set fileencoding=UTF-8
# Copyright © 2015-2017 STRG.AT GmbH, Vienna, Austria
#
# This file is part of the The SCORE Framework.
#
# The SCORE Framework and all its parts are free software: you can redistribute
# them and/or modify them under the terms of the GNU Lesser General Public
# License version 3 as published by the Free Software Foundation which is in the
# file named COPYING.LESSER.txt.
#
# The SCORE Framework and all its parts are distributed without any WARRANTY;
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. For more details see the GNU Lesser General Public
# License.
#
# If you have not received a copy of the GNU Lesser General Public License see
# http://www.gnu.org/licenses/.
#
# The License-Agreement realised between you as Licensee and STRG.AT GmbH as
# Licenser including the issue of its valid conclusion and its pre- and
# post-contractual effects is governed by the laws of Austria. Any disputes
# concerning this License-Agreement including the issue of its valid conclusion
# and its pre- and post-contractual effects are exclusively decided by the
# competent court, in whose district STRG.AT GmbH has its registered seat, at
# the discretion of STRG.AT GmbH also the competent court, in whose district the
# Licensee has his registered seat, an establishment or assets.

import os
import sys
import re
from score.init import parse_config_file as parse
from collections import OrderedDict
import textwrap


class InvalidConfigurationNameException(ValueError):
    """
    Raised when a configuration is registered with a bogus name.
    """


[docs]def venv_root(venv=None): """ Provides the root folder of the current virtual environment. Returns `None`, if this python process is not running inside a virtual environment. In order to provide a similar interface to the other functions in this package, it also accepts a *venv* parameter. Since that parameter is expected to be the root of a virtual environment, it will be returned, if it is passed. """ if venv is not None: return venv if hasattr(sys, 'real_prefix'): return sys.prefix if hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix: return sys.prefix # check for local installation home = os.getenv('HOME') or os.getenv('HOMEPATH') if sys.prefix.startswith(home): # the sys.prefix is inside the current user's home folder, so we're # assuming that this is a local installation by the user. # this scenario also includes python versions installed via conda, for # example. return sys.prefix return None
[docs]def rootdir(*, global_=False, venv=None): """ Provides the current ``.score`` folder. This function will determine the valid path of the configuration folder for the current environment, as described in the narrative documentation of the :ref:`configuration locations <score_cli_config_locations>`. It is possible to retrieve the configuration folder in one's home directory by passing a truthy value for *global_*. It is also possible to access the configuration folder of a different virtual environment by passing the *venv* parameter (the path to a virtual environment). """ if global_: if venv is not None: raise ValueError('Parameters *global_* and *venv* are mutually ' 'exclusive') root = os.getenv('HOME') or os.getenv('HOMEPATH') else: root = venv_root(venv) if not root: root = os.getenv('HOME') or os.getenv('HOMEPATH') return os.path.join(root, '.score')
[docs]def add(name, path, *, venv=None): """ Adds a configuration with given *name*, pointing to the configuration file at *path*. The name must not start with two underscores, must consist of alphanumeric characters, underscores and hyphens and must not start with a number or a hyphen. Will raise an InvalidConfigurationNameException violates these constraints. Can also operate on a given virtual environment if the *venv* parameter is not `None`. The specifics of this behaviour is documented in :func:`.rootdir`. """ if name.startswith('__') or not re.match('^[a-zA-Z_][a-zA-Z0-9_-]*$', name): raise InvalidConfigurationNameException(name) root = rootdir(venv=venv) root = os.path.join(root, 'conf') os.makedirs(root, exist_ok=True) file = os.path.join(root, name) open(file, 'w').write(textwrap.dedent(''' [score.init] based_on = %s %s ''' % (global_file(), path)))
[docs]def remove(name, *, venv=None): """ Deletes the configuration with given *name*. Can also operate on a given virtual environment if the *venv* parameter is not `None`. The specifics of this behaviour is documented in :func:`.rootdir`. """ file = os.path.join(rootdir(venv=venv), 'conf', name) try: os.unlink(file) except FileNotFoundError: pass
[docs]def make_default(name, *, venv=None): """ Updates the current environment's default configuration to point to the configuration with given *name*. Can also operate on a given virtual environment if the *venv* parameter is not `None`. The specifics of this behaviour is documented in :func:`.rootdir`. """ root = rootdir(venv=venv) file = os.path.join(root, 'conf', name) if not os.path.exists(file): raise FileNotFoundError(file) open(default_file(venv=venv), 'w').write(textwrap.dedent(''' [score.init] based_on = ${here}/%s ''' % name).lstrip())
[docs]def get_file(name, *, venv=None): """ Returns the file the configuration with given *name* is pointing to. Can also operate on a given virtual environment if the *venv* parameter is not `None`. The specifics of this behaviour is documented in :func:`.rootdir`. """ return name2file(venv=venv)[name]
[docs]def get_default(*, venv=None): """ Returns the name of the default configuration. Can also operate on a given virtual environment if the *venv* parameter is not `None`. The specifics of this behaviour is documented in :func:`.rootdir`. """ try: return os.path.basename(get_origin(default_file(venv=venv))) except FileNotFoundError: return None
[docs]def name2file(*, include_global=True, venv=None): """ Returns the names of all available configurations. Will list all configurations in the current virtual environment, as well as all global configuration files, unless *include_global* is `False`. Can also operate on a given virtual environment if the *venv* parameter is not `None`. The specifics of this behaviour is documented in :func:`.rootdir`. """ files = {} if include_global: folder = os.getenv('HOME') or os.getenv('HOMEPATH') folder = os.path.join(folder, '.score', 'conf') try: for file in os.listdir(folder): files[file] = os.path.join(folder, file) except FileNotFoundError: pass folder = venv_root(venv) if folder: folder = os.path.join(folder, '.score', 'conf') try: for file in os.listdir(folder): files[file] = os.path.join(folder, file) except FileNotFoundError: pass sortedfiles = OrderedDict() for name in sorted(files): if name.startswith('__'): continue sortedfiles[name] = files[name] return sortedfiles
[docs]def global_file(): """ Returns the path to the global configuration file. Although the return value of this function is always the same, it ensures that the file actually exists by creating it with some informative comments. """ file = os.path.join(rootdir(global_=True), 'conf', '__global__') os.makedirs(os.path.dirname(file), exist_ok=True) try: open(file, 'x').write(textwrap.dedent(''' # This is the global CLI configuration file for your SCORE # installation. The values defined here will be available in # *all* your command line applications. ''').lstrip()) except FileExistsError: pass return file
[docs]def default_file(*, global_=False, venv=None): """ Returns the path to the default configuration in the current environment. This function will create that file, if it does not exist. Can also operate on a given virtual environment if the *venv* parameter is not `None`. The specifics of this behaviour is documented in :func:`.rootdir`. """ file = os.path.join(rootdir(global_=global_, venv=venv), 'conf', '__default__') os.makedirs(os.path.dirname(file), exist_ok=True) try: open(file, 'x').write(textwrap.dedent(''' [score.init] based_on = %s ''' % global_file()).lstrip()) except FileExistsError: pass return file
[docs]def get_origin(file): """ Parses given configuration file and finds the file this one is :func:`based_on <score.init.parse_config_file>`. """ parsedconf = parse(file, recurse=False) base = parsedconf['score.init']['based_on'] if '\n' in base: base = base.split('\n')[-1] return base