Skip to content

Commit fb69743

Browse files
Ken KundertKen Kundert
Ken Kundert
authored and
Ken Kundert
committed
Several changes ...
1. allow config_dir to be specified through API. 2. change name of Settings to Emborg. 3. Fix version tests.
1 parent 8992835 commit fb69743

File tree

7 files changed

+114
-102
lines changed

7 files changed

+114
-102
lines changed

doc/api.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ separately:
2626
print(borg.stdout.rstrip())
2727
2828
*Emborg* takes the config name as an argument, if not given the default config
29-
is used. It provides the following useful methods and attributes:
29+
is used. You can also pass list of *Emborg* options and the path to the
30+
configurations directory.
31+
32+
*Emborg* provides the following useful methods and attributes:
3033

3134

3235
**configs**

emborg/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
__version__ = "1.34"
22
__released__ = "2022-11-03"
33

4-
from .settings import Settings as Emborg
4+
from .emborg import Emborg

emborg/settings.py renamed to emborg/emborg.py

Lines changed: 28 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Settings
1+
# Emborg Settings
22

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

110-
# extract_version {{{2
111-
def get_version():
112-
VERSION_REGEX = r"(\d+)\.(\d+)\.(\d+)(?:(a|b|rc|\.dev|\.post)(\d+))?"
113-
match = re.match(VERSION_REGEX, __version__)
114-
def to_int(s):
115-
try:
116-
return int(s)
117-
except:
118-
return s
119-
return tuple(to_int(c) for c in match.groups())
120-
121110
# ConfigQueue {{{1
122111
class ConfigQueue:
123112
def __init__(self, command=None):
@@ -161,7 +150,10 @@ def initialize(self, name, settings):
161150
raise Error(
162151
"unknown configuration.",
163152
culprit = name,
164-
codicil = "Perhaps you forgot to add it to the 'configurations' setting?.",
153+
codicil = (
154+
"Perhaps you forgot to add it to the ‘configurations’ setting?.",
155+
f"Choose from: {conjoin(all_configs)}.",
156+
)
165157
)
166158
else:
167159
if len(config_groups) > 0:
@@ -207,19 +199,32 @@ def __bool__(self):
207199
return bool(self.uninitialized or self.remaining_configs)
208200

209201

210-
# Settings class {{{1
211-
class Settings:
202+
# Emborg class {{{1
203+
class Emborg:
204+
"""Emborg Settings
205+
206+
config (str):
207+
Name of desired configuration. Passed only when reading the top level
208+
settings file. Default is the default configuration as specified in the
209+
settings file, or if that is not specified then the first configuration
210+
given is used.
211+
emborg_opts ([str])
212+
A list of Emborg options chosen from “verbose”, “narrate”, “dry-run”,
213+
and “no-log”.
214+
config_dir (str, Path)
215+
Path to configurations directory. Normally this is not specified.
216+
Give it only when overriding the default configurations directory.
217+
"""
212218
# Constructor {{{2
213-
def __init__(self, config=None, emborg_opts=(), **kwargs):
219+
def __init__(self, config=None, emborg_opts=(), config_dir=None, **kwargs):
214220
self.settings = dict()
215221
self.do_not_expand = ()
216222
self.emborg_opts = emborg_opts
217-
self.version = get_version()
218223

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

