1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6import time
7import requests
9import logging
11from pyrocko import util
12from pyrocko.util import DownloadError
15logger = logging.getLogger('pyrocko.gf.ws')
17g_url = '%(site)s/gfws/%(service)s/%(majorversion)i/%(method)s'
18g_url_static = '%(site)s/gfws/%(service)s'
20g_site_abbr = {
21 'localhost': 'http://localhost:8080',
22 'kinherd': 'http://kinherd.org:8080'}
24g_default_site = 'localhost'
27def sdatetime(t):
28 return util.time_to_str(t, format='%Y-%m-%dT%H:%M:%S')
31class EmptyResult(Exception):
32 def __init__(self, url):
33 Exception.__init__(self)
34 self._url = url
36 def __str__(self):
37 return 'No results for request %s' % self._url
40class RequestEntityTooLarge(Exception):
41 def __init__(self, url):
42 Exception.__init__(self)
43 self._url = url
45 def __str__(self):
46 return 'Request entity too large: %s' % self._url
49class InvalidRequest(Exception):
50 pass
53def _request(url, post=False, **kwargs):
54 logger.debug('Accessing URL %s' % url)
56 if post:
57 logger.debug('POST data: \n%s' % post)
58 req = requests.Request(
59 'POST',
60 url=url,
61 params=kwargs,
62 data=post)
63 else:
64 req = requests.Request(
65 'GET',
66 url=url,
67 params=kwargs)
69 ses = requests.Session()
71 prep = ses.prepare_request(req)
72 prep.headers['Accept'] = '*/*'
74 resp = ses.send(prep, stream=True)
75 resp.raise_for_status()
77 if resp.status_code == 204:
78 raise EmptyResult(url)
79 return resp.raw
82def fillurl(url, site, service, majorversion, method='query'):
83 return url % dict(
84 site=g_site_abbr.get(site, site),
85 service=service,
86 majorversion=majorversion,
87 method=method)
90def static(url=g_url_static, site=g_default_site, majorversion=1, **kwargs):
92 url = fillurl(url, site, 'static', majorversion)
93 return _request(url, **kwargs)
96def ujoin(*args):
97 return '/'.join(args)
100def rget(url, path, force=False, method='download', stats=None,
101 status_callback=None, entries_wanted=None):
103 return util._download(
104 url, path,
105 force=force,
106 method=method,
107 status_callback=status_callback,
108 entries_wanted=entries_wanted,
109 recursive=True)
112def download_gf_store(url=g_url_static, site=g_default_site, majorversion=1,
113 store_id=None, force=False, quiet=False):
115 url = fillurl(url, site, 'static', majorversion)
117 stores_url = ujoin(url, 'stores')
119 tlast = [time.time()]
121 if not quiet:
122 def status_callback(d):
123 i = d['nread_bytes_all_files']
124 n = d['ntotal_bytes_all_files']
125 tnow = time.time()
126 if n != 0 and ((tnow - tlast[0]) > 5 or i == n):
127 print('%s / %s [%.1f%%]' % (
128 util.human_bytesize(i), util.human_bytesize(n), i*100.0/n))
130 tlast[0] = tnow
131 else:
132 def status_callback(d):
133 pass
135 wanted = ['config', 'extra/', 'index', 'phases/', 'traces/']
137 try:
138 if store_id is None:
139 print(static(
140 url=stores_url+'/', format='text').read().decode('utf-8'))
142 else:
143 store_url = ujoin(stores_url, store_id)
144 stotal = rget(
145 store_url, store_id, force=force, method='calcsize',
146 entries_wanted=wanted)
148 rget(
149 store_url, store_id, force=force, stats=[0, stotal],
150 status_callback=status_callback, entries_wanted=wanted)
152 except Exception as e:
153 raise DownloadError('download failed. Original error was: %s, %s' % (
154 type(e).__name__, e))
156 import shutil
157 shutil.rmtree(store_id)
160def seismosizer(url=g_url, site=g_default_site, majorversion=1,
161 request=None):
163 url = fillurl(url, site, 'seismosizer', majorversion)
165 from pyrocko.gf import meta
167 return meta.load(stream=_request(url, post={'request': request.dump()}))