diff --git a/.github/workflows/rst-lint.yaml b/.github/workflows/rst-lint.yaml index 187ce87c..76f7a4cb 100644 --- a/.github/workflows/rst-lint.yaml +++ b/.github/workflows/rst-lint.yaml @@ -14,7 +14,7 @@ jobs: with: fetch-depth: 0 - name: Set up Python 3.11 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.11 - name: Install dependencies @@ -25,6 +25,6 @@ jobs: python setup.py build python doc/src/conf.py - name: doc8-check - uses: deep-entertainment/doc8-action@v4 + uses: deep-entertainment/doc8-action@v5 with: scanPaths: "doc/src" diff --git a/CHANGES.rst b/CHANGES.rst index 2941612e..d422eba9 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,6 +2,35 @@ Changelog ========= +.. _changes-1_4_0: + +1.4.0 (2024-08-30) +~~~~~~~~~~~~~~~~~~ + +New features +------------ + ++ `#155`_, `#156`_: Add an option to disable parsing of command line + arguments in :class:`icat.config.Config`. + +Bug fixes and minor changes +--------------------------- + ++ `#152`_: Fix a documentation error ++ `#154`_: Fix a duplicate test name + +Misc +---- + ++ `#157`_: :mod:`icat.ingest` now considered stable. + +.. _#152: https://github.com/icatproject/python-icat/pull/152 +.. _#154: https://github.com/icatproject/python-icat/pull/154 +.. _#155: https://github.com/icatproject/python-icat/issues/155 +.. _#156: https://github.com/icatproject/python-icat/pull/156 +.. _#157: https://github.com/icatproject/python-icat/pull/157 + + .. _changes-1_3_0: 1.3.0 (2024-03-21) diff --git a/doc/examples/init-icat.py b/doc/examples/init-icat.py index ef0017ac..a632f1a7 100644 --- a/doc/examples/init-icat.py +++ b/doc/examples/init-icat.py @@ -126,8 +126,8 @@ def getUser(client, attrs): client.createRules("CRUD", uotables, uogroup) # Setup permissions for the data ingester. They need read permission -# on Investigation and Shift and create and create permission on -# Dataset, Datafile, and the respective Parameter. +# on Investigation and Shift and create permission on Dataset, +# Datafile, and the respective Parameter. ingest = client.createUser("simple/dataingest", fullName="Data Ingester") ingestgroup = client.createGroup("ingest", [ ingest ]) client.createRules("R", [ "Investigation", "Shift" ], ingestgroup) diff --git a/doc/src/client.rst b/doc/src/client.rst index e32dc2df..051edac5 100644 --- a/doc/src/client.rst +++ b/doc/src/client.rst @@ -48,8 +48,6 @@ manages the interaction with an ICAT service as a client. The :class:`ssl.SSLContext` instance that has been used to establish the HTTPS conection to the ICAT and IDS server. - This is :const:`None` for old Python versions that do not have - the :class:`ssl.SSLContext` class. .. attribute:: typemap diff --git a/doc/src/ingest.rst b/doc/src/ingest.rst index e0574221..a12eca44 100644 --- a/doc/src/ingest.rst +++ b/doc/src/ingest.rst @@ -5,11 +5,6 @@ .. versionadded:: 1.1.0 -.. note:: - The status of this module in the current version is still - experimental. There may be incompatible changes in the future - even in minor releases of python-icat. - This module provides class :class:`icat.ingest.IngestReader` that reads :ref:`ICAT-ingest-files` to add them to ICAT. It is designed for the use case of ingesting metadata for datasets created during diff --git a/setup.py b/setup.py index ee7173e1..adf1bbf8 100755 --- a/setup.py +++ b/setup.py @@ -175,6 +175,7 @@ def run(self): "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Topic :: Software Development :: Libraries :: Python Modules", ], project_urls = dict( diff --git a/src/icat/client.py b/src/icat/client.py index b18935d6..8c0cf2cf 100644 --- a/src/icat/client.py +++ b/src/icat/client.py @@ -564,7 +564,7 @@ def searchChunked(self, query, skip=0, count=None, chunksize=100): # This version works! query = Query(client, "Dataset", includes="1", order=["id"]) for ds in client.searchChunked(query): - if not ds.complete: + if ds.complete: continue ds.complete = True ds.update() diff --git a/src/icat/config.py b/src/icat/config.py index f3187df5..992fd96f 100644 --- a/src/icat/config.py +++ b/src/icat/config.py @@ -271,6 +271,16 @@ def get(self, variable): raise NotImplementedError +class ConfigSourceDisabled(): + """A disabled configuration source. + + Do nothing and return :const:`None` for each variable to signal + that this variable is not set in this source. + """ + def get(self, variable): + return None + + class ConfigSourceCmdArgs(ConfigSource): """Get configuration from command line arguments. """ @@ -490,7 +500,7 @@ def add_variable(self, name, arg_opts=(), arg_kws=None, :type subst: :class:`bool` :return: the new configuration variable object. :rtype: :class:`icat.config.ConfigVariable` - :raise RuntimeError: if this objects already has subcommands + :raise RuntimeError: if this config object already has subcommands defined with :meth:`icat.config.BaseConfig.add_subcommands`. :raise ValueError: if the name is not valid. :see: the documentation of the :mod:`argparse` standard @@ -502,6 +512,16 @@ def add_variable(self, name, arg_opts=(), arg_kws=None, raise ValueError("Config variable name '%s' is reserved." % name) if name in self.confvariable: raise ValueError("Config variable '%s' is already defined." % name) + if self.argparser: + self._add_argparser_argument(name, arg_opts, arg_kws, default, type) + if type == flag: + type = boolean + var = ConfigVariable(name, envvar, optional, default, type, subst) + self.confvariable[name] = var + self.confvariables.append(var) + return var + + def _add_argparser_argument(self, name, arg_opts, arg_kws, default, type): if arg_kws is None: arg_kws = dict() else: @@ -529,7 +549,6 @@ def add_variable(self, name, arg_opts=(), arg_kws=None, arg_kws['const'] = False arg_kws['help'] = argparse.SUPPRESS self.argparser.add_argument("--no-"+arg, **arg_kws) - type = boolean elif arg_opts: prefix = self.argparser.prefix_chars if len(arg_opts) == 1 and arg_opts[0][0] not in prefix: @@ -542,10 +561,6 @@ def add_variable(self, name, arg_opts=(), arg_kws=None, # optional argument arg_kws['dest'] = name self.argparser.add_argument(*arg_opts, **arg_kws) - var = ConfigVariable(name, envvar, optional, default, type, subst) - self.confvariable[name] = var - self.confvariables.append(var) - return var def add_subcommands(self, name='subcmd', arg_kws=None, optional=False): """Defines a new configuration variable to select subcommands. @@ -576,11 +591,16 @@ def add_subcommands(self, name='subcmd', arg_kws=None, optional=False): :type optional: :class:`bool` :return: the new subcommand object. :rtype: :class:`icat.config.ConfigSubCmd` - :raise RuntimeError: if this objects already has subcommands. + :raise RuntimeError: if parsing of command line arguments is + disabled in this config object or if it already has + subcommands. :raise ValueError: if the name is not valid. :see: the documentation of the :mod:`argparse` standard library module for details on `arg_kws`. """ + if not self.argparser: + raise RuntimeError("Command line parsing is disabled " + "in this config, cannot add subcommands.") if self._subcmds is not None: raise RuntimeError("This config already has subcommands.") if name in self.ReservedVariables or name[0] == '_': @@ -618,12 +638,12 @@ def _getconfig(self, sources, config=None): if value is not None and var.subst: value = value % config.as_dict() setattr(config, var.name, value) + if var.postprocess: + var.postprocess(self, config) if isinstance(var, ConfigSubCmds): if value is not None: value._getconfig(sources, config) break - if var.postprocess: - var.postprocess(self, config) return config @@ -662,21 +682,30 @@ class Config(BaseConfig): environment variables, and settings in the configuration files still take precedence over the preset values. :type preset: :class:`dict` - :param args: list of command line arguments or :const:`None`. If - not set, the command line arguments will be taken from - :data:`sys.argv`. - :type args: :class:`list` of :class:`str` + :param args: list of command line arguments. If set to the + special value :const:`False`, parsing of command line + arguments will be disabled. The default, if :const:`None` is + to take the command line arguments from :data:`sys.argv`. + :type args: :class:`list` of :class:`str` or :class:`bool` .. versionchanged:: 1.0.0 add the `preset` argument. + + .. versionchanged:: 1.4.0 + allow to disable parsing of command line arguments, setting + `args` to :const:`False`. """ def __init__(self, defaultvars=True, needlogin=True, ids="optional", preset=None, args=None): """Initialize the object. """ - super().__init__(argparse.ArgumentParser()) - self.cmdargs = ConfigSourceCmdArgs(self.argparser) + if args is False: + super().__init__(None) + self.cmdargs = ConfigSourceDisabled() + else: + super().__init__(argparse.ArgumentParser()) + self.cmdargs = ConfigSourceCmdArgs(self.argparser) self.environ = ConfigSourceEnvironment() defaultFiles = [str(d / cfgfile) for d in cfgdirs] self.conffile = ConfigSourceFile(defaultFiles) @@ -731,7 +760,8 @@ def getconfig(self): configuration file, if an invalid value is given to a variable, or if a mandatory variable is not defined. """ - self.cmdargs.parse_args(self.args) + if self.argparser: + self.cmdargs.parse_args(self.args) config = self._getconfig(self.sources) if self.needlogin: @@ -841,9 +871,10 @@ def _setup_client(self): """Initialize the client. """ try: - with _argparserDisableExit(self.argparser): - self.cmdargs.parse_args(self.args, partial=True) - config = self._getconfig(self.sources) + if self.argparser: + with _argparserDisableExit(self.argparser): + self.cmdargs.parse_args(self.args, partial=True) + config = self._getconfig(self.sources) except ConfigError: return None, None client_kwargs = {} diff --git a/src/icat/ingest.py b/src/icat/ingest.py index 0e513526..55a10b5a 100644 --- a/src/icat/ingest.py +++ b/src/icat/ingest.py @@ -1,10 +1,5 @@ """Ingest metadata into ICAT. -.. note:: - The status of this module in the current version is still - experimental. There may be incompatible changes in the future - even in minor releases of python-icat. - .. versionadded:: 1.1.0 """ diff --git a/tests/test_01_config.py b/tests/test_01_config.py index 4f03f93c..75c4f2b3 100644 --- a/tests/test_01_config.py +++ b/tests/test_01_config.py @@ -1,8 +1,10 @@ """Test module icat.config """ +import argparse import getpass from pathlib import Path +import sys import pytest import icat.config import icat.exception @@ -10,13 +12,6 @@ # ============================= helper ============================= -# The icat.config.Config constructor already creates and initializes -# an ICAT client. Prevent this, as we don't want to connect to a real -# server in this test module. Foist a fake client class on the -# icat.config module. Note that we must monkeypatch icat.config -# rather than icat.client, as the former already imported the Client -# class at this point. - class Namespace(): def __init__(self, **kwargs): for (k, v) in kwargs.items(): @@ -33,6 +28,13 @@ def __le__(self, other): else: return True +# The icat.config.Config constructor already creates and initializes +# an ICAT client. Prevent this, as we don't want to connect to a real +# server in this test module. Foist a fake client class on the +# icat.config module. Note that we must monkeypatch icat.config +# rather than icat.client, as the former already imported the Client +# class at this point. + class FakeClient(): AuthInfo = None def __init__(self, url, **kwargs): @@ -53,6 +55,23 @@ def __eq__(self, other): def fakeClient(monkeypatch): monkeypatch.setattr(icat.config, "Client", FakeClient) +# Evil black magic: monkey patch ArgumentParser to raise an error if +# either parse_args() or parse_known_args() is called. This is needed +# to verify that disabling the argparser is effective in +# test_config_args_disable(). + +class ArgumentParserErrorMixin: + def parse_args(self, *args, **kwargs): + assert False, "parse_args() should not get called" + def parse_known_args(self, *args, **kwargs): + assert False, "parse_known_args() should not get called" + +@pytest.fixture(scope="function") +def patchArgParse(monkeypatch): + monkeypatch.setattr(argparse.ArgumentParser, "parse_args", + ArgumentParserErrorMixin.parse_args) + monkeypatch.setattr(argparse.ArgumentParser, "parse_known_args", + ArgumentParserErrorMixin.parse_known_args) # Deliberately not using the 'tmpdir' fixture provided by pytest, # because it seem to use a predictable directory name in /tmp wich is @@ -72,6 +91,13 @@ def fakeClient(monkeypatch): ldap_uri = ldap://ldap.example.com ldap_base = ou=People,dc=example,dc=com +[example_pubreader] +url = https://icat.example.com/ICATService/ICAT?wsdl +auth = simple +username = pubreader +password = pwpubreader +idsurl = https://icat.example.com/ids + [example_jdoe] url = https://icat.example.com/ICATService/ICAT?wsdl auth = ldap @@ -140,32 +166,33 @@ def tmpfiles(): # ============================= tests ============================== -def test_config_missing_mandatory(fakeClient): +def test_config_missing_mandatory(monkeypatch, fakeClient): """Not providing any config at all. This throws an error as url is mandatory. """ - config = icat.config.Config(needlogin=False, ids=False, args=[]) + monkeypatch.setattr(sys, "argv", ["cmd"]) + config = icat.config.Config(needlogin=False, ids=False) with pytest.raises(icat.exception.ConfigError) as err: _, conf = config.getconfig() assert "Config option 'url' not given" in str(err.value) -def test_config_minimal(fakeClient): +def test_config_minimal(monkeypatch, fakeClient): """Minimal example. No login credentials, only relevant config option is the url which is provided as command line argument. """ - args = ["-w", ex_icat] - config = icat.config.Config(needlogin=False, ids=False, args=args) + monkeypatch.setattr(sys, "argv", ("cmd -w %s" % ex_icat).split()) + config = icat.config.Config(needlogin=False, ids=False) _, conf = config.getconfig() assert ExpectedConf(configSection=None, url=ex_icat) <= conf -def test_config_minimal_file(fakeClient, tmpconfigfile, monkeypatch): +def test_config_minimal_file(monkeypatch, fakeClient, tmpconfigfile): """Minimal example. Almost the same as test_config_minimal(), but read the url from @@ -178,8 +205,8 @@ def test_config_minimal_file(fakeClient, tmpconfigfile, monkeypatch): monkeypatch.setattr(icat.config, "cfgdirs", cfgdirs) monkeypatch.chdir(str(tmpconfigfile.dir)) - args = ["-s", "example_root"] - config = icat.config.Config(needlogin=False, ids=False, args=args) + monkeypatch.setattr(sys, "argv", "cmd -s example_root".split()) + config = icat.config.Config(needlogin=False, ids=False) _, conf = config.getconfig() ex = ExpectedConf(configFile=[Path("icat.cfg")], @@ -188,7 +215,7 @@ def test_config_minimal_file(fakeClient, tmpconfigfile, monkeypatch): assert ex <= conf -def test_config_minimal_file_preset(fakeClient, tmpconfigfile, monkeypatch): +def test_config_minimal_file_preset(monkeypatch, fakeClient, tmpconfigfile): """Minimal example. Almost the same as test_config_minimal_file(), but set the section @@ -205,9 +232,9 @@ def test_config_minimal_file_preset(fakeClient, tmpconfigfile, monkeypatch): monkeypatch.setattr(icat.config, "cfgdirs", cfgdirs) monkeypatch.chdir(str(tmpconfigfile.dir)) + monkeypatch.setattr(sys, "argv", ["cmd"]) preset = {"configSection": "example_root"} - config = icat.config.Config(needlogin=False, ids=False, - preset=preset, args=()) + config = icat.config.Config(needlogin=False, ids=False, preset=preset) _, conf = config.getconfig() ex = ExpectedConf(configFile=[Path("icat.cfg")], @@ -216,7 +243,7 @@ def test_config_minimal_file_preset(fakeClient, tmpconfigfile, monkeypatch): assert ex <= conf -def test_config_file_expanduser(fakeClient, tmpconfigfile, monkeypatch): +def test_config_file_expanduser(monkeypatch, fakeClient, tmpconfigfile): """Explicitely point to the config file. Indicate the path of the config file in the command line @@ -230,8 +257,9 @@ def test_config_file_expanduser(fakeClient, tmpconfigfile, monkeypatch): monkeypatch.setattr(icat.config, "cfgdirs", cfgdirs) monkeypatch.chdir(str(tmpconfigfile.home)) - args = ["-c", "~/.icat/icat.cfg", "-s", "example_root"] - config = icat.config.Config(needlogin=False, ids=False, args=args) + cmdline = "cmd -c ~/.icat/icat.cfg -s example_root" + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config(needlogin=False, ids=False) _, conf = config.getconfig() ex = ExpectedConf(configFile=[tmpconfigfile.path], @@ -240,7 +268,7 @@ def test_config_file_expanduser(fakeClient, tmpconfigfile, monkeypatch): assert ex <= conf -def test_config_minimal_defaultfile(fakeClient, tmpconfigfile, monkeypatch): +def test_config_minimal_defaultfile(monkeypatch, fakeClient, tmpconfigfile): """Minimal example. Almost the same as test_config_minimal_file(), but let the @@ -256,8 +284,8 @@ def test_config_minimal_defaultfile(fakeClient, tmpconfigfile, monkeypatch): monkeypatch.setattr(icat.config, "cfgdirs", cfgdirs) monkeypatch.chdir(str(tmpconfigfile.home)) - args = ["-s", "example_root"] - config = icat.config.Config(needlogin=False, ids=False, args=args) + monkeypatch.setattr(sys, "argv", "cmd -s example_root".split()) + config = icat.config.Config(needlogin=False, ids=False) _, conf = config.getconfig() ex = ExpectedConf(configFile=[tmpconfigfile.path], @@ -266,7 +294,114 @@ def test_config_minimal_defaultfile(fakeClient, tmpconfigfile, monkeypatch): assert ex <= conf -def test_config_no_defaultvars(tmpconfigfile, monkeypatch): +def test_config_args_section(monkeypatch, fakeClient, tmpconfigfile): + """Override the command line arguments in the Config() call. + + Same setting as test_config_minimal_defaultfile(), but override + the command line arguments using the `args` keyword arguments to + Config(). + """ + + # Manipulate the default search path. + monkeypatch.setenv("HOME", str(tmpconfigfile.home)) + cfgdirs = [ Path("~/.config/icat").expanduser(), + Path("~/.icat").expanduser(), + Path("."), ] + monkeypatch.setattr(icat.config, "cfgdirs", cfgdirs) + monkeypatch.chdir(str(tmpconfigfile.home)) + + # Set some bogus arguments in the command line, a mixture of + # formally valid and invalid ones, to verify that they will indeed + # be ignored. + cmdline = "cmd -w https://bogus.example.com/ -f foobar" + monkeypatch.setattr(sys, "argv", cmdline.split()) + args = "-s example_root".split() + config = icat.config.Config(needlogin=False, ids=False, args=args) + _, conf = config.getconfig() + + ex = ExpectedConf(configFile=[tmpconfigfile.path], + configSection="example_root", + url=ex_icat) + assert ex <= conf + + +def test_config_args_empty(monkeypatch, fakeClient, tmpconfigfile): + """Disable command line arguments by setting empty args. + + Configuration is read from the config file, the config section is + set with `preset`. Setting an empty list in `args` essentially + disables potentially interfering command line arguments. This was + a common setting for service scripts with python-icat <= 1.3.0. + """ + + # Manipulate the default search path. + monkeypatch.setenv("HOME", str(tmpconfigfile.home)) + cfgdirs = [ Path("~/.config/icat").expanduser(), + Path("~/.icat").expanduser(), + Path("."), ] + monkeypatch.setattr(icat.config, "cfgdirs", cfgdirs) + monkeypatch.chdir(str(tmpconfigfile.home)) + + # Set some bogus arguments in the command line, a mixture of + # formally valid and invalid ones, to verify that they will indeed + # be ignored. + cmdline = "cmd -w https://bogus.example.com/ -f foobar" + monkeypatch.setattr(sys, "argv", cmdline.split()) + preset = dict(configSection="example_pubreader") + config = icat.config.Config(ids=False, preset=preset, args=()) + _, conf = config.getconfig() + + ex = ExpectedConf(configFile=[tmpconfigfile.path], + configSection="example_pubreader", + url=ex_icat, + auth="simple", + username="pubreader", + password="pwpubreader", + promptPass=False, + credentials={'username': 'pubreader', + 'password': 'pwpubreader'}) + assert ex <= conf + + +def test_config_args_disable(monkeypatch, fakeClient, tmpconfigfile, + patchArgParse): + """Disable command line arguments by setting args to False. + + Same setting as in test_config_args_empty(), but fully disable + parsing of command line args instead of setting an empty args + list. Ref. #155. + """ + + # Manipulate the default search path. + monkeypatch.setenv("HOME", str(tmpconfigfile.home)) + cfgdirs = [ Path("~/.config/icat").expanduser(), + Path("~/.icat").expanduser(), + Path("."), ] + monkeypatch.setattr(icat.config, "cfgdirs", cfgdirs) + monkeypatch.chdir(str(tmpconfigfile.home)) + + # Set some bogus arguments in the command line, a mixture of + # formally valid and invalid ones, to verify that they will indeed + # be ignored. + cmdline = "cmd -w https://bogus.example.com/ -f foobar" + monkeypatch.setattr(sys, "argv", cmdline.split()) + preset = dict(configSection="example_pubreader") + config = icat.config.Config(ids=False, preset=preset, args=False) + _, conf = config.getconfig() + + ex = ExpectedConf(configFile=[tmpconfigfile.path], + configSection="example_pubreader", + url=ex_icat, + auth="simple", + username="pubreader", + password="pwpubreader", + promptPass=False, + credentials={'username': 'pubreader', + 'password': 'pwpubreader'}) + assert ex <= conf + + +def test_config_no_defaultvars(monkeypatch, tmpconfigfile): """Config object with no default variables. If `defaultvars=False` is passed to the constructor of Config, no @@ -284,8 +419,8 @@ def test_config_no_defaultvars(tmpconfigfile, monkeypatch): monkeypatch.setattr(icat.config, "cfgdirs", cfgdirs) monkeypatch.chdir(str(tmpconfigfile.home)) - args = ["-s", "example_root"] - config = icat.config.Config(defaultvars=False, args=args) + monkeypatch.setattr(sys, "argv", "cmd -s example_root".split()) + config = icat.config.Config(defaultvars=False) config.add_variable('url', ("-w", "--url"), dict(help="URL to the web service description")) config.add_variable('wobble', ("--wobble",), @@ -300,14 +435,15 @@ def test_config_no_defaultvars(tmpconfigfile, monkeypatch): assert ex <= conf -def test_config_simple_login(fakeClient, tmpconfigfile): +def test_config_simple_login(monkeypatch, fakeClient, tmpconfigfile): """Simple login example. Standard usage, read everything from a config file. """ - args = ["-c", str(tmpconfigfile.path), "-s", "example_root"] - _, conf = icat.config.Config(args=args).getconfig() + cmdline = "cmd -c %s -s example_root" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + _, conf = icat.config.Config().getconfig() ex = ExpectedConf(configFile=[tmpconfigfile.path], configSection="example_root", @@ -321,15 +457,16 @@ def test_config_simple_login(fakeClient, tmpconfigfile): assert ex <= conf -def test_config_override(fakeClient, tmpconfigfile): +def test_config_override(monkeypatch, fakeClient, tmpconfigfile): """ Read some stuff from a config file, override some other options with command line arguments. """ - args = ["-c", str(tmpconfigfile.path), "-s", "example_root", - "-a", "db", "-u", "rbeck", "-p", "geheim"] - _, conf = icat.config.Config(args=args).getconfig() + cmdline = ("cmd -c %s -s example_root -a db -u rbeck -p geheim" + % tmpconfigfile.path) + monkeypatch.setattr(sys, "argv", cmdline.split()) + _, conf = icat.config.Config().getconfig() ex = ExpectedConf(configFile=[tmpconfigfile.path], configSection="example_root", @@ -343,7 +480,7 @@ def test_config_override(fakeClient, tmpconfigfile): assert ex <= conf -def test_config_askpass(fakeClient, tmpconfigfile, monkeypatch): +def test_config_askpass(monkeypatch, fakeClient, tmpconfigfile): """ Same as test_config_override(), but do not pass the password in the command line arguments. In this case, getconfig() should @@ -354,9 +491,9 @@ def mockgetpass(prompt='Password: '): return "mockpass" monkeypatch.setattr(getpass, "getpass", mockgetpass) - args = ["-c", str(tmpconfigfile.path), "-s", "example_root", - "-a", "db", "-u", "rbeck"] - _, conf = icat.config.Config(args=args).getconfig() + cmdline = "cmd -c %s -s example_root -a db -u rbeck" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + _, conf = icat.config.Config().getconfig() ex = ExpectedConf(configFile=[tmpconfigfile.path], configSection="example_root", @@ -370,7 +507,7 @@ def mockgetpass(prompt='Password: '): assert ex <= conf -def test_config_nopass_askpass(fakeClient, tmpconfigfile, monkeypatch): +def test_config_nopass_askpass(monkeypatch, fakeClient, tmpconfigfile): """ Same as test_config_askpass(), but with no password set in the config file. Very early versions of icat.config had a bug to @@ -383,8 +520,9 @@ def mockgetpass(prompt='Password: '): return "mockpass" monkeypatch.setattr(getpass, "getpass", mockgetpass) - args = ["-c", str(tmpconfigfile.path), "-s", "example_nbour", "-P"] - _, conf = icat.config.Config(args=args).getconfig() + cmdline = "cmd -c %s -s example_nbour -P" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + _, conf = icat.config.Config().getconfig() ex = ExpectedConf(configFile=[tmpconfigfile.path], configSection="example_nbour", @@ -397,7 +535,7 @@ def mockgetpass(prompt='Password: '): assert ex <= conf -def test_config_askpass_file(fakeClient, tmpconfigfile, monkeypatch): +def test_config_askpass_file(monkeypatch, fakeClient, tmpconfigfile): """ Set promptPass in the configuration file. This should force prompting for the password. Issue #21. @@ -407,8 +545,9 @@ def mockgetpass(prompt='Password: '): return "mockpass" monkeypatch.setattr(getpass, "getpass", mockgetpass) - args = ["-c", str(tmpconfigfile.path), "-s", "test21"] - _, conf = icat.config.Config(args=args).getconfig() + cmdline = "cmd -c %s -s test21" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + _, conf = icat.config.Config().getconfig() ex = ExpectedConf(configFile=[tmpconfigfile.path], configSection="test21", @@ -421,7 +560,7 @@ def mockgetpass(prompt='Password: '): assert ex <= conf -def test_config_environment(fakeClient, tmpconfigfile, monkeypatch): +def test_config_environment(monkeypatch, fakeClient, tmpconfigfile): """Set some config variables from the environment. """ @@ -431,8 +570,9 @@ def test_config_environment(fakeClient, tmpconfigfile, monkeypatch): monkeypatch.setenv("https_proxy", "http://www-cache.example.org:3128/") monkeypatch.setenv("no_proxy", "localhost, .example.org") - args = ["-s", "example_root", "-u", "rbeck", "-p", "geheim"] - _, conf = icat.config.Config(args=args).getconfig() + cmdline = "cmd -s example_root -u rbeck -p geheim" + monkeypatch.setattr(sys, "argv", cmdline.split()) + _, conf = icat.config.Config().getconfig() ex = ExpectedConf(configFile=[tmpconfigfile.path], configSection="example_root", @@ -469,7 +609,7 @@ def test_config_environment(fakeClient, tmpconfigfile, monkeypatch): promptPass=False, credentials={'username': 'jdoe', 'password': 'pass'})), ]) -def test_config_ids(fakeClient, tmpconfigfile, section, ex): +def test_config_ids(monkeypatch, fakeClient, tmpconfigfile, section, ex): """Simple login example. Ask for the idsurl configuration variable. @@ -477,19 +617,21 @@ def test_config_ids(fakeClient, tmpconfigfile, section, ex): # We set ids="optional", the idsurl is present in section # example_root, but not in example_jdoe. In the latter case, the # configuration variable is present, but set to None.. - args = ["-c", str(tmpconfigfile.path), "-s", section] - _, conf = icat.config.Config(ids="optional", args=args).getconfig() + cmdline = "cmd -c %s -s %s" % (tmpconfigfile.path, section) + monkeypatch.setattr(sys, "argv", cmdline.split()) + _, conf = icat.config.Config(ids="optional").getconfig() assert ex <= conf -def test_config_custom_var(fakeClient, tmpconfigfile): +def test_config_custom_var(monkeypatch, fakeClient, tmpconfigfile): """Define custom configuration variables. """ # Note that ldap_filter is not defined in the configuration file, # but we have a default value defined here, so this is ok. - args = ["-c", str(tmpconfigfile.path), "-s", "example_root"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_root" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() config.add_variable('ldap_uri', ("-l", "--ldap-uri"), dict(help="URL of the LDAP server"), envvar='LDAP_URI') @@ -516,14 +658,15 @@ def test_config_custom_var(fakeClient, tmpconfigfile): assert ex <= conf -def test_config_subst_nosubst(fakeClient, tmpconfigfile): +def test_config_subst_nosubst(monkeypatch, fakeClient, tmpconfigfile): """Use a format string in a configuration variable. But disable the substitution. """ - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_jdoe" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() config.add_variable('greeting', ("--greeting",), dict(help="Greeting message"), subst=False) @@ -541,14 +684,15 @@ def test_config_subst_nosubst(fakeClient, tmpconfigfile): assert ex <= conf -def test_config_subst(fakeClient, tmpconfigfile): +def test_config_subst(monkeypatch, fakeClient, tmpconfigfile): """Use a format string in a configuration variable. Same as above, but enable the substitution this time. """ - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_jdoe" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() config.add_variable('greeting', ("--greeting",), dict(help="Greeting message"), subst=True) @@ -566,16 +710,16 @@ def test_config_subst(fakeClient, tmpconfigfile): assert ex <= conf -def test_config_subst_cmdline(fakeClient, tmpconfigfile): +def test_config_subst_cmdline(monkeypatch, fakeClient, tmpconfigfile): """Use a format string in a configuration variable. Same as above, but set the referenced variable from the command line. """ - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe", - "-u", "jonny", "-p", "pass"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_jdoe -u jonny -p pass" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() config.add_variable('greeting', ("--greeting",), dict(help="Greeting message"), subst=True) @@ -593,12 +737,13 @@ def test_config_subst_cmdline(fakeClient, tmpconfigfile): assert ex <= conf -def test_config_type_int(fakeClient, tmpconfigfile): +def test_config_type_int(monkeypatch, fakeClient, tmpconfigfile): """Read an integer variable from the configuration file. """ - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe"] - config = icat.config.Config(needlogin=False, args=args) + cmdline = "cmd -c %s -s example_jdoe" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config(needlogin=False) config.add_variable('num', ("--num",), dict(help="Integer variable"), type=int) _, conf = config.getconfig() @@ -610,14 +755,15 @@ def test_config_type_int(fakeClient, tmpconfigfile): assert ex <= conf -def test_config_type_int_err(fakeClient, tmpconfigfile): +def test_config_type_int_err(monkeypatch, fakeClient, tmpconfigfile): """Read an integer variable from the configuration file. Same as last one, but have an invalid value this time. """ - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe"] - config = icat.config.Config(needlogin=False, args=args) + cmdline = "cmd -c %s -s example_jdoe" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config(needlogin=False) config.add_variable('invnum', ("--invnum",), dict(help="Integer variable"), type=int) with pytest.raises(icat.exception.ConfigError) as err: @@ -637,11 +783,12 @@ def test_config_type_int_err(fakeClient, tmpconfigfile): flag1=True, flag2=True)), ]) -def test_config_type_boolean(fakeClient, tmpconfigfile, flags, ex): +def test_config_type_boolean(monkeypatch, fakeClient, tmpconfigfile, flags, ex): """Test a boolean configuration variable. """ - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe"] + flags - config = icat.config.Config(needlogin=False, args=args) + cmdline = "cmd -c %s -s example_jdoe" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split() + flags) + config = icat.config.Config(needlogin=False) config.add_variable('flag1', ("--flag1",), dict(help="Flag 1", action='store_const', const=True), type=icat.config.boolean) @@ -664,11 +811,12 @@ def test_config_type_boolean(fakeClient, tmpconfigfile, flags, ex): flag1=False, flag2=True)), ]) -def test_config_type_flag(fakeClient, tmpconfigfile, flags, ex): +def test_config_type_flag(monkeypatch, fakeClient, tmpconfigfile, flags, ex): """Test the special configuration variable type flag. """ - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe"] + flags - config = icat.config.Config(needlogin=False, args=args) + cmdline = "cmd -c %s -s example_jdoe" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split() + flags) + config = icat.config.Config(needlogin=False) config.add_variable('flag1', ("--flag1",), dict(help="Flag 1"), type=icat.config.flag) config.add_variable('flag2', ("--flag2",), @@ -677,15 +825,16 @@ def test_config_type_flag(fakeClient, tmpconfigfile, flags, ex): assert ex <= conf -def test_config_positional(fakeClient, tmpconfigfile): +def test_config_positional(monkeypatch, fakeClient, tmpconfigfile): """Test adding a positional argument on the command line. (There used to be a bug in adding positional arguments, fixed in 7d10764.) """ - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe", "test.dat"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_jdoe test.dat" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() config.add_variable('datafile', ("datafile",), dict(metavar="input.dat", help="name of the input datafile")) @@ -703,15 +852,16 @@ def test_config_positional(fakeClient, tmpconfigfile): assert ex <= conf -def test_config_disable(fakeClient, tmpconfigfile): +def test_config_disable(monkeypatch, fakeClient, tmpconfigfile): """Configuration variables may be disabled. Note that this feature is used internally in config and not intended to be used in client code. """ - args = ["-c", str(tmpconfigfile.path), "-s", "example_root"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_root" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() config.confvariable['promptPass'].disabled = True _, conf = config.getconfig() @@ -726,7 +876,7 @@ def test_config_disable(fakeClient, tmpconfigfile): assert not hasattr(conf, 'promptPass') -def test_config_authinfo_simple(fakeClient, monkeypatch, tmpconfigfile): +def test_config_authinfo_simple(monkeypatch, fakeClient, tmpconfigfile): """Simple login example. Talking to a server that supports getAuthenticatorInfo. @@ -743,8 +893,9 @@ def test_config_authinfo_simple(fakeClient, monkeypatch, tmpconfigfile): ] monkeypatch.setattr(FakeClient, "AuthInfo", authInfo) - args = ["-c", str(tmpconfigfile.path), "-s", "example_root"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_root" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() assert list(config.authenticatorInfo) == authInfo _, conf = config.getconfig() @@ -759,7 +910,7 @@ def test_config_authinfo_simple(fakeClient, monkeypatch, tmpconfigfile): assert ex <= conf -def test_config_authinfo_anon(fakeClient, monkeypatch, tmpconfigfile): +def test_config_authinfo_anon(monkeypatch, fakeClient, tmpconfigfile): """Anon login example. Same as last test, but selecting the anon authenticator this time. @@ -776,8 +927,9 @@ def test_config_authinfo_anon(fakeClient, monkeypatch, tmpconfigfile): ] monkeypatch.setattr(FakeClient, "AuthInfo", authInfo) - args = ["-c", str(tmpconfigfile.path), "-s", "example_root", "-a", "anon"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_root -a anon" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() assert list(config.authenticatorInfo) == authInfo _, conf = config.getconfig() @@ -791,7 +943,7 @@ def test_config_authinfo_anon(fakeClient, monkeypatch, tmpconfigfile): assert not hasattr(conf, 'username') -def test_config_authinfo_anon_only(fakeClient, monkeypatch, tmpconfigfile): +def test_config_authinfo_anon_only(monkeypatch, fakeClient, tmpconfigfile): """ Talk to a server that supports getAuthenticatorInfo and has only the anon authenticator. @@ -802,8 +954,9 @@ def test_config_authinfo_anon_only(fakeClient, monkeypatch, tmpconfigfile): ] monkeypatch.setattr(FakeClient, "AuthInfo", authInfo) - args = ["-c", str(tmpconfigfile.path), "-s", "example_anon"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_anon" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() assert list(config.authenticatorInfo) == authInfo _, conf = config.getconfig() @@ -817,7 +970,7 @@ def test_config_authinfo_anon_only(fakeClient, monkeypatch, tmpconfigfile): assert not hasattr(conf, 'username') -def test_config_authinfo_strange(fakeClient, monkeypatch, tmpconfigfile): +def test_config_authinfo_strange(monkeypatch, fakeClient, tmpconfigfile): """ Talk to a server that requests strange credential keys. Note the prefix "cred_" in the name of configuration variable and the @@ -831,9 +984,10 @@ def test_config_authinfo_strange(fakeClient, monkeypatch, tmpconfigfile): ] monkeypatch.setattr(FakeClient, "AuthInfo", authInfo) - args = ["-c", str(tmpconfigfile.path), "-s", "example_quirks", - "--cred_secret", "geheim"] - config = icat.config.Config(args=args) + cmdline = ("cmd -c %s -s example_quirks --cred_secret geheim" + % tmpconfigfile.path) + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() assert list(config.authenticatorInfo) == authInfo _, conf = config.getconfig() @@ -848,7 +1002,7 @@ def test_config_authinfo_strange(fakeClient, monkeypatch, tmpconfigfile): assert not hasattr(conf, 'username') -def test_config_authinfo_strange_preset(fakeClient, monkeypatch, tmpconfigfile): +def test_config_authinfo_strange_preset(monkeypatch, fakeClient, tmpconfigfile): """Talk to a server that requests strange credential keys. Almost the same as test_config_authinfo_strange(), but set the @@ -870,7 +1024,8 @@ def test_config_authinfo_strange_preset(fakeClient, monkeypatch, tmpconfigfile): preset = {"configFile": str(tmpconfigfile.path), "configSection": "example_quirks", "cred_secret": "geheim",} - config = icat.config.Config(preset=preset, args=()) + monkeypatch.setattr(sys, "argv", ["cmd"]) + config = icat.config.Config(preset=preset) assert list(config.authenticatorInfo) == authInfo _, conf = config.getconfig() @@ -885,13 +1040,14 @@ def test_config_authinfo_strange_preset(fakeClient, monkeypatch, tmpconfigfile): assert not hasattr(conf, 'username') -def test_config_authinfo_no_authinfo(fakeClient, monkeypatch, tmpconfigfile): +def test_config_authinfo_no_authinfo(monkeypatch, fakeClient, tmpconfigfile): """ Talk to an old server that does not support getAuthenticatorInfo. """ - args = ["-c", str(tmpconfigfile.path), "-s", "example_root"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_root" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() client, conf = config.getconfig() with pytest.raises(icat.exception.VersionMethodError) as err: @@ -908,7 +1064,7 @@ def test_config_authinfo_no_authinfo(fakeClient, monkeypatch, tmpconfigfile): assert ex <= conf -def test_config_authinfo_invalid_auth(fakeClient, monkeypatch, tmpconfigfile): +def test_config_authinfo_invalid_auth(monkeypatch, fakeClient, tmpconfigfile): """ Try to use an invalid authenticator. @@ -926,14 +1082,15 @@ def test_config_authinfo_invalid_auth(fakeClient, monkeypatch, tmpconfigfile): ] monkeypatch.setattr(FakeClient, "AuthInfo", authInfo) - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_jdoe" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() with pytest.raises(icat.exception.ConfigError) as err: _, conf = config.getconfig() assert "No such authenticator 'ldap'" in str(err.value) -def test_config_cfgpath_default(fakeClient, tmpconfigfile, monkeypatch, +def test_config_cfgpath_default(monkeypatch, fakeClient, tmpconfigfile, tmpfiles): """Test a cfgpath configuration variable. @@ -951,8 +1108,9 @@ def test_config_cfgpath_default(fakeClient, tmpconfigfile, monkeypatch, cpath = Path("~/.config/icat/control.dat").expanduser() tmpfiles.addfile(cpath, "control\n") - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_jdoe" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() config.add_variable('controlfile', ("--control",), dict(metavar="control.dat", help="control file"), default="control.dat", type=icat.config.cfgpath) @@ -971,7 +1129,7 @@ def test_config_cfgpath_default(fakeClient, tmpconfigfile, monkeypatch, assert conf.controlfile.is_file() -def test_config_cfgpath_cwd(fakeClient, tmpconfigfile, monkeypatch, tmpfiles): +def test_config_cfgpath_cwd(monkeypatch, fakeClient, tmpconfigfile, tmpfiles): """Test a cfgpath configuration variable. Same as test_config_cfgpath_default() but a file in the current @@ -991,8 +1149,9 @@ def test_config_cfgpath_cwd(fakeClient, tmpconfigfile, monkeypatch, tmpfiles): hpath = tmpconfigfile.home / "control.dat" tmpfiles.addfile(hpath, "control home\n") - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_jdoe" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() config.add_variable('controlfile', ("--control",), dict(metavar="control.dat", help="control file"), default="control.dat", type=icat.config.cfgpath) @@ -1012,7 +1171,7 @@ def test_config_cfgpath_cwd(fakeClient, tmpconfigfile, monkeypatch, tmpfiles): @pytest.mark.parametrize('abspath', [True, False]) -def test_config_cfgpath_cmdline(fakeClient, tmpconfigfile, monkeypatch, +def test_config_cfgpath_cmdline(monkeypatch, fakeClient, tmpconfigfile, tmpfiles, abspath): """Test a cfgpath configuration variable. @@ -1039,9 +1198,10 @@ def test_config_cfgpath_cmdline(fakeClient, tmpconfigfile, monkeypatch, cfarg = "cl.dat" tmpfiles.addfile(apath, "control cmdline\n") - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe", - "--control", cfarg] - config = icat.config.Config(args=args) + cmdline = ("cmd -c %s -s example_jdoe --control %s" + % (tmpconfigfile.path, cfarg)) + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() config.add_variable('controlfile', ("--control",), dict(metavar="control.dat", help="control file"), default="control.dat", type=icat.config.cfgpath) @@ -1060,7 +1220,7 @@ def test_config_cfgpath_cmdline(fakeClient, tmpconfigfile, monkeypatch, assert conf.controlfile.is_file() -def test_config_client_kwargs(fakeClient, tmpconfigfile, monkeypatch): +def test_config_client_kwargs(monkeypatch, fakeClient, tmpconfigfile): """Test client_kwargs attribute of config. Issue #38: There should be a way to access the kwargs used to @@ -1081,8 +1241,9 @@ def test_config_client_kwargs(fakeClient, tmpconfigfile, monkeypatch): monkeypatch.setenv("https_proxy", "http://www-cache.example.org:3128/") monkeypatch.setenv("no_proxy", "localhost, .example.org") - args = ["-c", str(tmpconfigfile.path), "-s", "example_root"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_root" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() client, conf = config.getconfig() ex = ExpectedConf(configFile=[tmpconfigfile.path], @@ -1105,7 +1266,7 @@ def test_config_client_kwargs(fakeClient, tmpconfigfile, monkeypatch): @pytest.mark.parametrize('subcmd', ["create", "ls", "info"]) -def test_config_subcmd(fakeClient, tmpconfigfile, subcmd): +def test_config_subcmd(monkeypatch, fakeClient, tmpconfigfile, subcmd): """Test sub-commands. Issue #59: Add support for sub-commands in config. @@ -1154,8 +1315,9 @@ def info_cmd(conf): "ls": ["ls", "--format", "long"], "info": ["info", "--name", "brightness", ], } - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe"] + sub_args[subcmd] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_jdoe" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split() + sub_args[subcmd]) + config = icat.config.Config() subcmds = config.add_subcommands() create_config = subcmds.add_subconfig('create', dict(help="create a foo"), @@ -1182,7 +1344,8 @@ def info_cmd(conf): assert conf.subcmd.name == subcmd -def test_config_subcmd_err_var_nonunique(fakeClient, tmpconfigfile): +def test_config_subcmd_err_var_nonunique(monkeypatch, fakeClient, + tmpconfigfile): """Test sub-commands. Issue #59: Add support for sub-commands in config. @@ -1193,9 +1356,10 @@ def test_config_subcmd_err_var_nonunique(fakeClient, tmpconfigfile): configurations define the same variables, see for instance "name" which is defined in both "create" and "info" in the last test.) """ - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe", - "sub", "--url", "http://example.org/"] - config = icat.config.Config(args=args) + cmdline = ("cmd -c %s -s example_jdoe sub --url http://example.org/" + % tmpconfigfile.path) + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() subcmds = config.add_subcommands() subconfig = subcmds.add_subconfig('sub') with pytest.raises(ValueError) as err: @@ -1203,7 +1367,8 @@ def test_config_subcmd_err_var_nonunique(fakeClient, tmpconfigfile): assert "variable 'url' is already defined" in str(err.value) -def test_config_subcmd_err_subcmd_nonunique(fakeClient, tmpconfigfile): +def test_config_subcmd_err_subcmd_nonunique(monkeypatch, fakeClient, + tmpconfigfile): """Test sub-commands. Issue #59: Add support for sub-commands in config. @@ -1211,14 +1376,16 @@ def test_config_subcmd_err_subcmd_nonunique(fakeClient, tmpconfigfile): Similar situation as last test: sub-command names may not collide with already defined variables as well. """ - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe", "url"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_jdoe url" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() with pytest.raises(ValueError) as err: subcmds = config.add_subcommands('url') assert "variable 'url' is already defined" in str(err.value) -def test_config_subcmd_err_add_more_vars(fakeClient, tmpconfigfile): +def test_config_subcmd_err_add_more_vars(monkeypatch, fakeClient, + tmpconfigfile): """Test sub-commands. Issue #59: Add support for sub-commands in config. @@ -1226,9 +1393,9 @@ def test_config_subcmd_err_add_more_vars(fakeClient, tmpconfigfile): No more variables may be added to a config after a subcommand has been added. """ - args = ["-c", str(tmpconfigfile.path), "-s", "example_jdoe", - "sub", "--name", "foo"] - config = icat.config.Config(args=args) + cmdline = "cmd -c %s -s example_jdoe sub --name foo" % tmpconfigfile.path + monkeypatch.setattr(sys, "argv", cmdline.split()) + config = icat.config.Config() subcmds = config.add_subcommands() subconfig = subcmds.add_subconfig('sub') with pytest.raises(RuntimeError) as err: @@ -1236,8 +1403,8 @@ def test_config_subcmd_err_add_more_vars(fakeClient, tmpconfigfile): assert "config already has subcommands" in str(err.value) -def test_deprecated_config_defaultsection(fakeClient, tmpconfigfile, - monkeypatch): +def test_deprecated_config_defaultsection(monkeypatch, fakeClient, + tmpconfigfile): """The module variable icat.config.defaultsection is deprecated since 1.0.0. @@ -1254,6 +1421,7 @@ def test_deprecated_config_defaultsection(fakeClient, tmpconfigfile, monkeypatch.chdir(str(tmpconfigfile.dir)) monkeypatch.setattr(icat.config, "defaultsection", "example_root") + monkeypatch.setattr(sys, "argv", ["cmd"]) with pytest.deprecated_call(): config = icat.config.Config(needlogin=False, ids=False, args=()) _, conf = config.getconfig() diff --git a/tests/test_07_entity_validate.py b/tests/test_07_entity_validate.py index 17c12f27..05db236d 100644 --- a/tests/test_07_entity_validate.py +++ b/tests/test_07_entity_validate.py @@ -100,7 +100,7 @@ def test_valid_numeric_value(client, dataset): param.create() assert param.id is not None -def test_valid_string_permissible_value(client, dataset): +def test_valid_string_simple_value(client, dataset): """Create a simple STRING parameter. """ client.typemap['parameter'].validate = validate_param