239244
# read_config() {{{2
240-
def read_config(self, name=None, path=None, **kwargs):
241-
"""Recursively read configuration files.
242-
243-
name (str):
244-
Name of desired configuration. Passed only when reading the top level
245-
settings file. Default is the default configuration as specified in the
246-
settings file, or if that is not specified then the first configuration
247-
given is used.
248-
path (str):
249-
Full path to settings file. Should not be given for the top level
250-
settings file (SETTINGS_FILE in CONFIG_DIR).
251-
"""
252-
253-
if path:
245+
def read_config(self, name=None, **kwargs):
246+
if '_include_path' in kwargs:
254247
# we are reading an include file
255-
settings = PythonFile(path).run()
248+
path = kwargs['_include_path']
256249
parent = path.parent
250+
settings = PythonFile(path).run()
257251
includes = Collection(
258252
settings.get(INCLUDE_SETTING),
259253
split_lines,
@@ -327,8 +321,7 @@ def read_config(self, name=None, path=None, **kwargs):
327321

328322
# read include files, if any are specified
329323
for include in includes:
330-
path = to_path(parent, include)
331-
self.read_config(path=path)
324+
self.read_config(_include_path=to_path(parent, include))
332325

333326
# check() {{{2
334327
def check(self):

emborg/main.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
from . import __released__, __version__
4747
from .command import Command
4848
from .hooks import Hooks
49-
from .settings import ConfigQueue, Settings
49+
from .emborg import ConfigQueue, Emborg
5050

5151
# Globals {{{1
5252
version = f"{__version__} ({__released__})"
@@ -64,11 +64,11 @@
6464
# Main {{{1
6565
def main():
6666
with Inform(
67-
error_status=2,
68-
flush=True,
69-
logfile=LoggingCache(),
70-
prog_name='emborg',
71-
version=version,
67+
error_status = 2,
68+
flush = True,
69+
logfile = LoggingCache(),
70+
prog_name = 'emborg',
71+
version = version,
7272
) as inform:
7373

7474
# read command line
@@ -84,10 +84,10 @@ def main():
8484
os.environ['BORG_RELOCATED_REPO_ACCESS_IS_OK'] = 'YES'
8585
emborg_opts = cull(
8686
[
87-
"verbose" if cmdline["--verbose"] else "",
88-
"narrate" if cmdline["--narrate"] else "",
89-
"dry-run" if cmdline["--dry-run"] else "",
90-
"no-log" if cmdline["--no-log"] else "",
87+
"verbose" if cmdline["--verbose"] else None,
88+
"narrate" if cmdline["--narrate"] else None,
89+
"dry-run" if cmdline["--dry-run"] else None,
90+
"no-log" if cmdline["--no-log"] else None,
9191
]
9292
)
9393
if cmdline["--narrate"]:
@@ -107,7 +107,7 @@ def main():
107107

108108
queue = ConfigQueue(cmd)
109109
while queue:
110-
with Settings(config, emborg_opts, queue=queue) as settings:
110+
with Emborg(config, emborg_opts, queue=queue) as settings:
111111
try:
112112
exit_status = cmd.execute(
113113
cmd_name, args, settings, emborg_opts

emborg/preferences.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Emborg Settings
1+
# Emborg Preferences
22
#
33
# Copyright (C) 2018-2022 Kenneth S. Kundert
44

tests/test-cases.nt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ emborg without configs:
22

33
better:
44
args: version
5-
expected: emborg version: \d+\.\d+\.\d+(\.?\w+\d+)? \(\d\d\d\d-\d\d-\d\d\) \[Python \d\.\d+\.\d+\]\.
5+
expected: emborg version: \d+\.\d+(\.\d+(\.?\w+\d+)?)? \(\d\d\d\d-\d\d-\d\d\) \[Python \d\.\d+\.\d+\]\.
66
expected_type: regex
77
remove: .config
88

@@ -196,7 +196,7 @@ emborg with configs:
196196

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

202202
heathen:
@@ -318,7 +318,7 @@ emborg with configs:
318318

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

324324
plateful:

tests/test_emborg.py

Lines changed: 66 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ def run(self):
120120
# run command
121121
emborg = Run(self.cmd, "sOMW*")
122122
self.result = dedent(Color.strip_colors(emborg.stdout)).strip("\n")
123+
if emborg.stdout:
124+
print(emborg.stdout)
123125

124126
# check stdout
125127
matches = True
@@ -229,7 +231,7 @@ def test_emborg_without_configs(
229231
if not passes:
230232
result = tester.get_result()
231233
expected = tester.get_expected()
232-
assert result == expected, name
234+
assert result == expected, f"Test ‘{name}’ fails."
233235
raise AssertionError('test code failure')
234236

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

255257
# test_emborg_overdue {{{2
@@ -271,61 +273,75 @@ def test_emborg_overdue(
271273
args = args.split() if is_str(args) else args
272274
overdue = Run(emborg_overdue_exe + args, "sOEW")
273275
if 'regex' in expected_type.split():
274-
assert bool(re.fullmatch(expected, overdue.stdout)), name
276+
assert bool(re.fullmatch(expected, overdue.stdout)), f"Test ‘{name}’ fails."
275277
else:
276-
assert expected == overdue.stdout, name
278+
assert expected == overdue.stdout, f"Test ‘{name}’ fails."
277279
except Error as e:
278-
assert str(e) == expected, name
280+
assert str(e) == expected, f"Test ‘{name}’ fails."
279281

280282

281283
# test_emborg_api {{{2
282284
def test_emborg_api(initialize):
283-
with cd(tests_dir):
284-
from emborg import Emborg
285-
286-
with Emborg('tests') as emborg:
285+
from emborg import Emborg
286+
287+
# get available configs
288+
# do this before changing the working directory so as to test the ability
289+
# to explicitly set the config_dir
290+
config_dir = tests_dir / '.config/emborg'
291+
try:
292+
with Emborg('tests', config_dir=config_dir) as emborg:
287293
configs = emborg.configs
288-
assert configs == 'test0 test1 test2 test3'.split()
294+
except Error as e:
295+
e.report()
296+
assert not e, str(e)
297+
assert configs == 'test0 test1 test2 test3'.split()
298+
299+
with cd(tests_dir):
289300

301+
# list each config and assure than it contains expected paths
290302
for config in configs:
291-
# get the name of latest archive
292-
with Emborg(config) as emborg:
293-
borg = emborg.run_borg(
294-
cmd = 'list',
295-
args = ['--json', emborg.destination()]
296-
)
297-
response = json.loads(borg.stdout)
298-
archive = response['archives'][-1]['archive']
299-
300-
# list files in latest archive
301-
borg = emborg.run_borg(
302-
cmd = 'list',
303-
args = ['--json-lines', emborg.destination(archive)]
304-
)
305-
json_data = '[' + ','.join(borg.stdout.splitlines()) + ']'
306-
response = json.loads(json_data)
307-
paths = sorted([entry['path'] for entry in response])
308-
for each in [
309-
'⟪EMBORG⟫/tests/configs',
310-
'⟪EMBORG⟫/tests/configs/README',
311-
'⟪EMBORG⟫/tests/configs/overdue.conf',
312-
'⟪EMBORG⟫/tests/configs/settings',
313-
'⟪EMBORG⟫/tests/configs/subdir',
314-
'⟪EMBORG⟫/tests/configs/subdir/file',
315-
'⟪EMBORG⟫/tests/configs/test0',
316-
'⟪EMBORG⟫/tests/configs/test1',
317-
'⟪EMBORG⟫/tests/configs/test2',
318-
'⟪EMBORG⟫/tests/configs/test2excludes',
319-
'⟪EMBORG⟫/tests/configs/test2passphrase',
320-
'⟪EMBORG⟫/tests/configs/test3',
321-
'⟪EMBORG⟫/tests/configs/test4',
322-
'⟪EMBORG⟫/tests/configs/test5',
323-
'⟪EMBORG⟫/tests/configs/test6',
324-
'⟪EMBORG⟫/tests/configs/test6patterns',
325-
'⟪EMBORG⟫/tests/configs/test7',
326-
'⟪EMBORG⟫/tests/configs/test7patterns',
327-
'⟪EMBORG⟫/tests/configs/test8',
328-
]:
329-
each = each.replace("⟪EMBORG⟫", emborg_dir_wo_slash)
330-
assert each in paths
303+
try:
304+
# get the name of latest archive
305+
with Emborg(config) as emborg:
306+
borg = emborg.run_borg(
307+
cmd = 'list',
308+
args = ['--json', emborg.destination()]
309+
)
310+
response = json.loads(borg.stdout)
311+
archive = response['archives'][-1]['archive']
312+
313+
# list files in latest archive
314+
borg = emborg.run_borg(
315+
cmd = 'list',
316+
args = ['--json-lines', emborg.destination(archive)]
317+
)
318+
json_data = '[' + ','.join(borg.stdout.splitlines()) + ']'
319+
response = json.loads(json_data)
320+
paths = sorted([entry['path'] for entry in response])
321+
for each in [
322+
'⟪EMBORG⟫/tests/configs',
323+
'⟪EMBORG⟫/tests/configs/README',
324+
'⟪EMBORG⟫/tests/configs/overdue.conf',
325+
'⟪EMBORG⟫/tests/configs/settings',
326+
'⟪EMBORG⟫/tests/configs/subdir',
327+
'⟪EMBORG⟫/tests/configs/subdir/file',
328+
'⟪EMBORG⟫/tests/configs/test0',
329+
'⟪EMBORG⟫/tests/configs/test1',
330+
'⟪EMBORG⟫/tests/configs/test2',
331+
'⟪EMBORG⟫/tests/configs/test2excludes',
332+
'⟪EMBORG⟫/tests/configs/test2passphrase',
333+
'⟪EMBORG⟫/tests/configs/test3',
334+
'⟪EMBORG⟫/tests/configs/test4',
335+
'⟪EMBORG⟫/tests/configs/test5',
336+
'⟪EMBORG⟫/tests/configs/test6',
337+
'⟪EMBORG⟫/tests/configs/test6patterns',
338+
'⟪EMBORG⟫/tests/configs/test7',
339+
'⟪EMBORG⟫/tests/configs/test7patterns',
340+
'⟪EMBORG⟫/tests/configs/test8',
341+
]:
342+
each = each.replace("⟪EMBORG⟫", emborg_dir_wo_slash)
343+
assert each in paths
344+
except Error as e:
345+
e.report()
346+
assert not e, str(e)
331347

0 commit comments

Comments
 (0)