Skip to content

Commit

Permalink
Several changes ...
Browse files Browse the repository at this point in the history
1. allow config_dir to be specified through API.
2. change name of Settings to Emborg.
3. Fix version tests.
  • Loading branch information
Ken Kundert authored and Ken Kundert committed Nov 4, 2022
1 parent 8992835 commit fb69743
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 102 deletions.
5 changes: 4 additions & 1 deletion doc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ separately:
print(borg.stdout.rstrip())
*Emborg* takes the config name as an argument, if not given the default config
is used. It provides the following useful methods and attributes:
is used. You can also pass list of *Emborg* options and the path to the
configurations directory.

*Emborg* provides the following useful methods and attributes:


**configs**
Expand Down
2 changes: 1 addition & 1 deletion emborg/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "1.34"
__released__ = "2022-11-03"

from .settings import Settings as Emborg
from .emborg import Emborg
63 changes: 28 additions & 35 deletions emborg/settings.py → emborg/emborg.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Settings
# Emborg Settings

# License {{{1
# Copyright (C) 2018-2022 Kenneth S. Kundert
Expand Down Expand Up @@ -107,17 +107,6 @@
if "arg" in attrs and attrs["arg"]:
borg_options_arg_count[convert_name_to_option(name)] = 1

# extract_version {{{2
def get_version():
VERSION_REGEX = r"(\d+)\.(\d+)\.(\d+)(?:(a|b|rc|\.dev|\.post)(\d+))?"
match = re.match(VERSION_REGEX, __version__)
def to_int(s):
try:
return int(s)
except:
return s
return tuple(to_int(c) for c in match.groups())

# ConfigQueue {{{1
class ConfigQueue:
def __init__(self, command=None):
Expand Down Expand Up @@ -161,7 +150,10 @@ def initialize(self, name, settings):
raise Error(
"unknown configuration.",
culprit = name,
codicil = "Perhaps you forgot to add it to the 'configurations' setting?.",
codicil = (
"Perhaps you forgot to add it to the ‘configurations’ setting?.",
f"Choose from: {conjoin(all_configs)}.",
)
)
else:
if len(config_groups) > 0:
Expand Down Expand Up @@ -207,19 +199,32 @@ def __bool__(self):
return bool(self.uninitialized or self.remaining_configs)


# Settings class {{{1
class Settings:
# Emborg class {{{1
class Emborg:
"""Emborg Settings
config (str):
Name of desired configuration. Passed only when reading the top level
settings file. Default is the default configuration as specified in the
settings file, or if that is not specified then the first configuration
given is used.
emborg_opts ([str])
A list of Emborg options chosen from “verbose”, “narrate”, “dry-run”,
and “no-log”.
config_dir (str, Path)
Path to configurations directory. Normally this is not specified.
Give it only when overriding the default configurations directory.
"""
# Constructor {{{2
def __init__(self, config=None, emborg_opts=(), **kwargs):
def __init__(self, config=None, emborg_opts=(), config_dir=None, **kwargs):
self.settings = dict()
self.do_not_expand = ()
self.emborg_opts = emborg_opts
self.version = get_version()

# reset the logfile so anything logged after this is placed in the
# logfile for this config
get_informer().set_logfile(LoggingCache())
self.config_dir = to_path(CONFIG_DIR)
self.config_dir = to_path(config_dir if config_dir else CONFIG_DIR)
self.read_config(name=config, **kwargs)
self.check()
set_shlib_prefs(encoding=self.encoding if self.encoding else DEFAULT_ENCODING)
Expand All @@ -237,23 +242,12 @@ def __init__(self, config=None, emborg_opts=(), **kwargs):
warn(f'unknown colorscheme: {self.colorscheme}.')

# read_config() {{{2
def read_config(self, name=None, path=None, **kwargs):
"""Recursively read configuration files.
name (str):
Name of desired configuration. Passed only when reading the top level
settings file. Default is the default configuration as specified in the
settings file, or if that is not specified then the first configuration
given is used.
path (str):
Full path to settings file. Should not be given for the top level
settings file (SETTINGS_FILE in CONFIG_DIR).
"""

