1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5 

6import time 

7import requests 

8 

9import logging 

10 

11from pyrocko import util 

12from pyrocko.util import DownloadError 

13 

14 

15logger = logging.getLogger('pyrocko.gf.ws') 

16 

17g_url = '%(site)s/gfws/%(service)s/%(majorversion)i/%(method)s' 

18g_url_static = '%(site)s/gfws/%(service)s' 

19 

20g_site_abbr = { 

21 'localhost': 'http://localhost:8080', 

22 'kinherd': 'http://kinherd.org:8080'} 

23 

24g_default_site = 'localhost' 

25 

26 

27def sdatetime(t): 

28 return util.time_to_str(t, format='%Y-%m-%dT%H:%M:%S') 

29 

30 

31class EmptyResult(Exception): 

32 def __init__(self, url): 

33 Exception.__init__(self) 

34 self._url = url 

35 

36 def __str__(self): 

37 return 'No results for request %s' % self._url 

38 

39 

40class RequestEntityTooLarge(Exception): 

41 def __init__(self, url): 

42 Exception.__init__(self) 

43 self._url = url 

44 

45 def __str__(self): 

46 return 'Request entity too large: %s' % self._url 

47 

48 

49class InvalidRequest(Exception): 

50 pass 

51 

52 

53def _request(url, post=False, **kwargs): 

54 logger.debug('Accessing URL %s' % url) 

55 

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) 

68 

69 ses = requests.Session() 

70 

71 prep = ses.prepare_request(req) 

72 prep.headers['Accept'] = '*/*' 

73 

74 resp = ses.send(prep, stream=True) 

75 resp.raise_for_status() 

76 

77 if resp.status_code == 204: 

78 raise EmptyResult(url) 

79 return resp.raw 

80 

81 

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) 

88 

89 

90def static(url=g_url_static, site=g_default_site, majorversion=1, **kwargs): 

91 

92 url = fillurl(url, site, 'static', majorversion) 

93 return _request(url, **kwargs) 

94 

95 

96def ujoin(*args): 

97 return '/'.join(args) 

98 

99 

100def rget(url, path, force=False, method='download', stats=None, 

101 status_callback=None, entries_wanted=None): 

102 

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) 

110 

111 

112def download_gf_store(url=g_url_static, site=g_default_site, majorversion=1, 

113 store_id=None, force=False, quiet=False): 

114 

115 url = fillurl(url, site, 'static', majorversion) 

116 

117 stores_url = ujoin(url, 'stores') 

118 

119 tlast = [time.time()] 

120 

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

129 

130 tlast[0] = tnow 

131 else: 

132 def status_callback(d): 

133 pass 

134 

135 wanted = ['config', 'extra/', 'index', 'phases/', 'traces/'] 

136 

137 try: 

138 if store_id is None: 

139 print(static( 

140 url=stores_url+'/', format='text').read().decode('utf-8')) 

141 

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) 

147 

148 rget( 

149 store_url, store_id, force=force, stats=[0, stotal], 

150 status_callback=status_callback, entries_wanted=wanted) 

151 

152 except Exception as e: 

153 raise DownloadError('download failed. Original error was: %s, %s' % ( 

154 type(e).__name__, e)) 

155 

156 import shutil 

157 shutil.rmtree(store_id) 

158 

159 

160def seismosizer(url=g_url, site=g_default_site, majorversion=1, 

161 request=None): 

162 

163 url = fillurl(url, site, 'seismosizer', majorversion) 

164 

165 from pyrocko.gf import meta 

166 

167 return meta.load(stream=_request(url, post={'request': request.dump()}))