# http://pyrocko.org - GPLv3
#
# The Pyrocko Developers, 21st Century
# ---|P------/S----------~Lg----------
'''
Squirrel command line tool infrastructure and argument parsing.
'''
import sys
import argparse
import logging
from pyrocko import util, progress, io, guts
from pyrocko.cli import PyrockoArgumentParser, dq, ldq # noqa
from pyrocko.squirrel import error
from pyrocko.squirrel import storage
logger = logging.getLogger('psq.tool.common')
help_time_format = 'Format: ```YYYY-MM-DD HH:MM:SS.FFF```, truncation allowed.'
g_epilog_squirrel = '''
----
Manual: https://pyrocko.org/docs/current/apps/squirrel
Tutorial: https://pyrocko.org/docs/current/apps/squirrel/tutorial.html
Examples: https://pyrocko.org/docs/current/apps/squirrel/manual.html#examples
🐿️
'''
[docs]
class SquirrelArgumentParser(PyrockoArgumentParser):
'''
Parser for CLI arguments with a some extras for Squirrel based apps.
:param command:
Implementation of the command.
:type command:
:py:class:`SquirrelCommand` or module providing the same interface
:param subcommands:
Implementations of subcommands.
:type subcommands:
:py:class:`list` of :py:class:`SquirrelCommand` or modules providing
the same interface
:param \\*args:
Handed through to base class's init.
:param \\*\\*kwargs:
Handed through to base class's init.
'''
def __init__(self, *args, command=None, subcommands=[], **kwargs):
self._command = command
self._subcommands = subcommands
self._have_selection_arguments = False
self._have_selection_arguments_base = False
self._have_query_arguments = False
self._have_storage_scheme_arguments = False
# Subcommand parsers inherit the epilog of their parent, unless set
# explicitly.
self._epilog_explicit = 'epilog' in kwargs
self._child_parsers = []
kwargs['epilog'] = kwargs.get('epilog', g_epilog_squirrel)
kwargs['add_help'] = False
PyrockoArgumentParser.__init__(self, *args, **kwargs)
add_standard_arguments(self)
self._command = None
self._subcommands = []
if command:
self.set_command(command)
if subcommands:
self.set_subcommands(subcommands)
def set_command(self, command):
command.setup(self)
self.set_defaults(target=command.run)
def set_subcommands(self, subcommands):
subparsers = self.add_subparsers(
metavar='SUBCOMMAND',
title='Subcommands')
for mod in subcommands:
subparser = mod.make_subparser(subparsers)
if subparser is None:
raise Exception(
'make_subparser(subparsers) must return the created '
'parser.')
mod.setup(subparser)
subparser.set_defaults(target=mod.run, subparser=subparser)
if isinstance(subparser, SquirrelArgumentParser):
self._child_parsers.append(subparser)
subparser._inherit_epilog(self.epilog)
def _inherit_epilog(self, epilog):
if not self._epilog_explicit:
self.epilog = epilog
for child in self._child_parsers:
child._inherit_epilog(epilog)
[docs]
def parse_args(self, args=None, namespace=None):
'''
Parse arguments given on command line.
Extends the functionality of
:py:meth:`argparse.ArgumentParser.parse_args` to process and handle the
standard options ``--loglevel``, ``--progress`` and ``--help``.
'''
args = PyrockoArgumentParser.parse_args(
self, args=args, namespace=namespace)
eff_parser = args.__dict__.get('subparser', self)
process_standard_arguments(eff_parser, args)
if eff_parser._have_selection_arguments:
def make_squirrel(check_have_data=True):
sq = squirrel_from_selection_arguments(
args, check_have_data=check_have_data)
if 'squirrel_query' in args:
hint_codes_patterns_extra(
sq, args.squirrel_query.get('codes', []))
return sq
args.make_squirrel = make_squirrel
if eff_parser._have_selection_arguments_base:
def make_dataset():
return dataset_from_selection_arguments(args)
args.make_dataset = make_dataset
if eff_parser._have_query_arguments:
try:
args.squirrel_query = squirrel_query_from_arguments(args)
except (error.SquirrelError, error.ToolError) as e:
logger.fatal(str(e))
sys.exit(1)
if eff_parser._have_storage_scheme_arguments:
try:
args.squirrel_effective_storage_scheme = \
squirrel_effective_storage_scheme_from_arguments(args)
except (error.SquirrelError, error.ToolError) as e:
logger.fatal(str(e))
sys.exit(1)
return args
[docs]
def dispatch(self, args):
'''
Dispatch execution to selected command/subcommand.
:param args:
Parsed arguments obtained from :py:meth:`parse_args`.
:returns:
``True`` if dispatching was successful, ``False`` otherwise.
If an exception of type
:py:exc:`~pyrocko.squirrel.error.SquirrelError` or
:py:exc:`~pyrocko.squirrel.error.ToolError` is caught, the error is
logged and the program is terminated with exit code 1.
'''
eff_parser = args.__dict__.get('subparser', self)
target = args.__dict__.get('target', None)
if target:
try:
target(eff_parser, args)
return True
except (error.SquirrelError, error.ToolError) as e:
logger.fatal(str(e))
sys.exit(1)
return False
[docs]
def run(self, args=None):
'''
Parse arguments and dispatch to selected command/subcommand.
This simply calls :py:meth:`parse_args` and then :py:meth:`dispatch`
with the obtained ``args``. A usage message is printed if no command is
selected.
'''
args = self.parse_args(args)
if not self.dispatch(args):
self.print_help()
[docs]
def add_squirrel_selection_arguments(self, without=[]):
'''
Set up command line options commonly used to configure a
:py:class:`~pyrocko.squirrel.base.Squirrel` instance.
This will add optional arguments ``--add``, ``--include``,
``--exclude``, ``--optimistic``, ``--format``, ``--add-only``,
``--persistent``, and ``--dataset``.
Call ``args.make_squirrel()`` on the arguments returned from
:py:meth:`parse_args` to finally instantiate and configure the
:py:class:`~pyrocko.squirrel.base.Squirrel` instance.
'''
add_squirrel_selection_arguments(self, without=without)
self._have_selection_arguments = True
[docs]
def add_squirrel_selection_arguments_base(self, without=[]):
'''
Set up command line options commonly used to configure a
:py:class:`~pyrocko.squirrel.dataset.Dataset` instance.
This will add optional arguments ``--add``, ``--include``,
``--exclude``, ``--format``, ``--add-only``.
Call ``args.return make_dataset()`` on the arguments returned from
:py:meth:`parse_args` to finally instantiate and configure the
:py:class:`~pyrocko.squirrel.dataset.Dataset` instance.
'''
add_squirrel_selection_arguments_base(self)
self._have_selection_arguments_base = True
[docs]
def add_squirrel_query_arguments(self, without=[]):
'''
Set up command line options commonly used in squirrel queries.
This will add optional arguments ``--kinds``, ``--codes``, ``--tmin``,
``--tmax``, and ``--time``.
Once finished with parsing, the query arguments are available as
``args.squirrel_query`` on the arguments returned from
:py:meth:`parse_args`.
:param without:
Suppress adding given options.
:type without:
:py:class:`list` of :py:class:`str`, choices: ``'tmin'``,
``'tmax'``, ``'codes'``, and ``'time'``.
'''
add_squirrel_query_arguments(self, without=without)
self._have_query_arguments = True
[docs]
def add_squirrel_storage_scheme_arguments(self):
'''
Set up command line options commonly used for saving.
This will add optional arguments ``--out-path``, ``--out-sds-path``,
``--out-storage-path``, ``--out-storage-scheme``, ``--out-format``,
``--out-mseed-record-length`` and ``--out-mseed-steim``.
Once finished with parsing, the
:py:class:`pyrocko.squirrel.storage.StorageScheme` is available as
``args.squirrel_effective_storage_scheme`` on the arguments returned
from :py:meth:`parse_args`.
'''
add_squirrel_storage_scheme_arguments(self)
self._have_storage_scheme_arguments = True
def csvtype(choices):
def splitarg(arg):
values = arg.split(',')
for value in values:
if value not in choices:
raise argparse.ArgumentTypeError(
'Invalid choice: {!r} (choose from {})'
.format(value, ', '.join(map(repr, choices))))
return values
return splitarg
def add_standard_arguments(parser):
group = parser.add_argument_group('General options')
group.add_argument(
'--help', '-h',
action='help',
help='Show this help message and exit.')
loglevel_choices = ['critical', 'error', 'warning', 'info', 'debug']
loglevel_default = 'info'
group.add_argument(
'--loglevel',
choices=loglevel_choices,
default=loglevel_default,
metavar='LEVEL',
help='Set logger level. Choices: %s. Default: %s.' % (
ldq(loglevel_choices), dq(loglevel_default)))
progress_choices = ['terminal', 'log', 'off']
progress_default = 'terminal'
group.add_argument(
'--progress',
choices=progress_choices,
default=progress_default,
metavar='DEST',
help='Set how progress status is reported. Choices: %s. '
'Default: %s.' % (
ldq(progress_choices), dq(progress_default)))
group.add_argument(
'--threads-loading',
dest='n_threads',
type=int,
default=1,
metavar='INT',
help='Set number of threads used in file content loading/decoding. '
'Default: 1')
def process_standard_arguments(parser, args):
loglevel = args.__dict__.pop('loglevel')
util.setup_logging(parser.prog, loglevel)
pmode = args.__dict__.pop('progress')
progress.set_default_viewer(pmode)
[docs]
def add_squirrel_selection_arguments(parser, without=[]):
'''
Set up command line options commonly used to configure a
:py:class:`~pyrocko.squirrel.base.Squirrel` instance.
This will optional arguments ``--add``, ``--include``, ``--exclude``,
``--optimistic``, ``--format``, ``--add-only``, ``--persistent``,
and ``--dataset`` to a given argument parser.
Once finished with parsing, call
:py:func:`squirrel_from_selection_arguments` to finally instantiate and
configure the :py:class:`~pyrocko.squirrel.base.Squirrel` instance.
:param parser:
The argument parser to be configured.
:type parser:
argparse.ArgumentParser
:param without:
Suppress adding given options.
:type without:
:py:class:`list` of :py:class:`str`
'''
from pyrocko import squirrel as sq
group = parser.add_argument_group('Data collection options')
if 'add' not in without:
group.add_argument(
'--add', '-a',
dest='paths',
metavar='PATH',
nargs='+',
help='Add files and directories with waveforms, metadata and '
'events. Content is indexed and added to the temporary '
'(default) or persistent (see ``--persistent``) data '
'selection.')
if 'include' not in without:
group.add_argument(
'--include',
dest='include',
metavar='REGEX',
help='Only include files whose paths match the regular expression '
"``REGEX``. Examples: ``--include='\\.MSEED$'`` would only "
'match files ending with ```.MSEED```. '
"``--include='\\.BH[EN]\\.'`` would match paths containing "
"```.BHE.``` or ```.BHN.```. ``--include='/2011/'`` would "
'match paths with a subdirectory ```2011``` in their path '
'hierarchy.')
if 'exclude' not in without:
group.add_argument(
'--exclude',
dest='exclude',
metavar='REGEX',
help='Only include files whose paths do not match the regular '
"expression ``REGEX``. Examples: "
"``--exclude='/\\.DS_Store/'`` would exclude anything inside "
'any ```.DS_Store``` subdirectory.')
if 'optimistic' not in without:
group.add_argument(
'--optimistic', '-o',
action='store_false',
dest='check',
default=True,
help='Disable checking file modification times for faster '
'startup.')
if 'format' not in without:
group.add_argument(
'--format', '-f',
dest='format',
metavar='FORMAT',
default='detect',
choices=sq.supported_formats(),
help='Assume input files are of given ``FORMAT``. Choices: %s. '
'Default: %s.' % (
ldq(sq.supported_formats()),
dq('detect')))
if 'add-only' not in without:
group.add_argument(
'--add-only',
type=csvtype(sq.supported_content_kinds()),
dest='kinds_add',
metavar='KINDS',
help='Restrict meta-data scanning to given content kinds. '
'``KINDS`` is a comma-separated list of content kinds. '
'Choices: %s. By default, all content kinds are indexed.'
% ldq(sq.supported_content_kinds()))
if 'persistent' not in without:
group.add_argument(
'--persistent', '-p',
dest='persistent',
metavar='NAME',
help='Create/use persistent selection with given ``NAME``. '
'Persistent selections can be used to speed up startup of '
'Squirrel-based applications.')
if 'samples-block' not in without:
group.add_argument(
'--samples-block',
dest='n_samples_block',
type=int,
metavar='N',
default=100000,
help='When downloading data, use blocks with approximately ``N`` '
'samples. Default: 100000')
if 'dataset' not in without:
group.add_argument(
'--dataset', '-d',
dest='datasets',
default=[],
action='append',
metavar='FILE',
help='Add files, directories and remote sources from dataset '
'description file. This option can be repeated to add '
'multiple datasets. Run ```squirrel template``` to obtain '
'examples of dataset description files.')
if 'upgrade-storage' not in without:
group.add_argument(
'--upgrade-storage',
dest='upgrade_storage',
default=False,
action='store_true',
help='Upgrade storage layout of cached data to latest version.')
[docs]
def add_squirrel_selection_arguments_base(parser):
'''
Set up command line options used to configure a
:py:class:`~pyrocko.squirrel.dataset.Dataset` instance.
This is adds a subset of the arguments added by
:py:func:`add_squirrel_selection_arguments`.
'''
return add_squirrel_selection_arguments(parser, without=[
'dataset',
'upgrade-storage',
'samples-block',
'persistent',
'optimistic'])
[docs]
def squirrel_from_selection_arguments(args, check_have_data=True):
'''
Create a :py:class:`~pyrocko.squirrel.base.Squirrel` instance from command
line arguments.
Use :py:func:`add_squirrel_selection_arguments` to configure the parser
with the necessary options.
:param args:
Parsed command line arguments, as returned by
:py:meth:`argparse.ArgumentParser.parse_args`.
:returns:
:py:class:`pyrocko.squirrel.base.Squirrel` instance with paths,
datasets and remote sources added.
'''
from pyrocko.squirrel import base
if check_have_data and not (
args.persistent or args.datasets or args.paths):
raise error.ToolError(
'No data. Use --add, --dataset, and/or --persistent to set up '
'data sources.')
squirrel = base.Squirrel(
persistent=args.persistent,
n_samples_block=args.n_samples_block,
n_threads=getattr(args, 'n_threads', 1))
with progress.view():
if args.paths:
squirrel.add(
args.paths,
check=args.check,
format=args.format,
kinds=args.kinds_add or None,
include=args.include,
exclude=args.exclude)
with progress.task('add datasets', logger=logger) as task:
for dataset_path in task(args.datasets):
squirrel.add_dataset(
dataset_path,
check=args.check,
upgrade=args.upgrade_storage)
return squirrel
[docs]
def dataset_from_selection_arguments(args):
'''
Create a :py:class:`~pyrocko.squirrel.dataset.Dataset` instance from
command line arguments.
The set of supported arguments for the dataset is a subset of the data
collection options. Use :py:func:`add_squirrel_selection_arguments_base` to
configure the parser with the necessary options.
:param args:
Parsed command line arguments, as returned by
:py:meth:`argparse.ArgumentParser.parse_args`.
:returns:
:py:class:`pyrocko.squirrel.dataset.Dataset` instance
'''
from pyrocko.squirrel.dataset import Dataset
from pyrocko.squirrel.client.local import LocalData
dataset = Dataset(
path_prefix='.',
sources=[
LocalData(
paths=args.paths,
kinds=args.kinds_add or None,
include=args.include,
exclude=args.exclude,
format=args.format)])
dataset.set_basepath('.')
return dataset
[docs]
def add_squirrel_query_arguments(parser, without=[]):
'''
Set up command line options commonly used in squirrel queries.
This will add optional arguments ``--kinds``, ``--codes``, ``--tmin``,
``--tmax``, and ``--time``.
Once finished with parsing, call
:py:func:`squirrel_query_from_arguments` to get the parsed values.
:param parser:
The argument parser to be configured.
:type parser:
argparse.ArgumentParser
:param without:
Suppress adding given options.
:type without:
:py:class:`list` of :py:class:`str`
'''
from pyrocko import squirrel as sq
group = parser.add_argument_group('Data query options')
if 'kinds' not in without:
group.add_argument(
'--kinds',
type=csvtype(sq.supported_content_kinds()),
dest='kinds',
metavar='KINDS',
help='Content kinds to query. ``KINDS`` is a comma-separated list '
'of content kinds. Choices: %s. By default, all content '
'kinds are queried.' % ldq(sq.supported_content_kinds()))
if 'codes' not in without:
group.add_argument(
'--codes',
dest='codes',
metavar='CODES',
help='Code patterns to query (``STA``, ``NET.STA``, '
'``NET.STA.LOC``, ``NET.STA.LOC.CHA``, or '
'``NET.STA.LOC.CHA.EXTRA``). The pattern may contain '
'wildcards ``*`` (zero or more arbitrary characters), ``?`` '
'(single arbitrary character), and ``[CHARS]`` (any '
'character out of ``CHARS``). Multiple patterns can be '
'given by separating them with commas.')
group.add_argument(
'--codes-exclude',
dest='codes_exclude',
metavar='CODES',
help='Code patterns to exclude. See ``--codes``.')
if 'tmin' not in without:
group.add_argument(
'--tmin',
dest='tmin',
metavar='TIME',
help='Begin of time interval to query. %s' % help_time_format)
if 'tmax' not in without:
group.add_argument(
'--tmax',
dest='tmax',
metavar='TIME',
help='End of time interval to query. %s' % help_time_format)
if 'time' not in without:
group.add_argument(
'--time',
dest='time',
metavar='TIME',
help='Time instant to query. %s' % help_time_format)
[docs]
def ce(prefix, func, *args):
'''
Convert Exceptions in to ToolError.
'''
try:
return func(*args)
except Exception as e:
raise error.ToolError('%s: %s' % (prefix, str(e)))
[docs]
def squirrel_query_from_arguments(args):
'''
Get common arguments to be used in squirrel queries from command line.
Use :py:func:`add_squirrel_query_arguments` to configure the parser with
the necessary options.
:param args:
Parsed command line arguments, as returned by
:py:meth:`argparse.ArgumentParser.parse_args`.
:returns:
:py:class:`dict` with any parsed option values.
'''
from pyrocko import squirrel as sq
d = {}
if 'kinds' in args and args.kinds:
d['kind'] = args.kinds
if 'tmin' in args and args.tmin:
d['tmin'] = ce(
'--tmin', util.str_to_time_fillup, args.tmin)
if 'tmax' in args and args.tmax:
d['tmax'] = ce(
'--tmax', util.str_to_time_fillup, args.tmax)
if 'time' in args and args.time:
d['tmin'] = d['tmax'] = ce(
'--time', util.str_to_time_fillup, args.time)
if 'codes' in args and args.codes:
d['codes'] = [
sq.to_codes_guess(s.strip()) for s in args.codes.split(',')]
if 'codes_exclude' in args and args.codes_exclude:
d['codes_exclude'] = [
sq.to_codes_guess(s.strip())
for s in args.codes_exclude.split(',')]
if ('tmin' in d and 'time' in d) or ('tmax' in d and 'time' in d):
raise error.ToolError(
'Options --tmin/--tmax and --time are mutually exclusive.')
return d
[docs]
def add_squirrel_storage_scheme_arguments(parser):
'''
Set up command line options commonly used for saving.
This will add optional arguments ``--out-path``, ``--out-sds-path``,
``--out-storage-path``, ``--out-storage-scheme``, ``--out-format``,
``--out-mseed-record-length`` and ``--out-mseed-steim``.
Once finished with parsing, call
:py:func:`squirrel_effective_storage_scheme_from_arguments` to get the
configured :py:class:`pyrocko.squirrel.storage.StorageScheme` instance.
:param parser:
The argument parser to be configured.
:type parser:
argparse.ArgumentParser
'''
group = parser.add_argument_group('Storage options')
group.add_argument(
'--out-path',
dest='out_path',
metavar='TEMPLATE',
help='''
Set output path to ``TEMPLATE``. Available placeholders are ``%%n``: network,
``%%s``: station, ``%%l``: location, ``%%c``: channel, ``%%b``: begin time,
``%%e``: end time, ``%%j``: julian day of year. The following additional
placeholders use the current processing window's begin and end times rather
than trace begin and end times (to suppress producing many small files for
gappy traces), ``%%(wmin_year)s``, ``%%(wmin_month)s``, ``%%(wmin_day)s``,
``%%(wmin)s``, ``%%(wmin_jday)s``, ``%%(wmax_year)s``, ``%%(wmax_month)s``,
``%%(wmax_day)s``, ``%%(wmax)s``, ``%%(wmax_jday)s``. Example: ``--out-path
'data/%%s/trace-%%s-%%c.mseed'``
'''.strip())
group.add_argument(
'--out-sds-path',
dest='out_sds_path',
metavar='PATH',
help='''
Set output path to create an SDS archive
(https://www.seiscomp.de/seiscomp3/doc/applications/slarchive/SDS.html), rooted
at PATH. Implies ``--tinc 3600`` if not specified otherwise. Equivalent to
``--out-storage-path PATH --out-storage-scheme sds``. Example:
``--out-sds-path data/sds``
'''.strip())
group.add_argument(
'--out-storage-path',
dest='out_storage_path',
metavar='PATH',
help='''
Create storage directory under PATH. The storage scheme can be set with
``--out-storage-scheme``.
'''.strip())
group.add_argument(
'--out-storage-scheme',
dest='out_storage_scheme',
default='default',
choices=storage.StorageSchemeChoice.choices,
metavar='SCHEME',
help='''
Set storage scheme to produce when using ``--out-storage-path``. Choices: %s
'''.strip() % ldq(storage.StorageSchemeChoice.choices))
group.add_argument(
'--out-format',
dest='out_format',
choices=io.allowed_formats('save'),
metavar='FORMAT',
help='Set output file format. Choices: %s' % io.allowed_formats(
'save', 'cli_help', 'mseed'))
group.add_argument(
'--out-mseed-record-length',
dest='out_mseed_record_length',
type=int,
choices=io.mseed.VALID_RECORD_LENGTHS,
metavar='INT',
help='Set the Mini-SEED record length in bytes. Choices: %s. '
'Default is 4096 bytes, which is commonly used for archiving, '
'unless the selected storage scheme specifies a different '
'default.' % ldq(str(b) for b in io.mseed.VALID_RECORD_LENGTHS))
group.add_argument(
'--out-mseed-steim',
dest='out_mseed_steim',
type=int,
choices=(1, 2),
metavar='INT',
help='Set the Mini-SEED STEIM compression. Choices: ``1`` or '
'``2``. Default is STEIM-2 unless the selected storage scheme '
'specifies a different default. Note: STEIM-2 is limited to 30 '
'bit dynamic range.')
[docs]
def squirrel_effective_storage_scheme_from_arguments(args):
'''
Get storage scheme from command line arguments.
Use :py:func:`add_squirrel_storage_scheme_arguments` to configure the
parser with the necessary options.
:param args:
Parsed command line arguments, as returned by
:py:meth:`argparse.ArgumentParser.parse_args`.
:returns:
:py:class:`pyrocko.squirrel.storage.StorageScheme` or ``None`` if
neither ``--out-path`` nor ``--out-sds-path`` nor
``--out-storage-path`` is given.
'''
nset = sum(x is not None for x in (
args.out_path,
args.out_sds_path,
args.out_storage_path))
if nset > 1:
raise error.ToolError(
'Only one of the options --out-path, --out-sds-path, and '
'--out-storage-path may be selected.')
if args.out_path:
scheme = storage.StorageScheme(
name='custom',
layouts=[storage.StorageSchemeLayout(
name='custom',
path_template=args.out_path)])
elif args.out_sds_path:
scheme = guts.clone(storage.get_storage_scheme('sds'))
scheme.set_base_path(args.out_sds_path)
elif args.out_storage_path:
scheme = guts.clone(storage.get_storage_scheme(
args.out_storage_scheme))
scheme.set_base_path(args.out_storage_path)
else:
return None
if args.out_mseed_record_length is not None:
scheme.mseed_record_length = args.out_mseed_record_length
if args.out_mseed_steim is not None:
scheme.mseed_steim = args.out_mseed_steim
if args.out_format is not None:
scheme.format = args.out_format
return scheme
[docs]
class SquirrelCommand(object):
'''
Base class for Squirrel-based CLI programs and subcommands.
'''
[docs]
def fail(self, message):
'''
Raises :py:exc:`~pyrocko.squirrel.error.ToolError`.
:py:meth:`SquirrelArgumentParser.run` catches
:py:exc:`~pyrocko.squirrel.error.ToolError`, logs the error message and
terminates with an error exit state.
'''
raise error.ToolError(message)
[docs]
def make_subparser(self, subparsers):
'''
To be implemented in subcommand. Create subcommand parser.
Must return a newly created parser obtained with
``subparsers.add_parser(...)``, e.g.::
def make_subparser(self, subparsers):
return subparsers.add_parser(
'plot', help='Draw a nice plot.')
'''
return subparsers.add_parser(
self.__class__.__name__, help='Undocumented.')
[docs]
def setup(self, parser):
'''
To be implemented in subcommand. Configure parser.
:param parser:
The argument parser to be configured.
:type parser:
argparse.ArgumentParser
Example::
def setup(self, parser):
parser.add_squirrel_selection_arguments()
parser.add_squirrel_query_arguments()
parser.add_argument(
'--fmin',
dest='fmin',
metavar='FLOAT',
type=float,
help='Corner of highpass [Hz].')
'''
pass
[docs]
def run(self, parser, args):
'''
To be implemented in subcommand. Main routine of the command.
:param parser:
The argument parser to be configured.
:type parser:
argparse.ArgumentParser
:param args:
Parsed command line arguments, as returned by
:py:meth:`argparse.ArgumentParser.parse_args`.
Example::
def run(self, parser, args):
print('User has selected fmin = %g Hz' % args.fmin)
# args.make_squirrel() is available if
# parser.add_squirrel_selection_arguments() was called during
# setup().
sq = args.make_squirrel()
# args.squirrel_query is available if
# praser.add_squirrel_query_arguments() was called during
# setup().
stations = sq.get_stations(**args.squirrel_query)
'''
pass
def add_mantra_arguments(parser):
parser.add_argument(
'--mantra',
dest='mantra_selection',
metavar='PATH[:PATTERN,...]',
help='Read mantra configurations from PATH. If PATTERN(s) are '
'specified, restrict execution to matching mantra names.')
def get_mantras_from_arguments(args):
from pyrocko.squirrel.mantra import Mantra
if not args.mantra_selection:
return []
if ':' not in args.mantra_selection:
path = args.mantra_selection
patterns = None
else:
path, _patterns = args.mantra_selection.split(':')
patterns = _patterns.split(',')
try:
mantras = guts.load_all(filename=path)
except Exception as e:
raise error.ToolError(
'Error while reading mantra configurations from "%s": %s' % (
path, str(e)))
for mantra in mantras:
if not isinstance(mantra, Mantra):
raise error.ToolError(
'Configuration file "%s" must contain Mantra objects.' % path)
names = [mantra.name for mantra in mantras]
if patterns:
try:
names = set(util.glob_filter(
patterns, names, raise_if_nomatch=True))
except util.GlobFilterNoMatch as e:
raise error.ToolError(str(e)) from None
names = set(names)
return [mantra for mantra in mantras if mantra.name in names]
__all__ = [
'SquirrelArgumentParser',
'SquirrelCommand',
'add_squirrel_selection_arguments',
'squirrel_from_selection_arguments',
'add_squirrel_query_arguments',
'hint_codes_patterns_extra',
'squirrel_query_from_arguments',
'add_squirrel_storage_scheme_arguments',
'squirrel_effective_storage_scheme_from_arguments',
'add_mantra_arguments',
'get_mantras_from_arguments',
]