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

1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5 

6''' 

7Web service to distribute precomputed GFs (:app:`fomosto server`). 

8''' 

9 

10import time 

11import requests 

12 

13import logging 

14 

15from pyrocko import util 

16from pyrocko.util import DownloadError 

17 

18 

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

20 

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

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

23 

24g_site_abbr = { 

25 'localhost': 'http://localhost:8080', 

26 'kinherd': 'https://gf.pyrocko.org', 

27 'pyrocko': 'https://gf.pyrocko.org', 

28} 

29 

30g_default_site = 'localhost' 

31 

32 

33def sdatetime(t): 

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

35 

36 

37class EmptyResult(Exception): 

38 def __init__(self, url): 

39 Exception.__init__(self) 

40 self._url = url 

41 

42 def __str__(self): 

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

44 

45 

46class RequestEntityTooLarge(Exception): 

47 def __init__(self, url): 

48 Exception.__init__(self) 

49 self._url = url 

50 

51 def __str__(self): 

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

53 

54 

55class InvalidRequest(Exception): 

56 pass 

57 

58 

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

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

61 

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) 

74 

75 ses = requests.Session() 

76 

77 prep = ses.prepare_request(req) 

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

79 

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

81 resp.raise_for_status() 

82 

83 if resp.status_code == 204: 

84 raise EmptyResult(url) 

85 return resp.raw 

86 

87 

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) 

94 

95 

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

97 

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

99 return _request(url, **kwargs) 

100 

101 

102def ujoin(*args): 

103 return '/'.join(args) 

104 

105 

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

107 status_callback=None, entries_wanted=None): 

108 

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) 

116 

117 

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

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

120 

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

122 

123 stores_url = ujoin(url, 'stores') 

124 

125 tlast = [time.time()] 

126 

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

135 

136 tlast[0] = tnow 

137 else: 

138 def status_callback(d): 

139 pass 

140 

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

142 

143 try: 

144 if store_id is None: 

145 print(static( 

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

147 

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) 

153 

154 rget( 

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

156 status_callback=status_callback, entries_wanted=wanted) 

157 

158 except Exception as e: 

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

160 type(e).__name__, e)) 

161 

162 import shutil 

163 shutil.rmtree(store_id) 

164 

165 

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

167 request=None): 

168 

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

170 

171 from pyrocko.gf import meta 

172 

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