From bbfa72c02e72cdb213bd362787376866bb8a0b83 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Sat, 29 Aug 2026 15:04:29 +0000 Subject: [PATCH] cfg: add opts_data['requires'] --- mmgen/cfg.py | 11 ++++++++++- test/cmdtest_d/opts.py | 16 ++++++++++++++++ test/misc/opts_main.py | 4 ++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/mmgen/cfg.py b/mmgen/cfg.py index f05f0aa6..acb995f4 100755 --- a/mmgen/cfg.py +++ b/mmgen/cfg.py @@ -584,10 +584,12 @@ class Config(Lockable): # Step 7: set auto typeset opts from user-supplied data or cfgfile data, in that order: self._set_auto_typeset_opts(self._cfgfile_opts.auto_typeset) - # Step 8: process opts_data['sets']: + # Step 8: process opts_data['sets'] and opts_data['requires']: if opts_data: if 'sets' in opts_data: self._set_opts_data_sets_opts(opts_data) + if 'requires' in opts_data: # for required value of None, use False instead + self._check_opts_data_requires_opts(opts_data) if 'usage' in self._uopts: # requires self.coin import importlib @@ -789,6 +791,13 @@ class Config(Lockable): fmt_opt_val(b_opt, usr_b_val), fmt_opt_val(a_opt, usr_a_val))) + def _check_opts_data_requires_opts(self, opts_data): + for a_opt, a_val, b_opt, b_val in opts_data['requires']: + if getattr(self, a_opt, False) == a_val and getattr(self, b_opt, False) != b_val: + die('UserOptError', 'Option {} requires option {}\n'.format( + fmt_opt_val(a_opt, a_val), + fmt_opt_val(b_opt, b_val))) + def _die_on_incompatible_opts(self): for group in self._incompatible_opts: bad = [k for k in self.__dict__ diff --git a/test/cmdtest_d/opts.py b/test/cmdtest_d/opts.py index fb45e560..04e83643 100755 --- a/test/cmdtest_d/opts.py +++ b/test/cmdtest_d/opts.py @@ -54,6 +54,8 @@ class CmdTestOpts(CmdTestBase): ('opt_good31', (41, 'good cmdline opt (--xmr-rpc-port=28081)', [])), ('opt_good32', (41, 'good cmdline opt (A sets B)', [])), ('opt_good33', (41, 'good cmdline opt (A sets not B)', [])), + ('opt_good34', (41, 'good cmdline opt (A requires B)', [])), + ('opt_good35', (41, 'good cmdline opt (A requires not B)', [])), ('opt_bad_param', (41, 'bad global opt (--pager=1)', [])), ('opt_bad_infile', (41, 'bad infile parameter', [])), ('opt_bad_outdir', (41, 'bad outdir parameter', [])), @@ -61,6 +63,8 @@ class CmdTestOpts(CmdTestBase): ('opt_bad_autoset', (41, 'invalid autoset value', [])), ('opt_bad_sets1', (41, "invalid value for opts_data['sets']", [])), ('opt_bad_sets2', (41, "invalid value for opts_data['sets']", [])), + ('opt_bad_requires1', (41, "invalid value for opts_data['requires']", [])), + ('opt_bad_requires2', (41, "invalid value for opts_data['requires']", [])), ('opt_invalid_1', (41, 'invalid cmdline opt ‘--x’', [])), ('opt_invalid_2', (41, 'invalid cmdline opt ‘---’', [])), ('opt_invalid_5', (41, 'invalid cmdline opt (missing parameter)', [])), @@ -319,6 +323,12 @@ class CmdTestOpts(CmdTestBase): def opt_good33(self): return self.do_run(['--silent', '--no-verbose'], None, 0) + def opt_good34(self): + return self.do_run(['--coin=DOGE', '--no-foobleize'], None, 0) + + def opt_good35(self): + return self.do_run(['--no-silent', '--no-foobleize'], None, 0) + def opt_bad_param(self): return self.do_run(['--pager=1'], 'no parameter', 1) @@ -342,6 +352,12 @@ class CmdTestOpts(CmdTestBase): def opt_bad_sets2(self): return self.do_run(['--no-foobleize', '--in-fmt=csv'], 'conflicts with', 1) + def opt_bad_requires1(self): + return self.do_run(['--coin=DOGE'], 'requires option', 1) + + def opt_bad_requires2(self): + return self.do_run(['--no-foobleize', '--silent'], 'requires option --no-', 1) + def opt_invalid(self, args, expect, opts=[], need_proto=False, exit_val=1): t = self.spawn_prog(args, opts=opts, exit_val=exit_val, need_proto=need_proto) t.expect(expect) diff --git a/test/misc/opts_main.py b/test/misc/opts_main.py index 2ffdc310..aa2742de 100755 --- a/test/misc/opts_main.py +++ b/test/misc/opts_main.py @@ -11,6 +11,10 @@ opts_data = { ('silent', True, 'verbose', False), ('no_foobleize', True, 'in_fmt', 'hex'), ], + 'requires': [ + ('coin', 'DOGE', 'no_foobleize', True), + ('no_foobleize', True, 'silent', False), + ], 'text': { 'desc': 'Opts test', 'usage':'[args] [opts]',