1
- from __future__ import unicode_literals
2
-
3
1
import base64
4
2
from contextlib import closing
3
+ from http .server import BaseHTTPRequestHandler
5
4
import os
6
5
import socket
6
+ from socketserver import ThreadingMixIn
7
7
import sys
8
8
import threading
9
+ from urllib .error import HTTPError
10
+ from urllib .parse import parse_qs , quote_plus , urlparse
11
+ from urllib .request import (
12
+ build_opener , HTTPHandler , HTTPRedirectHandler , Request ,
13
+ )
9
14
from wsgiref .simple_server import make_server , WSGIRequestHandler , WSGIServer
10
15
11
16
from .openmetrics import exposition as openmetrics
12
17
from .registry import REGISTRY
13
18
from .utils import floatToGoString
14
19
15
- try :
16
- from urllib import quote_plus
17
-
18
- from BaseHTTPServer import BaseHTTPRequestHandler
19
- from SocketServer import ThreadingMixIn
20
- from urllib2 import (
21
- build_opener , HTTPError , HTTPHandler , HTTPRedirectHandler , Request ,
22
- )
23
- from urlparse import parse_qs , urlparse
24
- except ImportError :
25
- # Python 3
26
- from http .server import BaseHTTPRequestHandler
27
- from socketserver import ThreadingMixIn
28
- from urllib .error import HTTPError
29
- from urllib .parse import parse_qs , quote_plus , urlparse
30
- from urllib .request import (
31
- build_opener , HTTPHandler , HTTPRedirectHandler , Request ,
32
- )
33
-
34
- CONTENT_TYPE_LATEST = str ('text/plain; version=0.0.4; charset=utf-8' )
20
+ CONTENT_TYPE_LATEST = 'text/plain; version=0.0.4; charset=utf-8'
35
21
"""Content type of the latest text format"""
36
- PYTHON27_OR_OLDER = sys .version_info < (3 , )
37
22
PYTHON376_OR_NEWER = sys .version_info > (3 , 7 , 5 )
38
23
39
24
@@ -88,11 +73,7 @@ def redirect_request(self, req, fp, code, msg, headers, newurl):
88
73
unverifiable = True ,
89
74
data = req .data ,
90
75
)
91
- if PYTHON27_OR_OLDER :
92
- # the `method` attribute did not exist for Request in Python 2.7.
93
- new_request .get_method = lambda : m
94
- else :
95
- new_request .method = m
76
+ new_request .method = m
96
77
return new_request
97
78
98
79
@@ -102,7 +83,7 @@ def _bake_output(registry, accept_header, params):
102
83
if 'name[]' in params :
103
84
registry = registry .restricted_registry (params ['name[]' ])
104
85
output = encoder (registry )
105
- return str ( '200 OK' ) , (str ( 'Content-Type' ) , content_type ), output
86
+ return '200 OK' , ('Content-Type' , content_type ), output
106
87
107
88
108
89
def make_wsgi_app (registry = REGISTRY ):
@@ -114,8 +95,8 @@ def prometheus_app(environ, start_response):
114
95
params = parse_qs (environ .get ('QUERY_STRING' , '' ))
115
96
if environ ['PATH_INFO' ] == '/favicon.ico' :
116
97
# Serve empty response for browsers
117
- status = str ( '200 OK' )
118
- header = (str ( '' ), str ( '' ) )
98
+ status = '200 OK'
99
+ header = ('' , '' )
119
100
output = b''
120
101
else :
121
102
# Bake output
@@ -160,17 +141,16 @@ def generate_latest(registry=REGISTRY):
160
141
def sample_line (line ):
161
142
if line .labels :
162
143
labelstr = '{{{0}}}' .format (',' .join (
163
- ['{0 }="{1 }"' .format (
144
+ ['{}="{}"' .format (
164
145
k , v .replace ('\\ ' , r'\\' ).replace ('\n ' , r'\n' ).replace ('"' , r'\"' ))
165
146
for k , v in sorted (line .labels .items ())]))
166
147
else :
167
148
labelstr = ''
168
149
timestamp = ''
169
150
if line .timestamp is not None :
170
151
# Convert to milliseconds.
171
- timestamp = ' {0:d}' .format (int (float (line .timestamp ) * 1000 ))
172
- return '{0}{1} {2}{3}\n ' .format (
173
- line .name , labelstr , floatToGoString (line .value ), timestamp )
152
+ timestamp = f' { int (float (line .timestamp ) * 1000 ):d} '
153
+ return f'{ line .name } { labelstr } { floatToGoString (line .value )} { timestamp } \n '
174
154
175
155
output = []
176
156
for metric in registry .collect ():
@@ -192,9 +172,9 @@ def sample_line(line):
192
172
elif mtype == 'unknown' :
193
173
mtype = 'untyped'
194
174
195
- output .append ('# HELP {0 } {1 }\n ' .format (
175
+ output .append ('# HELP {} {}\n ' .format (
196
176
mname , metric .documentation .replace ('\\ ' , r'\\' ).replace ('\n ' , r'\n' )))
197
- output .append ('# TYPE {0 } {1 }\n ' . format ( mname , mtype ) )
177
+ output .append (f '# TYPE { mname } { mtype } \n ' )
198
178
199
179
om_samples = {}
200
180
for s in metric .samples :
@@ -210,9 +190,9 @@ def sample_line(line):
210
190
raise
211
191
212
192
for suffix , lines in sorted (om_samples .items ()):
213
- output .append ('# HELP {0}{1 } {2 }\n ' .format (metric .name , suffix ,
214
- metric .documentation .replace ('\\ ' , r'\\' ).replace ('\n ' , r'\n' )))
215
- output .append ('# TYPE {0}{1 } gauge\n ' . format ( metric . name , suffix ) )
193
+ output .append ('# HELP {}{ } {}\n ' .format (metric .name , suffix ,
194
+ metric .documentation .replace ('\\ ' , r'\\' ).replace ('\n ' , r'\n' )))
195
+ output .append (f '# TYPE { metric . name } { suffix } gauge\n ' )
216
196
output .extend (lines )
217
197
return '' .join (output ).encode ('utf-8' )
218
198
@@ -267,25 +247,13 @@ def write_to_textfile(path, registry):
267
247
268
248
This is intended for use with the Node exporter textfile collector.
269
249
The path must end in .prom for the textfile collector to process it."""
270
- tmppath = '%s.%s.%s' % ( path , os .getpid (), threading .current_thread ().ident )
250
+ tmppath = f' { path } . { os .getpid ()} . { threading .current_thread ().ident } '
271
251
with open (tmppath , 'wb' ) as f :
272
252
f .write (generate_latest (registry ))
273
253
274
254
# rename(2) is atomic but fails on Windows if the destination file exists
275
255
if os .name == 'nt' :
276
- if sys .version_info <= (3 , 3 ):
277
- # Unable to guarantee atomic rename on Windows and Python<3.3
278
- # Remove and rename instead (risks losing the file)
279
- try :
280
- os .remove (path )
281
- except FileNotFoundError :
282
- pass
283
-
284
- os .rename (tmppath , path )
285
- else :
286
- # os.replace is introduced in Python 3.3 but there is some dispute whether
287
- # it is a truly atomic file operation: https://bugs.python.org/issue8828
288
- os .replace (tmppath , path )
256
+ os .replace (tmppath , path )
289
257
else :
290
258
os .rename (tmppath , path )
291
259
@@ -299,8 +267,7 @@ def handle():
299
267
request .add_header (k , v )
300
268
resp = build_opener (base_handler ).open (request , timeout = timeout )
301
269
if resp .code >= 400 :
302
- raise IOError ("error talking to pushgateway: {0} {1}" .format (
303
- resp .code , resp .msg ))
270
+ raise OSError (f"error talking to pushgateway: { resp .code } { resp .msg } " )
304
271
305
272
return handle
306
273
@@ -337,7 +304,7 @@ def handle():
337
304
"""Handler that implements HTTP Basic Auth.
338
305
"""
339
306
if username is not None and password is not None :
340
- auth_value = '{0 }:{1 }' .format ( username , password ). encode ('utf-8' )
307
+ auth_value = f' { username } :{ password } ' .encode ()
341
308
auth_token = base64 .b64encode (auth_value )
342
309
auth_header = b'Basic ' + auth_token
343
310
headers .append (['Authorization' , auth_header ])
@@ -447,10 +414,10 @@ def _use_gateway(method, gateway, job, registry, grouping_key, timeout, handler)
447
414
PYTHON376_OR_NEWER
448
415
and gateway_url .scheme not in ['http' , 'https' ]
449
416
):
450
- gateway = 'http://{0}' . format ( gateway )
417
+ gateway = f 'http://{ gateway } '
451
418
452
419
gateway = gateway .rstrip ('/' )
453
- url = '{0 }/metrics/{1 }/{2 }' .format (gateway , * _escape_grouping_key ("job" , job ))
420
+ url = '{}/metrics/{}/{}' .format (gateway , * _escape_grouping_key ("job" , job ))
454
421
455
422
data = b''
456
423
if method != 'DELETE' :
@@ -459,7 +426,7 @@ def _use_gateway(method, gateway, job, registry, grouping_key, timeout, handler)
459
426
if grouping_key is None :
460
427
grouping_key = {}
461
428
url += '' .join (
462
- '/{0 }/{1 }' .format (* _escape_grouping_key (str (k ), str (v )))
429
+ '/{}/{}' .format (* _escape_grouping_key (str (k ), str (v )))
463
430
for k , v in sorted (grouping_key .items ()))
464
431
465
432
handler (
@@ -495,8 +462,4 @@ def instance_ip_grouping_key():
495
462
return {'instance' : s .getsockname ()[0 ]}
496
463
497
464
498
- try :
499
- # Python >3.5 only
500
- from .asgi import make_asgi_app # noqa
501
- except :
502
- pass
465
+ from .asgi import make_asgi_app # noqa
0 commit comments