Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
RKrahl committed Aug 30, 2024
2 parents 7876725 + f48d2b0 commit 902c427
Show file tree
Hide file tree
Showing 11 changed files with 385 additions and 168 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/rst-lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"
29 changes: 29 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions doc/examples/init-icat.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 0 additions & 2 deletions doc/src/client.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 0 additions & 5 deletions doc/src/ingest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion src/icat/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
69 changes: 50 additions & 19 deletions src/icat/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
"""
Expand Down Expand Up @@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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.
Expand Down Expand Up @@ -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] == '_':
Expand Down Expand Up @@ -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


Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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 = {}
Expand Down
5 changes: 0 additions & 5 deletions src/icat/ingest.py
Original file line number Diff line number Diff line change
@@ -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
"""

Expand Down
Loading

0 comments on commit 902c427

Please sign in to comment.