Coverage for /usr/local/lib/python3.13/dist-packages/pyrocko/gf/ws.py: 35%
69 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'''
7Web service to distribute precomputed GFs (:app:`fomosto server`).
8'''
10import time
11import requests
13import logging
15from pyrocko import util
16from pyrocko.util import DownloadError
19logger = logging.getLogger('pyrocko.gf.ws')
21g_url = '%(site)s/gfws/%(service)s/%(majorversion)i/%(method)s'
22g_url_static = '%(site)s/gfws/%(service)s'
24g_site_abbr = {
25 'localhost': 'http://localhost:8080',
26 'kinherd': 'https://gf.pyrocko.org',
27 'pyrocko': 'https://gf.pyrocko.org',
28}
30g_default_site = 'localhost'
33def sdatetime(t):
34 return util.time_to_str(t, format='%Y-%m-%dT%H:%M:%S')
37class EmptyResult(Exception):
38 def __init__(self, url):
39 Exception.__init__(self)
40 self._url = url
42 def __str__(self):
43 return 'No results for request %s' % self._url
46class RequestEntityTooLarge(Exception):
47 def __init__(self, url):
48 Exception.__init__(self)
49 self._url = url
51 def __str__(self):
52 return 'Request entity too large: %s' % self._url
55class InvalidRequest(Exception):
56 pass
59def _request(url, post=False, **kwargs):
60 logger.debug('Accessing URL %s' % url)
62 if post:
63 logger.debug('POST data: \n%s' % post)
64 req = requests.Request(
65 'POST',
66 url=url,
67 params=kwargs,
68 data=post)
69 else:
70 req = requests.Request(
71 'GET',
72 url=url,
73 params=kwargs)
75 ses = requests.Session()
77 prep = ses.prepare_request(req)
78 prep.headers['Accept'] = '*/*'
80 resp = ses.send(prep, stream=True)
81 resp.raise_for_status()
83 if resp.status_code == 204:
84 raise EmptyResult(url)
85 return resp.raw
88def fillurl(url, site, service, majorversion, method='query'):
89 return url % dict(
90 site=g_site_abbr.get(site, site),
91 service=service,
92 majorversion=majorversion,
93 method=method)
96def static(url=g_url_static, site=g_default_site, majorversion=1, **kwargs):
98 url = fillurl(url, site, 'static', majorversion)
99 return _request(url, **kwargs)
102def ujoin(*args):
103 return '/'.join(args)
106def rget(url, path, force=False, method='download', stats=None,
107 status_callback=None, entries_wanted=None):
109 return util._download(
110 url, path,
111 force=force,
112 method=method,
113 status_callback=status_callback,
114 entries_wanted=entries_wanted,
115 recursive=True)
118def download_gf_store(url=g_url_static, site=g_default_site, majorversion=1,
119 store_id=None, force=False, quiet=False):
121 url = fillurl(url, site, 'static', majorversion)
123 stores_url = ujoin(url, 'stores')
125 tlast = [time.time()]
127 if not quiet:
128 def status_callback(d):
129 i = d['nread_bytes_all_files']
130 n = d['ntotal_bytes_all_files']
131 tnow = time.time()
132 if n != 0 and ((tnow - tlast[0]) > 5 or i == n):
133 print('%s / %s [%.1f%%]' % (
134 util.human_bytesize(i), util.human_bytesize(n), i*100.0/n))
136 tlast[0] = tnow
137 else:
138 def status_callback(d):
139 pass
141 wanted = ['config', 'extra/', 'index', 'phases/', 'traces/']
143 try:
144 if store_id is None:
145 print(static(
146 url=stores_url+'/', format='text').read().decode('utf-8'))
148 else:
149 store_url = ujoin(stores_url, store_id)
150 stotal = rget(
151 store_url, store_id, force=force, method='calcsize',
152 entries_wanted=wanted)
154 rget(
155 store_url, store_id, force=force, stats=[0, stotal],
156 status_callback=status_callback, entries_wanted=wanted)
158 except Exception as e:
159 raise DownloadError('download failed. Original error was: %s, %s' % (
160 type(e).__name__, e))
162 import shutil
163 shutil.rmtree(store_id)
166def seismosizer(url=g_url, site=g_default_site, majorversion=1,
167 request=None):
169 url = fillurl(url, site, 'seismosizer', majorversion)
171 from pyrocko.gf import meta
173 return meta.load(stream=_request(url, post={'request': request.dump()}))