Skip to content

Commit 902c427

Browse files
committed
Merge branch 'develop'
2 parents 7876725 + f48d2b0 commit 902c427

File tree

11 files changed

+385
-168
lines changed

11 files changed

+385
-168
lines changed

.github/workflows/rst-lint.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
with:
1515
fetch-depth: 0
1616
- name: Set up Python 3.11
17-
uses: actions/setup-python@v4
17+
uses: actions/setup-python@v5
1818
with:
1919
python-version: 3.11
2020
- name: Install dependencies
@@ -25,6 +25,6 @@ jobs:
2525
python setup.py build
2626
python doc/src/conf.py
2727
- name: doc8-check
28-
uses: deep-entertainment/doc8-action@v4
28+
uses: deep-entertainment/doc8-action@v5
2929
with:
3030
scanPaths: "doc/src"

CHANGES.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,35 @@ Changelog
22
=========
33

44

5+
.. _changes-1_4_0:
6+
7+
1.4.0 (2024-08-30)
8+
~~~~~~~~~~~~~~~~~~
9+
10+
New features
11+
------------
12+
13+
+ `#155`_, `#156`_: Add an option to disable parsing of command line
14+
arguments in :class:`icat.config.Config`.
15+
16+
Bug fixes and minor changes
17+
---------------------------
18+
19+
+ `#152`_: Fix a documentation error
20+
+ `#154`_: Fix a duplicate test name
21+
22+
Misc
23+
----
24+
25+
+ `#157`_: :mod:`icat.ingest` now considered stable.
26+
27+
.. _#152: https://github.com/icatproject/python-icat/pull/152
28+
.. _#154: https://github.com/icatproject/python-icat/pull/154
29+
.. _#155: https://github.com/icatproject/python-icat/issues/155
30+
.. _#156: https://github.com/icatproject/python-icat/pull/156
31+
.. _#157: https://github.com/icatproject/python-icat/pull/157
32+
33+
534
.. _changes-1_3_0:
635

736
1.3.0 (2024-03-21)

doc/examples/init-icat.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ def getUser(client, attrs):
126126
client.createRules("CRUD", uotables, uogroup)
127127

128128
# Setup permissions for the data ingester. They need read permission
129-
# on Investigation and Shift and create and create permission on
130-
# Dataset, Datafile, and the respective Parameter.
129+
# on Investigation and Shift and create permission on Dataset,
130+
# Datafile, and the respective Parameter.
131131
ingest = client.createUser("simple/dataingest", fullName="Data Ingester")
132132
ingestgroup = client.createGroup("ingest", [ ingest ])
133133
client.createRules("R", [ "Investigation", "Shift" ], ingestgroup)

doc/src/client.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ manages the interaction with an ICAT service as a client.
4848

4949
The :class:`ssl.SSLContext` instance that has been used to
5050
establish the HTTPS conection to the ICAT and IDS server.
51-
This is :const:`None` for old Python versions that do not have
52-
the :class:`ssl.SSLContext` class.
5351

5452
.. attribute:: typemap
5553

doc/src/ingest.rst

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@
55
66
.. versionadded:: 1.1.0
77

