9595# "debug" means "none" + no tracker/template cache
9696MULTIPROCESS_TYPES = ["debug" , "none" ]
9797try :
98- import thread
98+ import thread # nosrc: F401
9999except ImportError :
100100 pass
101101else :
104104 MULTIPROCESS_TYPES .append ("fork" )
105105DEFAULT_MULTIPROCESS = MULTIPROCESS_TYPES [- 1 ]
106106
107+
107108def auto_ssl ():
108109 print (_ ('WARNING: generating temporary SSL certificate' ))
109110 import OpenSSL , random
@@ -112,7 +113,7 @@ def auto_ssl():
112113 cert = OpenSSL .crypto .X509 ()
113114 cert .set_serial_number (random .randint (0 , sys .maxsize ))
114115 cert .gmtime_adj_notBefore (0 )
115- cert .gmtime_adj_notAfter (60 * 60 * 24 * 365 ) # one year
116+ cert .gmtime_adj_notAfter (60 * 60 * 24 * 365 ) # one year
116117 cert .get_subject ().CN = '*'
117118 cert .get_subject ().O = 'Roundup Dummy Certificate'
118119 cert .get_issuer ().CN = 'Roundup Dummy Certificate Authority'
@@ -125,6 +126,7 @@ def auto_ssl():
125126
126127 return ctx
127128
129+
128130class SecureHTTPServer (http_ .server .HTTPServer ):
129131 def __init__ (self , server_address , HandlerClass , ssl_pem = None ):
130132 assert SSL , "pyopenssl not installed"
@@ -176,6 +178,7 @@ class ConnFixer(object):
176178 which the HTTP handlers require """
177179 def __init__ (self , conn ):
178180 self .__conn = conn
181+
179182 def makefile (self , mode , bufsize ):
180183 fo = socket ._fileobject (self .__conn , mode , bufsize )
181184 return RetryingFile (fo )
@@ -186,6 +189,7 @@ def __getattr__(self, attrib):
186189 conn = ConnFixer (conn )
187190 return (conn , info )
188191
192+
189193class RoundupRequestHandler (http_ .server .BaseHTTPRequestHandler ):
190194 TRACKER_HOMES = {}
191195 TRACKERS = None
@@ -225,7 +229,7 @@ def run_cgi(self):
225229 except client .NotFound :
226230 self .send_error (404 , self .path )
227231 except client .Unauthorised as message :
228- self .send_error (403 , '%s (%s)' % (self .path , message ))
232+ self .send_error (403 , '%s (%s)' % (self .path , message ))
229233 except :
230234 exc , val , tb = sys .exc_info ()
231235 if hasattr (socket , 'timeout' ) and isinstance (val , socket .timeout ):
@@ -252,12 +256,13 @@ def run_cgi(self):
252256 self .wfile .write (s2b (cgitb .breaker ()))
253257 ts = time .ctime ()
254258 self .wfile .write (s2b ('''<p>%s: An error occurred. Please check
255- the server log for more information.</p>''' % ts ))
259+ the server log for more information.</p>''' % ts ))
256260 # out to the logfile
257261 print ('EXCEPTION AT' , ts )
258262 traceback .print_exc ()
259263
260- do_GET = do_POST = do_HEAD = do_PUT = do_DELETE = do_PATCH = do_OPTIONS = run_cgi
264+ do_GET = do_POST = do_HEAD = do_PUT = do_DELETE = \
265+ do_PATCH = do_OPTIONS = run_cgi
261266
262267 def index (self ):
263268 ''' Print up an index of the available trackers
@@ -278,18 +283,18 @@ def index(self):
278283 template = open (self .CONFIG ['TEMPLATE' ]).read ()
279284 pt = PageTemplate ()
280285 pt .write (template )
281- extra = { 'trackers' : self .TRACKERS ,
282- 'nothing' : None ,
283- 'true' : 1 ,
284- 'false' : 0 ,
285- }
286+ extra = {'trackers' : self .TRACKERS ,
287+ 'nothing' : None ,
288+ 'true' : 1 ,
289+ 'false' : 0 ,
290+ }
286291 w (s2b (pt .pt_render (extra_context = extra )))
287292 else :
288293 w (s2b (_ ('<html><head><title>Roundup trackers index</title></head>\n '
289294 '<body><h1>Roundup trackers index</h1><ol>\n ' )))
290295 keys .sort ()
291296 for tracker in keys :
292- w (s2b ('<li><a href="%(tracker_url)s/index">%(tracker_name)s</a>\n ' % {
297+ w (s2b ('<li><a href="%(tracker_url)s/index">%(tracker_name)s</a>\n ' % {
293298 'tracker_url' : urllib_ .quote (tracker ),
294299 'tracker_name' : html_escape (tracker )}))
295300 w (b'</ol></body></html>' )
@@ -311,16 +316,16 @@ def inner_run_cgi(self):
311316 if os .access (favicon_filepath , os .R_OK ):
312317 favicon_fileobj = open (favicon_filepath , 'rb' )
313318
314-
315319 if favicon_fileobj is None :
316320 favicon_fileobj = io .BytesIO (favico )
317321
318322 self .send_response (200 )
319323 self .send_header ('Content-Type' , 'image/x-icon' )
320324 self .end_headers ()
321325
322- # this bufsize is completely arbitrary, I picked 4K because it sounded good.
323- # if someone knows of a better buffer size, feel free to plug it in.
326+ # this bufsize is completely arbitrary, I picked 4K because
327+ # it sounded good. if someone knows of a better buffer size,
328+ # feel free to plug it in.
324329 bufsize = 4 * 1024
325330 Processing = True
326331 while Processing :
@@ -356,9 +361,9 @@ def inner_run_cgi(self):
356361 self .send_response (301 )
357362 # redirect - XXX https??
358363 protocol = 'http'
359- url = '%s://%s%s/' % (protocol , self .headers ['host' ], rest )
364+ url = '%s://%s%s/' % (protocol , self .headers ['host' ], rest )
360365 if query :
361- url += '?' + query
366+ url += '?' + query
362367 self .send_header ('Location' , url )
363368 self .end_headers ()
364369 self .wfile .write (b'Moved Permanently' )
@@ -385,7 +390,7 @@ def inner_run_cgi(self):
385390 content_type = self .headers .type
386391 else :
387392 # Python 2.
388- content_type = self .headers .typeheader
393+ content_type = self .headers .typeheader
389394 if content_type :
390395 env ['CONTENT_TYPE' ] = content_type
391396 length = self .headers .get ('content-length' )
@@ -405,7 +410,7 @@ def inner_run_cgi(self):
405410 env ['SERVER_NAME' ] = self .server .server_name
406411 env ['SERVER_PORT' ] = str (self .server .server_port )
407412 try :
408- env ['HTTP_HOST' ] = self .headers ['host' ]
413+ env ['HTTP_HOST' ] = self .headers ['host' ]
409414 except KeyError :
410415 env ['HTTP_HOST' ] = ''
411416 # https://tools.ietf.org/html/draft-ietf-appsawg-http-forwarded-10
@@ -476,7 +481,7 @@ def log_message(self, format, *args):
476481 logger .info ("%s - - [%s] %s" %
477482 (self .client_address [0 ],
478483 self .log_date_time_string (),
479- format % args ))
484+ format % args ))
480485 else :
481486 try :
482487 http_ .server .BaseHTTPRequestHandler .log_message (self ,
@@ -491,10 +496,12 @@ def start_response(self, headers, response):
491496 self .send_header (key , value )
492497 self .end_headers ()
493498
499+
494500def error ():
495501 exc_type , exc_value = sys .exc_info ()[:2 ]
496502 return _ ('Error: %s: %s' % (exc_type , exc_value ))
497503
504+
498505def setgid (group ):
499506 if group is None :
500507 return
@@ -518,9 +525,10 @@ def setgid(group):
518525 else :
519526 grp .getgrgid (gid )
520527 except KeyError :
521- raise ValueError (_ ("Group %(group)s doesn't exist" )% locals ())
528+ raise ValueError (_ ("Group %(group)s doesn't exist" ) % locals ())
522529 os .setgid (gid )
523530
531+
524532def setuid (user ):
525533 if not hasattr (os , 'getuid' ):
526534 return
@@ -547,9 +555,10 @@ def setuid(user):
547555 else :
548556 pwd .getpwuid (uid )
549557 except KeyError :
550- raise ValueError (_ ("User %(user)s doesn't exist" )% locals ())
558+ raise ValueError (_ ("User %(user)s doesn't exist" ) % locals ())
551559 os .setuid (uid )
552560
561+
553562class TrackerHomeOption (configuration .FilePathOption ):
554563
555564 # Tracker homes do not need any description strings
@@ -559,6 +568,7 @@ def format(self):
559568 "value" : self .value2str (self ._value ),
560569 }
561570
571+
562572class ServerConfig (configuration .Config ):
563573
564574 SETTINGS = (
@@ -659,8 +669,7 @@ def _adjust_options(self, config):
659669 self .add_option (TrackerHomeOption (self , "trackers" , name ))
660670
661671 def getopt (self , args , short_options = "" , long_options = (),
662- config_load_options = ("C" , "config" ), ** options
663- ):
672+ config_load_options = ("C" , "config" ), ** options ):
664673 options .update (self .OPTIONS )
665674 return configuration .Config .getopt (self , args ,
666675 short_options , long_options , config_load_options , ** options )
@@ -693,7 +702,7 @@ def get_server(self):
693702 trackers = None
694703 else :
695704 trackers = dict ([(name , roundup .instance .open (home , optimize = 1 ))
696- for (name , home ) in tracker_homes ])
705+ for (name , home ) in tracker_homes ])
697706
698707 # build customized request handler class
699708 class RequestHandler (RoundupRequestHandler ):
@@ -730,18 +739,18 @@ def finish(self):
730739 # obtain request server class
731740 if self ["MULTIPROCESS" ] not in MULTIPROCESS_TYPES :
732741 print (_ ("Multiprocess mode \" %s\" is not available, "
733- "switching to single-process" ) % self ["MULTIPROCESS" ])
742+ "switching to single-process" ) % self ["MULTIPROCESS" ])
734743 self ["MULTIPROCESS" ] = "none"
735744 server_class = base_server
736745 elif self ["MULTIPROCESS" ] == "fork" :
737746 class ForkingServer (socketserver .ForkingMixIn ,
738- base_server ):
739- pass
747+ base_server ):
748+ pass
740749 server_class = ForkingServer
741750 elif self ["MULTIPROCESS" ] == "thread" :
742751 class ThreadingServer (socketserver .ThreadingMixIn ,
743- base_server ):
744- pass
752+ base_server ):
753+ pass
745754 server_class = ThreadingServer
746755 else :
747756 server_class = base_server
@@ -756,18 +765,19 @@ class ThreadingServer(socketserver.ThreadingMixIn,
756765 httpd = server_class (* args , ** kwargs )
757766 except socket .error as e :
758767 if e .args [0 ] == errno .EADDRINUSE :
759- raise socket .error (_ ("Unable to bind to port %s, port already in use." ) \
760- % self ["PORT" ])
768+ raise socket .error (_ ("Unable to bind to port %s, "
769+ "port already in use." ) % self ["PORT" ])
761770 raise
762771 # change user and/or group
763772 setgid (self ["GROUP" ])
764773 setuid (self ["USER" ])
765774 # return the server
766775 return httpd
767776
777+
768778try :
769779 import win32serviceutil
770- except :
780+ except ImportError :
771781 RoundupService = None
772782else :
773783
@@ -792,7 +802,7 @@ def SvcDoRun(self):
792802 (optlist , args ) = config .getopt (sys .argv [1 :])
793803 if not config ["LOGFILE" ]:
794804 servicemanager .LogMsg (servicemanager .EVENTLOG_ERROR_TYPE ,
795- servicemanager .PYS_SERVICE_STOPPED ,
805+ servicemanager .PYS_SERVICE_STOPPED ,
796806 (self ._svc_display_name_ , "\r \n Missing logfile option" ))
797807 self .ReportServiceStatus (win32service .SERVICE_STOPPED )
798808 return
@@ -801,13 +811,15 @@ def SvcDoRun(self):
801811 self .running = 1
802812 self .ReportServiceStatus (win32service .SERVICE_RUNNING )
803813 servicemanager .LogMsg (servicemanager .EVENTLOG_INFORMATION_TYPE ,
804- servicemanager .PYS_SERVICE_STARTED , (self ._svc_display_name_ ,
805- " at %s:%s" % (config ["HOST" ], config ["PORT" ])))
814+ servicemanager .PYS_SERVICE_STARTED ,
815+ (self ._svc_display_name_ ,
816+ " at %s:%s" % (config ["HOST" ],
817+ config ["PORT" ])))
806818 while self .running :
807819 self .server .handle_request ()
808820 servicemanager .LogMsg (servicemanager .EVENTLOG_INFORMATION_TYPE ,
809- servicemanager .PYS_SERVICE_STOPPED ,
810- (self ._svc_display_name_ , "" ))
821+ servicemanager .PYS_SERVICE_STOPPED ,
822+ (self ._svc_display_name_ , "" ))
811823 self .ReportServiceStatus (win32service .SERVICE_STOPPED )
812824
813825 def SvcStop (self ):
@@ -821,6 +833,7 @@ def SvcStop(self):
821833 sock .close ()
822834 self .ReportServiceStatus (win32service .SERVICE_STOP_PENDING )
823835
836+
824837def usage (message = '' ):
825838 if RoundupService :
826839 os_part = \
@@ -911,6 +924,7 @@ def writepidfile(pidfile):
911924 pidfile .write (str (pid ))
912925 pidfile .close ()
913926
927+
914928def daemonize (pidfile ):
915929 ''' Turn this process into a daemon.
916930 - make sure the sys.std(in|out|err) are completely cut off
@@ -945,7 +959,10 @@ def daemonize(pidfile):
945959 os .dup2 (devnull , 1 )
946960 os .dup2 (devnull , 2 )
947961
962+
948963undefined = []
964+
965+
949966def run (port = undefined , success_message = None ):
950967 ''' Script entry point - handle args and figure out what to to.
951968 '''
@@ -954,7 +971,8 @@ def run(port=undefined, success_message=None):
954971 short_options = "hvSc"
955972 try :
956973 (optlist , args ) = config .getopt (sys .argv [1 :],
957- short_options , ("help" , "version" , "save-config" ,))
974+ short_options ,
975+ ("help" , "version" , "save-config" ,))
958976 except (getopt .GetoptError , configuration .ConfigurationError ) as e :
959977 usage (str (e ))
960978 return
@@ -995,7 +1013,7 @@ def run(port=undefined, success_message=None):
9951013 RoundupService ._exe_args_ = " " .join (svc_args )
9961014 # pass the control to serviceutil
9971015 win32serviceutil .HandleCommandLine (RoundupService ,
998- argv = sys .argv [:1 ] + args )
1016+ argv = sys .argv [:1 ] + args )
9991017 return
10001018
10011019 # add tracker names from command line.
@@ -1011,12 +1029,12 @@ def run(port=undefined, success_message=None):
10111029
10121030 # handle remaining options
10131031 if optlist :
1014- for (opt , arg ) in optlist :
1032+ for (opt , _arg ) in optlist :
10151033 if opt in ("-h" , "--help" ):
10161034 usage ()
10171035 elif opt in ("-v" , "--version" ):
10181036 print ('%s (python %s)' % (roundup_version ,
1019- sys .version .split ()[0 ]))
1037+ sys .version .split ()[0 ]))
10201038 elif opt in ("-S" , "--save-config" ):
10211039 config .save ()
10221040 print (_ ("Configuration saved to %s" ) % config .filepath )
@@ -1038,7 +1056,7 @@ def run(port=undefined, success_message=None):
10381056 if config ["PIDFILE" ]:
10391057 if not hasattr (os , 'fork' ):
10401058 print (_ ("Sorry, you can't run the server as a daemon"
1041- " on this Operating System" ))
1059+ " on this Operating System" ))
10421060 sys .exit (0 )
10431061 else :
10441062 if config ['NODAEMON' ]:
@@ -1065,6 +1083,7 @@ def run(port=undefined, success_message=None):
10651083 except KeyboardInterrupt :
10661084 print ('Keyboard Interrupt: exiting' )
10671085
1086+
10681087if __name__ == '__main__' :
10691088 run ()
10701089
0 commit comments