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

1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

4# ---|P------/S----------~Lg---------- 

5 

6''' 

7Implementation of :app:`squirrel template`. 

8''' 

9 

10import re 

11import logging 

12 

13from pyrocko.guts import load_string, dump 

14 

15from pyrocko.squirrel.error import ToolError 

16from ..common import dq, ldq 

17 

18logger = logging.getLogger('psq.cli.template') 

19 

20headline = 'Print configuration snippets.' 

21 

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() 

29 

30 

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)) 

37 

38 kwargs['qargs'] = '\n' + '\n'.join(lqargs) if lqargs else '{}' 

39 return ''' 

40--- !squirrel.Dataset 

41 

42{path_prefix} 

43 

44# Data sources to be added (LocalData, FDSNSource, CatalogSource, ...) 

45sources: 

46- !squirrel.FDSNSource 

47 

48 # URL or alias of FDSN site. 

49 site: {site} 

50 

51 # Uncomment to let metadata expire in 10 days: 

52 #expires: 10d 

53 

54 # anxious: 600s 

55 

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 

61 

62 # Read authentication token from file: 

63 #auth_token_path: 'tokens/{site}.pgp' 

64 

65 # Plain text user credentials: 

66 #user_credentials: ['username', 'password'] 

67 

68 # Path to user Python module to locally patch metadata errors while 

69 # importing: 

70 #hotfix_module_path: 'hotfix/{site}.py' 

71 

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() 

78 

79 

80templates = { 

81 'local.dataset': { 

82 'description': 

83 'A typical collection of local files.', 

84 'yaml': ''' 

85--- !squirrel.Dataset 

86 

87{path_prefix} 

88 

89# Data sources to be added (LocalData, FDSNSource, CatalogSource, ...) 

90sources: 

91- !squirrel.LocalData # This data source is for local files. 

92 

93 # These paths are scanned for waveforms, stations, events. 

94 paths: 

95 - 'catalogs/events.txt' 

96 - 'meta/stations.xml' 

97 - 'data/waveforms' 

98 

99 # Select file format or 'detect' for autodetection. 

100 format: 'detect' 

101'''.format(path_prefix=path_prefix).strip()}, 

102 

103 'geofon.dataset': { 

104 'description': 

105 'Everything available through GEOFON.', 

106 'yaml': _template_online_dataset( 

107 site='geofon', 

108 ), 

109 }, 

110 

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 }, 

119 

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 }, 

128 

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 }, 

137 

138 'gcmt-m7.dataset': { 

139 'description': 'Global-CMT events with Mw >= 7.0.', 

140 'yaml': ''' 

141--- !squirrel.Dataset 

142 

143{path_prefix} 

144 

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} 

154 

155names = sorted(templates.keys()) 

156 

157template_listing = '\n'.join( 

158 '%-30s %s' % ( 

159 '%s:' % name, 

160 templates[name]['description']) for name in templates) 

161 

162 

163def make_subparser(subparsers): 

164 return subparsers.add_parser( 

165 'template', 

166 help=headline, 

167 description=headline + ''' 

168 

169Available SNIPPETs 

170 

171{} 

172'''.format('\n'.join(' ' + line for line in template_listing.splitlines()))) 

173 

174 

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.') 

182 

183 format_default = 'commented' 

184 format_choices = ['commented', 'normal', 'brief'] 

185 

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))) 

193 

194 parser.add_argument( 

195 '--write', '-w', 

196 action='store_true', 

197 help='Write to file.') 

198 

199 

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) 

206 

207 return '\n'.join(out) 

208 

209 

210def brief(s): 

211 return dump(load_string(s)) 

212 

213 

214def run(parser, args): 

215 

216 if not args.name: 

217 print(template_listing) 

218 

219 else: 

220 func = { 

221 'brief': brief, 

222 'commented': lambda s: s, 

223 'normal': decomment}[args.format] 

224 

225 s = func(templates[args.name]['yaml']) 

226 

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') 

233 

234 logger.info('File written: %s' % path) 

235 

236 except FileExistsError: 

237 raise ToolError('File exists: %s' % path) 

238 else: 

239 print(s)