@@ -442,11 +442,11 @@ def __init__(self, instance, request, env, form=None, translator=None):
442442 # will never arrive.
443443 # If not defined, set CONTENT_LENGTH to 0 so it doesn't
444444 # hang reading the data.
445- if self .env ['REQUEST_METHOD' ] in ['OPTIONS' , 'DELETE' , 'PATCH' ]:
446- if 'CONTENT_LENGTH' not in self .env :
447- self .env ['CONTENT_LENGTH' ] = 0
448- logger .debug ("Setting CONTENT_LENGTH to 0 for method: %s" ,
449- self .env ['REQUEST_METHOD' ])
445+ if self .env ['REQUEST_METHOD' ] in ['OPTIONS' , 'DELETE' , 'PATCH' ] \
446+ and 'CONTENT_LENGTH' not in self .env :
447+ self .env ['CONTENT_LENGTH' ] = 0
448+ logger .debug ("Setting CONTENT_LENGTH to 0 for method: %s" ,
449+ self .env ['REQUEST_METHOD' ])
450450
451451 # cgi.FieldStorage must save all data as
452452 # binary/bytes. Subclass BinaryFieldStorage does this.
@@ -496,8 +496,7 @@ def __init__(self, instance, request, env, form=None, translator=None):
496496
497497 def _gen_nonce (self ):
498498 """ generate a unique nonce """
499- n = b2s (base64 .b32encode (random_ .token_bytes (40 )))
500- return n
499+ return b2s (base64 .b32encode (random_ .token_bytes (40 )))
501500
502501 def setTranslator (self , translator = None ):
503502 """Replace the translation engine
@@ -694,7 +693,8 @@ def handle_rest(self):
694693 if (self .is_cors_preflight ()):
695694 self .handle_preflight ()
696695 return
697- elif not self .db .security .hasPermission ('Rest Access' , self .userid ):
696+
697+ if not self .db .security .hasPermission ('Rest Access' , self .userid ):
698698 output = s2b ('{ "error": { "status": 403, "msg": "Forbidden." } }' )
699699 self .reject_request (output ,
700700 message_type = "application/json" ,
@@ -811,14 +811,11 @@ def inner_main(self):
811811 self .form_wins = True
812812 self ._error_message = msg .args
813813
814- if csrf_ok :
815- # csrf checks pass. Run actions etc.
816- # possibly handle a form submit action (may change
817- # self.classname and self.template, and may also
818- # append error/ok_messages)
819- html = self .handle_action ()
820- else :
821- html = None
814+ # If csrf checks pass. Run actions etc.
815+ # handle_action() may handle a form submit action.
816+ # It can change self.classname and self.template,
817+ # and may also append error/ok_messages.
818+ html = self .handle_action () if csrf_ok else None
822819
823820 if html :
824821 self .write_html (html )
@@ -883,7 +880,7 @@ def inner_main(self):
883880 self .response_code = http_ .client .UNAUTHORIZED
884881 realm = self .instance .config .TRACKER_NAME
885882 self .setHeader ("WWW-Authenticate" ,
886- " Basic realm=\ " %s\" " % realm )
883+ ' Basic realm="%s"' % realm )
887884 else :
888885 self .response_code = http_ .client .FORBIDDEN
889886 self .renderFrontPage (str (message ))
@@ -1041,10 +1038,7 @@ def determine_charset(self):
10411038
10421039 def _decode_charref (matchobj ):
10431040 num = matchobj .group (1 )
1044- if num [0 ].lower () == 'x' :
1045- uc = int (num [1 :], 16 )
1046- else :
1047- uc = int (num )
1041+ uc = int (num [1 :], 16 ) if num [0 ].lower () == 'x' else int (num )
10481042 return uchr (uc )
10491043
10501044 for field_name in self .form :
@@ -1235,7 +1229,7 @@ def determine_user(self, is_api=False):
12351229
12361230 # will be used later to override the get_roles method
12371231 # having it defined as truthy allows it to be used.
1238- override_get_roles = lambda self : iter_roles ( # noqa: E731
1232+ override_get_roles = lambda self : iter_roles ( # noqa: ARG005
12391233 ',' .join (token ['roles' ]))
12401234
12411235 # if user was not set by http authorization, try session lookup
@@ -1291,6 +1285,8 @@ def check_anonymous_access(self):
12911285 raise SeriousError (
12921286 self ._ ('broken form: multiple @action values submitted' ))
12931287 elif action != '' :
1288+ # '' is value when no action parameter was found so run
1289+ # this to extract action string value when action found.
12941290 action = action .value .lower ()
12951291 if action in ('login' , 'register' ):
12961292 return
@@ -1302,8 +1298,8 @@ def check_anonymous_access(self):
13021298 return
13031299
13041300 # otherwise for everything else
1305- if self .user == 'anonymous' :
1306- if not self .db .security .hasPermission ('Web Access' , self .userid ):
1301+ if self .user == 'anonymous' and \
1302+ not self .db .security .hasPermission ('Web Access' , self .userid ):
13071303 raise Unauthorised (self ._ ("Anonymous users are not "
13081304 "allowed to use the web interface" ))
13091305
@@ -1326,10 +1322,7 @@ def is_origin_header_ok(self, api=False, credentials=False):
13261322 try :
13271323 origin = self .env ['HTTP_ORIGIN' ]
13281324 except KeyError :
1329- if self .env ['REQUEST_METHOD' ] == 'GET' :
1330- return True
1331- else :
1332- return False
1325+ return self .env ['REQUEST_METHOD' ] == 'GET'
13331326
13341327 # note base https://host/... ends host with with a /,
13351328 # so add it to origin.
@@ -1478,7 +1471,7 @@ def handle_csrf(self, api=False):
14781471 "ORIGIN" ,
14791472 "REFERER" ,
14801473 "X-FORWARDED-HOST" ,
1481- "HOST"
1474+ "HOST" ,
14821475 ]
14831476
14841477 header_pass = 0 # count of passing header checks
@@ -1581,21 +1574,20 @@ def handle_csrf(self, api=False):
15811574 raise UsageError (self ._ ("Unable to verify sufficient headers" ))
15821575
15831576 enforce = config ['WEB_CSRF_ENFORCE_HEADER_X-REQUESTED-WITH' ]
1584- if api :
1585- if enforce in ['required' , 'yes' ]:
1586- # if we get here we have usually passed at least one
1587- # header check. We check for presence of this custom
1588- # header for xmlrpc/rest calls only.
1589- # E.G. X-Requested-With: XMLHttpRequest
1590- # Note we do not use CSRF nonces for xmlrpc/rest requests.
1591- #
1592- # see: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Protecting_REST_Services:_Use_of_Custom_Request_Headers
1593- if 'HTTP_X_REQUESTED_WITH' not in self .env :
1594- logger .error (self ._ (
1595- '' "csrf X-REQUESTED-WITH xmlrpc required header "
1596- '' "check failed for user%s." ),
1597- current_user )
1598- raise UsageError (self ._ ("Required Header Missing" ))
1577+ if api and enforce in ['required' , 'yes' ]:
1578+ # if we get here we have usually passed at least one
1579+ # header check. We check for presence of this custom
1580+ # header for xmlrpc/rest calls only.
1581+ # E.G. X-Requested-With: XMLHttpRequest
1582+ # Note we do not use CSRF nonces for xmlrpc/rest requests.
1583+ #
1584+ # see: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Protecting_REST_Services:_Use_of_Custom_Request_Headers
1585+ if 'HTTP_X_REQUESTED_WITH' not in self .env :
1586+ logger .error (self ._ (
1587+ '' "csrf X-REQUESTED-WITH xmlrpc required header "
1588+ '' "check failed for user%s." ),
1589+ current_user )
1590+ raise UsageError (self ._ ("Required Header Missing" ))
15991591
16001592 # Expire old csrf tokens now so we don't use them. These will
16011593 # be committed after the otks.destroy below. Note that the
@@ -1703,17 +1695,16 @@ def opendb(self, username):
17031695 if not hasattr (self , 'db' ):
17041696 self .db = self .instance .open (username )
17051697 self .db .tx_Source = "web"
1706- else :
1707- if self .instance .optimize :
1698+ elif self .instance .optimize :
17081699 self .db .setCurrentUser (username )
17091700 self .db .tx_Source = "web"
1710- else :
1711- self .db .close ()
1712- self .db = self .instance .open (username )
1713- self .db .tx_Source = "web"
1714- # The old session API refers to the closed database;
1715- # we can no longer use it.
1716- self .session_api = Session (self )
1701+ else :
1702+ self .db .close ()
1703+ self .db = self .instance .open (username )
1704+ self .db .tx_Source = "web"
1705+ # The old session API refers to the closed database;
1706+ # we can no longer use it.
1707+ self .session_api = Session (self )
17171708
17181709 # match designator in URL stripping leading 0's. So:
17191710 # https://issues.roundup-tracker.org/issue002551190 is the same as
@@ -1793,7 +1784,7 @@ def determine_context(self, dre=dre_url):
17931784 else :
17941785 self .template = ''
17951786 return
1796- elif path [0 ] in ('_file' , '@@file' ):
1787+ if path [0 ] in ('_file' , '@@file' ):
17971788 raise SendStaticFile (os .path .join (* path [1 :]))
17981789 else :
17991790 self .classname = path [0 ]
@@ -1973,10 +1964,7 @@ def serve_static_file(self, file):
19731964 file = str (file )
19741965 mime_type = mimetypes .guess_type (file )[0 ]
19751966 if not mime_type :
1976- if file .endswith ('.css' ):
1977- mime_type = 'text/css'
1978- else :
1979- mime_type = 'text/plain'
1967+ mime_type = 'text/css' if file .endswith ('.css' ) else 'text/plain'
19801968
19811969 # get filename: given a/b/c.js extract c.js
19821970 fn = file .rpartition ("/" )[2 ]
@@ -2079,12 +2067,9 @@ def selectTemplate(self, name, view):
20792067 if (view and view .find ('|' ) != - 1 ):
20802068 # we have alternate templates, parse them apart.
20812069 (oktmpl , errortmpl ) = view .split ("|" , 2 )
2082- if self ._error_message :
2083- # we have an error, use errortmpl
2084- view = errortmpl
2085- else :
2086- # no error message recorded, use oktmpl
2087- view = oktmpl
2070+
2071+ # Choose the right template
2072+ view = errortmpl if self ._error_message else oktmpl
20882073
20892074 loader = self .instance .templates
20902075
@@ -2135,7 +2120,7 @@ def renderContext(self):
21352120 # catch errors so we can handle PT rendering errors more nicely
21362121 args = {
21372122 'ok_message' : self ._ok_message ,
2138- 'error_message' : self ._error_message
2123+ 'error_message' : self ._error_message ,
21392124 }
21402125 pt = self .instance .templates .load (tplname )
21412126 # let the template render figure stuff out
@@ -2189,8 +2174,7 @@ def renderContext(self):
21892174 # than the one we tried to generate above.
21902175 if sys .version_info [0 ] > 2 :
21912176 raise exc_info [0 ](exc_info [1 ]).with_traceback (exc_info [2 ])
2192- else :
2193- exec ('raise exc_info[0], exc_info[1], exc_info[2]' ) # nosec
2177+ exec ('raise exc_info[0], exc_info[1], exc_info[2]' ) # nosec
21942178
21952179 def renderError (self , error , response_code = 400 , use_template = True ):
21962180 self .response_code = response_code
@@ -2222,7 +2206,7 @@ def renderError(self, error, response_code=400, use_template=True):
22222206
22232207 args = {
22242208 'ok_message' : self ._ok_message ,
2225- 'error_message' : self ._error_message
2209+ 'error_message' : self ._error_message ,
22262210 }
22272211
22282212 try :
@@ -2573,7 +2557,7 @@ def handle_range_header(self, length, etag):
25732557 # If the condition doesn't match the entity tag, then we
25742558 # must send the client the entire file.
25752559 if if_range != etag :
2576- return
2560+ return None
25772561 # The grammar for the Range header value is:
25782562 #
25792563 # ranges-specifier = byte-ranges-specifier
@@ -2761,13 +2745,10 @@ def write_file(self, filename):
27612745 self ._socket_op (self .request .sendfile , filename , offset , length )
27622746 return
27632747 # Fallback to the "write" operation.
2764- f = open (filename , 'rb' )
2765- try :
2748+ with open (filename , 'rb' ) as f :
27662749 if offset :
27672750 f .seek (offset )
27682751 content = f .read (length )
2769- finally :
2770- f .close ()
27712752 self .write (content )
27722753
27732754 def setHeader (self , header , value ):
0 commit comments