new: add a cli.config_dir

This commit is contained in:
Zach White 2021-08-09 21:07:10 -07:00
parent c1592e19a9
commit 4e2a63ae76
5 changed files with 47 additions and 23 deletions

View file

@ -8,7 +8,7 @@ PYTHON_ARGCOMPLETE_OK
import os
from pathlib import Path
from shutil import rmtree
from subprocess import CalledProcessError, run
from subprocess import CalledProcessError, DEVNULL, run
from milc import set_metadata
@ -26,19 +26,19 @@ def main(cli):
cli.log.info('Running nose2 tests...')
cmd = ['nose2']
result = run(cmd)
result = run(cmd, stdin=DEVNULL)
if result.returncode != 0:
build_ok = False
cli.log.info('Running flake8...')
cmd = ['flake8']
result = run(cmd)
result = run(cmd, stdin=DEVNULL)
if result.returncode != 0:
build_ok = False
cli.log.info('Running yapf...')
cmd = ['yapf', '-q', '-r', '.']
result = run(cmd)
result = run(cmd, stdin=DEVNULL)
if result.returncode != 0:
build_ok = False
cli.log.error('Improperly formatted code. Please run this: yapf -i -r .')

View file

@ -32,16 +32,19 @@ Use `cli.save_config()` to save the user's configuration file. It will be writte
# Configuration File Location
MILC uses [appdirs](https://github.com/ActiveState/appdirs) to determine the configuration file location. You can set your application's name and author by setting environment variables:
MILC uses [appdirs](https://github.com/ActiveState/appdirs) to determine the configuration file location. You can set your application's name and author by using `milc.set_metadata`:
os.environ['MILC_APP_NAME'] = 'hello'
os.environ['MILC_AUTHOR_NAME'] = 'Hello Author'
```python
from milc import set_metadata
set_metadata('Florzelbop', '1.0.0', 'Jane Doe')
```
This will (usually) result in the following config file locations:
* Linux: `~/.local/share/hello`
* macOS: `~/Library/Application Support/hello`
* Windows: `C:\Documents and Settings\<User>\Application Data\Local Settings\Hello Author\hello`
* Linux: `~/.local/share/Florzelbop`
* macOS: `~/Library/Application Support/Florzelbop`
* Windows: `C:\Documents and Settings\<User>\Application Data\Local Settings\Florzelbop Jane Doe\hello`
# Where Did A Value Come From?

View file

@ -68,5 +68,11 @@ def goodbye(cli):
cli.echo('{fg_blue}Goodbye, %s!', cli.config.general.name)
@cli.subcommand('Show the configured config file and directory.')
def config_file(cli):
cli.echo(f'cli.config_file={cli.config_file}')
cli.echo(f'cli.config_dir={cli.config_dir}')
if __name__ == '__main__':
cli()

View file

@ -7,6 +7,7 @@ import subprocess
import shlex
import sys
from decimal import Decimal
from functools import lru_cache
from pathlib import Path
from platform import platform
from tempfile import NamedTemporaryFile
@ -44,6 +45,7 @@ class MILC(object):
# Define some basic info
self.acquire_lock()
self.prog_name = name
self.version = version
self.author = author
self._config_store_true = []
@ -55,10 +57,9 @@ class MILC(object):
self._inside_context_manager = False
self.ansi = ansi_colors
self.arg_only = {}
self.config_file = None
self.config_file = self.find_config_file()
self.default_arguments = {}
self.platform = platform()
self.prog_name = name
self.interactive = sys.stdin.isatty()
self.release_lock()
self._deprecated_arguments = {}
@ -69,6 +70,10 @@ class MILC(object):
self.initialize_argparse()
self.initialize_logging()
@property
def config_dir(self):
return self.config_file.parent
@property
def description(self):
return self._description
@ -267,6 +272,7 @@ class MILC(object):
if self._lock:
self._lock.release()
@lru_cache(maxsize=None)
def find_config_file(self):
"""Locate the config file.
"""
@ -343,15 +349,15 @@ class MILC(object):
self.release_lock()
def read_config_file(self, config_file):
def read_config_file(self):
"""Read in the configuration file and return Configuration objects for it and the config_source.
"""
config = Configuration()
config_source = Configuration()
if config_file.exists():
if self.config_file.exists():
raw_config = RawConfigParser()
raw_config.read(str(config_file))
raw_config.read(str(self.config_file))
# Iterate over the config file options and write them into config
for section in raw_config.sections():
@ -380,8 +386,7 @@ class MILC(object):
"""Read in the configuration file and store it in self.config.
"""
self.acquire_lock()
self.config_file = self.find_config_file()
self.config, self.config_source = self.read_config_file(self.config_file)
self.config, self.config_source = self.read_config_file()
self.release_lock()
def merge_args_into_config(self):
@ -435,13 +440,12 @@ class MILC(object):
if self.config_source[section_name][option_name] == 'config_file' and value is not None:
sane_config.set(section_name, option_name, str(value))
config_dir = self.config_file.parent
if not config_dir.exists():
config_dir.mkdir(parents=True, exist_ok=True)
if not self.config_dir.exists():
self.config_dir.mkdir(parents=True, exist_ok=True)
# Write the config file atomically.
self.acquire_lock()
with NamedTemporaryFile(mode='w', dir=str(config_dir), delete=False) as tmpfile:
with NamedTemporaryFile(mode='w', dir=str(self.config_dir), delete=False) as tmpfile:
sane_config.write(tmpfile)
if os.path.getsize(tmpfile.name) > 0:
@ -457,7 +461,7 @@ class MILC(object):
self.log.warning('%s.config_file not set, not saving config!', self.__class__.__name__)
return
config, config_source = self.read_config_file(self.config_file)
config, config_source = self.read_config_file()
if section in config and option in config[section] and config[section][option] is None:
del config[section][option]

View file

@ -8,7 +8,7 @@ from .common import check_assert, check_command, check_returncode
def test_example():
result = check_command('./example', '-h')
check_returncode(result)
check_assert(result, '{config,dashed-hello,hello,goodbye}' in result.stdout)
check_assert(result, '{config,dashed-hello,hello,goodbye,config-file}' in result.stdout)
def test_example_version():
@ -91,3 +91,14 @@ def test_example_dashed_hello_dashed_name():
result = check_command('./example', 'dashed-hello', '--dashed-name', 'Tester')
check_returncode(result)
check_assert(result, result.stdout == 'Hello, dashed-subcommand Tester!\n')
def test_example_config_file():
result = check_command('./example', 'config-file')
check_returncode(result)
lines = result.stdout.split('\n')
filename = lines[0].split('=', 1)[1]
filedir = lines[1].split('=', 1)[1]
check_assert(result, len(lines) == 3)
check_assert(result, filename.endswith('example.ini'))
check_assert(result, filename.startswith(filedir))