if path:
def read_config(self, name=None, **kwargs):
if '_include_path' in kwargs:
# we are reading an include file
settings = PythonFile(path).run()
path = kwargs['_include_path']
parent = path.parent
settings = PythonFile(path).run()
includes = Collection(
settings.get(INCLUDE_SETTING),
split_lines,
Expand Down Expand Up @@ -327,8 +321,7 @@ def read_config(self, name=None, path=None, **kwargs):

# read include files, if any are specified
for include in includes:
path = to_path(parent, include)
self.read_config(path=path)
self.read_config(_include_path=to_path(parent, include))

# check() {{{2
def check(self):
Expand Down
22 changes: 11 additions & 11 deletions emborg/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
from . import __released__, __version__
from .command import Command
from .hooks import Hooks
from .settings import ConfigQueue, Settings
from .emborg import ConfigQueue, Emborg

# Globals {{{1
version = f"{__version__} ({__released__})"
Expand All @@ -64,11 +64,11 @@
# Main {{{1
def main():
with Inform(
error_status=2,
flush=True,
logfile=LoggingCache(),
prog_name='emborg',
version=version,
error_status = 2,
flush = True,
logfile = LoggingCache(),
prog_name = 'emborg',
version = version,
) as inform:

# read command line
Expand All @@ -84,10 +84,10 @@ def main():
os.environ['BORG_RELOCATED_REPO_ACCESS_IS_OK'] = 'YES'
emborg_opts = cull(
[
"verbose" if cmdline["--verbose"] else "",
"narrate" if cmdline["--narrate"] else "",
"dry-run" if cmdline["--dry-run"] else "",
"no-log" if cmdline["--no-log"] else "",
"verbose" if cmdline["--verbose"] else None,
"narrate" if cmdline["--narrate"] else None,
"dry-run" if cmdline["--dry-run"] else None,
"no-log" if cmdline["--no-log"] else None,
]
)
if cmdline["--narrate"]:
Expand All @@ -107,7 +107,7 @@ def main():

queue = ConfigQueue(cmd)
while queue:
with Settings(config, emborg_opts, queue=queue) as settings:
with Emborg(config, emborg_opts, queue=queue) as settings:
try:
exit_status = cmd.execute(
cmd_name, args, settings, emborg_opts
Expand Down
2 changes: 1 addition & 1 deletion emborg/preferences.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Emborg Settings
# Emborg Preferences
#
# Copyright (C) 2018-2022 Kenneth S. Kundert

Expand Down
6 changes: 3 additions & 3 deletions tests/test-cases.nt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ emborg without configs:

better:
args: version
expected: emborg version: \d+\.\d+\.\d+(\.?\w+\d+)? \(\d\d\d\d-\d\d-\d\d\) \[Python \d\.\d+\.\d+\]\.
expected: emborg version: \d+\.\d+(\.\d+(\.?\w+\d+)?)? \(\d\d\d\d-\d\d-\d\d\) \[Python \d\.\d+\.\d+\]\.
expected_type: regex
remove: .config

Expand Down Expand Up @@ -196,7 +196,7 @@ emborg with configs:

idiocy:
args: version
expected: emborg version: \d+\.\d+\.\d+(\.?\w+\d+)? \(\d\d\d\d-\d\d-\d\d\) \[Python \d\.\d+\.\d+\]\.
expected: emborg version: \d+\.\d+(\.\d+(\.?\w+\d+)?)? \(\d\d\d\d-\d\d-\d\d\) \[Python \d\.\d+\.\d+\]\.
expected_type: regex

heathen:
Expand Down Expand Up @@ -318,7 +318,7 @@ emborg with configs:

weave:
args: version
expected: emborg version: \d+\.\d+\.\d+(\.?\w+\d+)? \(\d\d\d\d-\d\d-\d\d\) \[Python \d\.\d+\.\d+\]\.
expected: emborg version: \d+\.\d+(\.\d+(\.?\w+\d+)?)? \(\d\d\d\d-\d\d-\d\d\) \[Python \d\.\d+\.\d+\]\.
expected_type: regex

plateful:
Expand Down
116 changes: 66 additions & 50 deletions tests/test_emborg.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ def run(self):
# run command
emborg = Run(self.cmd, "sOMW*")
self.result = dedent(Color.strip_colors(emborg.stdout)).strip("\n")
if emborg.stdout:
print(emborg.stdout)

# check stdout
matches = True
Expand Down Expand Up @@ -229,7 +231,7 @@ def test_emborg_without_configs(
if not passes:
result = tester.get_result()
expected = tester.get_expected()
assert result == expected, name
assert result == expected, f"Test ‘{name}’ fails."
raise AssertionError('test code failure')

# test_emborg_with_configs{{{2
Expand All @@ -249,7 +251,7 @@ def test_emborg_with_configs(
if not passes:
result = tester.get_result()
expected = tester.get_expected()
assert result == expected, name
assert result == expected, f"Test ‘{name}’ fails."
raise AssertionError('test code failure')

# test_emborg_overdue {{{2
Expand All @@ -271,61 +273,75 @@ def test_emborg_overdue(
args = args.split() if is_str(args) else args
overdue = Run(emborg_overdue_exe + args, "sOEW")
if 'regex' in expected_type.split():
assert bool(re.fullmatch(expected, overdue.stdout)), name
assert bool(re.fullmatch(expected, overdue.stdout)), f"Test ‘{name}’ fails."
else:
assert expected == overdue.stdout, name
assert expected == overdue.stdout, f"Test ‘{name}’ fails."
except Error as e:
assert str(e) == expected, name
assert str(e) == expected, f"Test ‘{name}’ fails."


# test_emborg_api {{{2
def test_emborg_api(initialize):
with cd(tests_dir):
from emborg import Emborg

with Emborg('tests') as emborg:
from emborg import Emborg

# get available configs
# do this before changing the working directory so as to test the ability
# to explicitly set the config_dir
config_dir = tests_dir / '.config/emborg'
try:
with Emborg('tests', config_dir=config_dir) as emborg:
configs = emborg.configs
assert configs == 'test0 test1 test2 test3'.split()
except Error as e:
e.report()
assert not e, str(e)
assert configs == 'test0 test1 test2 test3'.split()

with cd(tests_dir):

# list each config and assure than it contains expected paths
for config in configs:
# get the name of latest archive
with Emborg(config) as emborg:
borg = emborg.run_borg(
cmd = 'list',
args = ['--json', emborg.destination()]
)
response = json.loads(borg.stdout)
archive = response['archives'][-1]['archive']

# list files in latest archive
borg = emborg.run_borg(
cmd = 'list',
args = ['--json-lines', emborg.destination(archive)]
)
json_data = '[' + ','.join(borg.stdout.splitlines()) + ']'
response = json.loads(json_data)
paths = sorted([entry['path'] for entry in response])
for each in [
'⟪EMBORG⟫/tests/configs',
'⟪EMBORG⟫/tests/configs/README',
'⟪EMBORG⟫/tests/configs/overdue.conf',
'⟪EMBORG⟫/tests/configs/settings',
'⟪EMBORG⟫/tests/configs/subdir',
'⟪EMBORG⟫/tests/configs/subdir/file',
'⟪EMBORG⟫/tests/configs/test0',
'⟪EMBORG⟫/tests/configs/test1',
'⟪EMBORG⟫/tests/configs/test2',
'⟪EMBORG⟫/tests/configs/test2excludes',
'⟪EMBORG⟫/tests/configs/test2passphrase',
'⟪EMBORG⟫/tests/configs/test3',
'⟪EMBORG⟫/tests/configs/test4',
'⟪EMBORG⟫/tests/configs/test5',
'⟪EMBORG⟫/tests/configs/test6',
'⟪EMBORG⟫/tests/configs/test6patterns',
'⟪EMBORG⟫/tests/configs/test7',
'⟪EMBORG⟫/tests/configs/test7patterns',
'⟪EMBORG⟫/tests/configs/test8',
]:
each = each.replace("⟪EMBORG⟫", emborg_dir_wo_slash)
assert each in paths
try:
# get the name of latest archive
with Emborg(config) as emborg:
borg = emborg.run_borg(
cmd = 'list',
args = ['--json', emborg.destination()]
)
response = json.loads(borg.stdout)
archive = response['archives'][-1]['archive']

# list files in latest archive
borg = emborg.run_borg(
cmd = 'list',
args = ['--json-lines', emborg.destination(archive)]
)
json_data = '[' + ','.join(borg.stdout.splitlines()) + ']'
response = json.loads(json_data)
paths = sorted([entry['path'] for entry in response])
for each in [
'⟪EMBORG⟫/tests/configs',
'⟪EMBORG⟫/tests/configs/README',
'⟪EMBORG⟫/tests/configs/overdue.conf',
'⟪EMBORG⟫/tests/configs/settings',
'⟪EMBORG⟫/tests/configs/subdir',
'⟪EMBORG⟫/tests/configs/subdir/file',
'⟪EMBORG⟫/tests/configs/test0',
'⟪EMBORG⟫/tests/configs/test1',
'⟪EMBORG⟫/tests/configs/test2',
'⟪EMBORG⟫/tests/configs/test2excludes',
'⟪EMBORG⟫/tests/configs/test2passphrase',
'⟪EMBORG⟫/tests/configs/test3',
'⟪EMBORG⟫/tests/configs/test4',
'⟪EMBORG⟫/tests/configs/test5',
'⟪EMBORG⟫/tests/configs/test6',
'⟪EMBORG⟫/tests/configs/test6patterns',
'⟪EMBORG⟫/tests/configs/test7',
'⟪EMBORG⟫/tests/configs/test7patterns',
'⟪EMBORG⟫/tests/configs/test8',
]:
each = each.replace("⟪EMBORG⟫", emborg_dir_wo_slash)
assert each in paths
except Error as e:
e.report()
assert not e, str(e)

0 comments on commit fb69743

Please sign in to comment.