Coverage for /usr/local/lib/python3.13/dist-packages/pyrocko/squirrel/tool/commands/template.py: 48%
50 statements
« prev ^ index » next coverage.py v7.6.0, created at 2025-12-04 10:41 +0000
« prev ^ index » next coverage.py v7.6.0, created at 2025-12-04 10:41 +0000
1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6'''
7Implementation of :app:`squirrel template`.
8'''
10import re
11import logging
13from pyrocko.guts import load_string, dump
15from pyrocko.squirrel.error import ToolError
16from ..common import dq, ldq
18logger = logging.getLogger('psq.cli.template')
20headline = 'Print configuration snippets.'
22path_prefix = '''
23# All file paths given below are treated relative to the location of this
24# configuration file. Here we may give a common prefix. For example, if the
25# configuration file is in the sub-directory 'PROJECT/config/', set it to '..'
26# so that all paths are relative to 'PROJECT/'.
27path_prefix: '.'
28'''.strip()
31def _template_online_dataset(**kwargs):
32 lqargs = []
33 for k in ['network', 'station', 'channel']:
34 if k in kwargs:
35 v = kwargs.pop(k)
36 lqargs.append(" %s: '%s'" % (k, v))
38 kwargs['qargs'] = '\n' + '\n'.join(lqargs) if lqargs else '{}'
39 return '''
40--- !squirrel.Dataset
42{path_prefix}
44# Data sources to be added (LocalData, FDSNSource, CatalogSource, ...)
45sources:
46- !squirrel.FDSNSource
48 # URL or alias of FDSN site.
49 site: {site}
51 # Uncomment to let metadata expire in 10 days:
52 #expires: 10d
54 # anxious: 600s
56 # Waveforms can be optionally shared with other FDSN client configurations,
57 # so that data is not downloaded multiple times. The downside may be that in
58 # some cases more data than expected is available (if data was previously
59 # downloaded for a different application).
60 #shared_waveforms: true
62 # Read authentication token from file:
63 #auth_token_path: 'tokens/{site}.pgp'
65 # Plain text user credentials:
66 #user_credentials: ['username', 'password']
68 # Path to user Python module to locally patch metadata errors while
69 # importing:
70 #hotfix_module_path: 'hotfix/{site}.py'
72 # FDSN query arguments to make metadata queries.
73 # See http://www.fdsn.org/webservices/fdsnws-station-1.1.pdf
74 # Time span arguments should not be added here, because they are handled
75 # automatically by Squirrel.
76 query_args: {qargs}
77'''.format(path_prefix=path_prefix, **kwargs).strip()
80templates = {
81 'local.dataset': {
82 'description':
83 'A typical collection of local files.',
84 'yaml': '''
85--- !squirrel.Dataset
87{path_prefix}
89# Data sources to be added (LocalData, FDSNSource, CatalogSource, ...)
90sources:
91- !squirrel.LocalData # This data source is for local files.
93 # These paths are scanned for waveforms, stations, events.
94 paths:
95 - 'catalogs/events.txt'
96 - 'meta/stations.xml'
97 - 'data/waveforms'
99 # Select file format or 'detect' for autodetection.
100 format: 'detect'
101'''.format(path_prefix=path_prefix).strip()},
103 'geofon.dataset': {
104 'description':
105 'Everything available through GEOFON.',
106 'yaml': _template_online_dataset(
107 site='geofon',
108 ),
109 },
111 'iris-seis.dataset': {
112 'description':
113 'High- and low-gain seismometer channels from IRIS.',
114 'yaml': _template_online_dataset(
115 site='iris',
116 channel='?H?,?L?',
117 ),
118 },
120 'iris-seis-bb.dataset': {
121 'description':
122 'Broad-band high-gain seismometer channels from IRIS.',
123 'yaml': _template_online_dataset(
124 site='iris',
125 channel='VH?,LH?,BH?,HH?',
126 ),
127 },
129 'bgr-gr-lh.dataset': {
130 'description': 'LH channels for network GR from BGR.',
131 'yaml': _template_online_dataset(
132 site='bgr',
133 network='GR',
134 channel='LH?',
135 ),
136 },
138 'gcmt-m7.dataset': {
139 'description': 'Global-CMT events with Mw >= 7.0.',
140 'yaml': '''
141--- !squirrel.Dataset
143{path_prefix}
145# Data sources to be added (LocalData, FDSNSource, CatalogSource, ...)
146sources:
147- !squirrel.CatalogSource
148 catalog: gcmt
149 query_args:
150 magmin: '7.0'
151'''.format(path_prefix=path_prefix).strip()
152 },
153}
155names = sorted(templates.keys())
157template_listing = '\n'.join(
158 '%-30s %s' % (
159 '%s:' % name,
160 templates[name]['description']) for name in templates)
163def make_subparser(subparsers):
164 return subparsers.add_parser(
165 'template',
166 help=headline,
167 description=headline + '''
169Available SNIPPETs
171{}
172'''.format('\n'.join(' ' + line for line in template_listing.splitlines())))
175def setup(parser):
176 parser.add_argument(
177 'name',
178 choices=names,
179 nargs='?',
180 metavar='SNIPPET',
181 help='Name of template snippet to print.')
183 format_default = 'commented'
184 format_choices = ['commented', 'normal', 'brief']
186 parser.add_argument(
187 '--format', '-f',
188 choices=format_choices,
189 default=format_default,
190 metavar='FMT',
191 help='Set verbosity level of output YAML. Choices: %s. '
192 'Default: %s.' % (ldq(format_choices), dq(format_default)))
194 parser.add_argument(
195 '--write', '-w',
196 action='store_true',
197 help='Write to file.')
200def decomment(s):
201 out = []
202 for line in s.splitlines():
203 line = re.sub(r'#.+', '', line)
204 if line.strip():
205 out.append(line)
207 return '\n'.join(out)
210def brief(s):
211 return dump(load_string(s))
214def run(parser, args):
216 if not args.name:
217 print(template_listing)
219 else:
220 func = {
221 'brief': brief,
222 'commented': lambda s: s,
223 'normal': decomment}[args.format]
225 s = func(templates[args.name]['yaml'])
227 if args.write:
228 path = args.name + '.yaml'
229 try:
230 with open(path, 'x') as f:
231 f.write(s)
232 f.write('\n')
234 logger.info('File written: %s' % path)
236 except FileExistsError:
237 raise ToolError('File exists: %s' % path)
238 else:
239 print(s)