8-
.. note::
9-
The status of this module in the current version is still
10-
experimental. There may be incompatible changes in the future
11-
even in minor releases of python-icat.
12-
138
This module provides class :class:`icat.ingest.IngestReader` that
149
reads :ref:`ICAT-ingest-files` to add them to ICAT. It is designed
1510
for the use case of ingesting metadata for datasets created during

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ def run(self):
175175
"Programming Language :: Python :: 3.10",
176176
"Programming Language :: Python :: 3.11",
177177
"Programming Language :: Python :: 3.12",
178+
"Programming Language :: Python :: 3.13",
178179
"Topic :: Software Development :: Libraries :: Python Modules",
179180
],
180181
project_urls = dict(

src/icat/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ def searchChunked(self, query, skip=0, count=None, chunksize=100):
564564
# This version works!
565565
query = Query(client, "Dataset", includes="1", order=["id"])
566566
for ds in client.searchChunked(query):
567-
if not ds.complete:
567+
if ds.complete:
568568
continue
569569
ds.complete = True
570570
ds.update()

src/icat/config.py

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,16 @@ def get(self, variable):
271271
raise NotImplementedError
272272

273273

274+
class ConfigSourceDisabled():
275+
"""A disabled configuration source.
276+
277+
Do nothing and return :const:`None` for each variable to signal
278+
that this variable is not set in this source.
279+
"""
280+
def get(self, variable):
281+
return None
282+
283+
274284
class ConfigSourceCmdArgs(ConfigSource):
275285
"""Get configuration from command line arguments.
276286
"""
@@ -490,7 +500,7 @@ def add_variable(self, name, arg_opts=(), arg_kws=None,
490500
:type subst: :class:`bool`
491501
:return: the new configuration variable object.
492502
:rtype: :class:`icat.config.ConfigVariable`
493-
:raise RuntimeError: if this objects already has subcommands
503+
:raise RuntimeError: if this config object already has subcommands
494504
defined with :meth:`icat.config.BaseConfig.add_subcommands`.
495505
:raise ValueError: if the name is not valid.
496506
:see: the documentation of the :mod:`argparse` standard
@@ -502,6 +512,16 @@ def add_variable(self, name, arg_opts=(), arg_kws=None,
502512
raise ValueError("Config variable name '%s' is reserved." % name)
503513
if name in self.confvariable:
504514
raise ValueError("Config variable '%s' is already defined." % name)
515+
if self.argparser:
516+
self._add_argparser_argument(name, arg_opts, arg_kws, default, type)
517+
if type == flag:
518+
type = boolean
519+
var = ConfigVariable(name, envvar, optional, default, type, subst)
520+
self.confvariable[name] = var
521+
self.confvariables.append(var)
522+
return var
523+
524+
def _add_argparser_argument(self, name, arg_opts, arg_kws, default, type):
505525
if arg_kws is None:
506526
arg_kws = dict()
507527
else:
@@ -529,7 +549,6 @@ def add_variable(self, name, arg_opts=(), arg_kws=None,
529549
arg_kws['const'] = False
530550
arg_kws['help'] = argparse.SUPPRESS
531551
self.argparser.add_argument("--no-"+arg, **arg_kws)
532-
type = boolean
533552
elif arg_opts:
534553
prefix = self.argparser.prefix_chars
535554
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,
542561
# optional argument
543562
arg_kws['dest'] = name
544563
self.argparser.add_argument(*arg_opts, **arg_kws)
545-
var = ConfigVariable(name, envvar, optional, default, type, subst)
546-
self.confvariable[name] = var
547-
self.confvariables.append(var)
548-
return var
549564

550565
def add_subcommands(self, name='subcmd', arg_kws=None, optional=False):
551566
"""Defines a new configuration variable to select subcommands.
@@ -576,11 +591,16 @@ def add_subcommands(self, name='subcmd', arg_kws=None, optional=False):
576591
:type optional: :class:`bool`
577592
:return: the new subcommand object.
578593
:rtype: :class:`icat.config.ConfigSubCmd`
579-
:raise RuntimeError: if this objects already has subcommands.
594+
:raise RuntimeError: if parsing of command line arguments is
595+
disabled in this config object or if it already has
596+
subcommands.
580597
:raise ValueError: if the name is not valid.
581598
:see: the documentation of the :mod:`argparse` standard
582599
library module for details on `arg_kws`.
583600
"""
601+
if not self.argparser:
602+
raise RuntimeError("Command line parsing is disabled "
603+
"in this config, cannot add subcommands.")
584604
if self._subcmds is not None:
585605
raise RuntimeError("This config already has subcommands.")
586606
if name in self.ReservedVariables or name[0] == '_':
@@ -618,12 +638,12 @@ def _getconfig(self, sources, config=None):
618638
if value is not None and var.subst:
619639
value = value % config.as_dict()
620640
setattr(config, var.name, value)
641+
if var.postprocess:
642+
var.postprocess(self, config)
621643
if isinstance(var, ConfigSubCmds):
622644
if value is not None:
623645
value._getconfig(sources, config)
624646
break
625-
if var.postprocess:
626-
var.postprocess(self, config)
627647
return config
628648

629649

@@ -662,21 +682,30 @@ class Config(BaseConfig):
662682
environment variables, and settings in the configuration files
663683
still take precedence over the preset values.
664684
:type preset: :class:`dict`
665-
:param args: list of command line arguments or :const:`None`. If
666-
not set, the command line arguments will be taken from
667-
:data:`sys.argv`.
668-
:type args: :class:`list` of :class:`str`
685+
:param args: list of command line arguments. If set to the
686+
special value :const:`False`, parsing of command line
687+
arguments will be disabled. The default, if :const:`None` is
688+
to take the command line arguments from :data:`sys.argv`.
689+
:type args: :class:`list` of :class:`str` or :class:`bool`
669690
670691
.. versionchanged:: 1.0.0
671692
add the `preset` argument.
693+
694+
.. versionchanged:: 1.4.0
695+
allow to disable parsing of command line arguments, setting
696+
`args` to :const:`False`.
672697
"""
673698

674699
def __init__(self, defaultvars=True, needlogin=True, ids="optional",
675700
preset=None, args=None):
676701
"""Initialize the object.
677702
"""
678-
super().__init__(argparse.ArgumentParser())
679-
self.cmdargs = ConfigSourceCmdArgs(self.argparser)
703+
if args is False:
704+
super().__init__(None)
705+
self.cmdargs = ConfigSourceDisabled()
706+
else:
707+
super().__init__(argparse.ArgumentParser())
708+
self.cmdargs = ConfigSourceCmdArgs(self.argparser)
680709
self.environ = ConfigSourceEnvironment()
681710
defaultFiles = [str(d / cfgfile) for d in cfgdirs]
682711
self.conffile = ConfigSourceFile(defaultFiles)
@@ -731,7 +760,8 @@ def getconfig(self):
731760
configuration file, if an invalid value is given to a
732761
variable, or if a mandatory variable is not defined.
733762
"""
734-
self.cmdargs.parse_args(self.args)
763+
if self.argparser:
764+
self.cmdargs.parse_args(self.args)
735765
config = self._getconfig(self.sources)
736766

737767
if self.needlogin:
@@ -841,9 +871,10 @@ def _setup_client(self):
841871
"""Initialize the client.
842872
"""
843873
try:
844-
with _argparserDisableExit(self.argparser):
845-
self.cmdargs.parse_args(self.args, partial=True)
846-
config = self._getconfig(self.sources)
874+
if self.argparser:
875+
with _argparserDisableExit(self.argparser):
876+
self.cmdargs.parse_args(self.args, partial=True)
877+
config = self._getconfig(self.sources)
847878
except ConfigError:
848879
return None, None
849880
client_kwargs = {}

src/icat/ingest.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
"""Ingest metadata into ICAT.
22
3-
.. note::
4-
The status of this module in the current version is still
5-
experimental. There may be incompatible changes in the future
6-
even in minor releases of python-icat.
7-
83
.. versionadded:: 1.1.0
94
"""
105

0 commit comments

Comments
 (0)