Replace string slicing with proper string methods

Updated string prefix and suffix checker slicing to startswith()
and endswith() methods.

Using startswith() and endswith() improves readability, error-proneness
and enhances maintainability.

Change-Id: I1d5fbf116a61763346c6f92fd8023dbbe9bb37cf
This commit is contained in:
Ferenc Horváth 2015-10-07 11:10:28 +02:00
parent 1a28ccd01d
commit 635bc7fa8f
12 changed files with 44 additions and 39 deletions

View File

@ -293,14 +293,14 @@ def _parse_set_info_values(argvish):
devs = builder.search_devs(parse_search_value(search_value))
change = {}
ip = ''
if len(change_value) and change_value[0].isdigit():
if change_value and change_value[0].isdigit():
i = 1
while (i < len(change_value) and
change_value[i] in '0123456789.'):
i += 1
ip = change_value[:i]
change_value = change_value[i:]
elif len(change_value) and change_value[0] == '[':
elif change_value and change_value.startswith('['):
i = 1
while i < len(change_value) and change_value[i] != ']':
i += 1
@ -318,14 +318,14 @@ def _parse_set_info_values(argvish):
if change_value.startswith('R'):
change_value = change_value[1:]
replication_ip = ''
if len(change_value) and change_value[0].isdigit():
if change_value and change_value[0].isdigit():
i = 1
while (i < len(change_value) and
change_value[i] in '0123456789.'):
i += 1
replication_ip = change_value[:i]
change_value = change_value[i:]
elif len(change_value) and change_value[0] == '[':
elif change_value and change_value.startswith('['):
i = 1
while i < len(change_value) and change_value[i] != ']':
i += 1
@ -1147,7 +1147,7 @@ def main(arguments=None):
print(Commands.default.__doc__.strip())
print()
cmds = [c for c, f in Commands.__dict__.items()
if f.__doc__ and c[0] != '_' and c != 'default']
if f.__doc__ and not c.startswith('_') and c != 'default']
cmds.sort()
for cmd in cmds:
print(Commands.__dict__[cmd].__doc__.strip())

View File

@ -97,17 +97,17 @@ def clean_acl(name, value):
values.append(raw_value)
continue
first, second = (v.strip() for v in raw_value.split(':', 1))
if not first or first[0] != '.':
if not first or not first.startswith('.'):
values.append(raw_value)
elif first in ('.r', '.ref', '.referer', '.referrer'):
if 'write' in name:
raise ValueError('Referrers not allowed in write ACL: '
'%s' % repr(raw_value))
negate = False
if second and second[0] == '-':
if second and second.startswith('-'):
negate = True
second = second[1:].strip()
if second and second != '*' and second[0] == '*':
if second and second != '*' and second.startswith('*'):
second = second[1:].strip()
if not second or second == '.':
raise ValueError('No host/domain value after referrer '
@ -263,13 +263,13 @@ def referrer_allowed(referrer, referrer_acl):
if referrer_acl:
rhost = urlparse(referrer or '').hostname or 'unknown'
for mhost in referrer_acl:
if mhost[0] == '-':
if mhost.startswith('-'):
mhost = mhost[1:]
if mhost == rhost or (mhost[0] == '.' and
if mhost == rhost or (mhost.startswith('.') and
rhost.endswith(mhost)):
allow = False
elif mhost == '*' or mhost == rhost or \
(mhost[0] == '.' and rhost.endswith(mhost)):
(mhost.startswith('.') and rhost.endswith(mhost)):
allow = True
return allow

View File

@ -434,7 +434,7 @@ class DynamicLargeObject(object):
except ValueError:
pass
if not container or not prefix or '?' in value or '&' in value or \
prefix[0] == '/':
prefix.startswith('/'):
return HTTPBadRequest(
request=req,
body=('X-Object-Manifest must be in the '

View File

@ -68,7 +68,7 @@ class DomainRemapMiddleware(object):
def __init__(self, app, conf):
self.app = app
self.storage_domain = conf.get('storage_domain', 'example.com')
if self.storage_domain and self.storage_domain[0] != '.':
if self.storage_domain and not self.storage_domain.startswith('.'):
self.storage_domain = '.' + self.storage_domain
self.path_root = conf.get('path_root', 'v1').strip('/')
prefixes = conf.get('reseller_prefixes', 'AUTH')

View File

@ -272,7 +272,7 @@ class FormPost(object):
hdrs['Content-Type'] or 'application/octet-stream'
status, subheaders, message = \
self._perform_subrequest(env, attributes, fp, keys)
if status[:1] != '2':
if not status.startswith('2'):
break
else:
data = ''
@ -337,7 +337,7 @@ class FormPost(object):
del subenv['QUERY_STRING']
subenv['HTTP_TRANSFER_ENCODING'] = 'chunked'
subenv['wsgi.input'] = _CappedFileLikeObject(fp, max_file_size)
if subenv['PATH_INFO'][-1] != '/' and \
if not subenv['PATH_INFO'].endswith('/') and \
subenv['PATH_INFO'].count('/') < 4:
subenv['PATH_INFO'] += '/'
subenv['PATH_INFO'] += attributes['filename'] or 'filename'

View File

@ -350,7 +350,7 @@ class _StaticWebContext(WSGIContext):
if config_true_value(env.get('HTTP_X_WEB_MODE', 'f')):
return HTTPNotFound()(env, start_response)
return self.app(env, start_response)
if env['PATH_INFO'][-1] != '/':
if not env['PATH_INFO'].endswith('/'):
resp = HTTPMovedPermanently(
location=(env['PATH_INFO'] + '/'))
return resp(env, start_response)
@ -415,13 +415,13 @@ class _StaticWebContext(WSGIContext):
tmp_env['HTTP_USER_AGENT'] = \
'%s StaticWeb' % env.get('HTTP_USER_AGENT')
tmp_env['swift.source'] = 'SW'
if tmp_env['PATH_INFO'][-1] != '/':
if not tmp_env['PATH_INFO'].endswith('/'):
tmp_env['PATH_INFO'] += '/'
tmp_env['PATH_INFO'] += self._index
resp = self._app_call(tmp_env)
status_int = self._get_status_int()
if is_success(status_int) or is_redirection(status_int):
if env['PATH_INFO'][-1] != '/':
if not env['PATH_INFO'].endswith('/'):
resp = HTTPMovedPermanently(
location=env['PATH_INFO'] + '/')
return resp(env, start_response)
@ -429,7 +429,7 @@ class _StaticWebContext(WSGIContext):
self._response_exc_info)
return resp
if status_int == HTTP_NOT_FOUND:
if env['PATH_INFO'][-1] != '/':
if not env['PATH_INFO'].endswith('/'):
tmp_env = make_env(
env, 'GET', '/%s/%s/%s' % (
self.version, self.account, self.container),

View File

@ -177,9 +177,9 @@ class TempAuth(object):
'"/auth/" (Non-empty auth prefix path '
'is required)' % self.auth_prefix)
self.auth_prefix = '/auth/'
if self.auth_prefix[0] != '/':
if not self.auth_prefix.startswith('/'):
self.auth_prefix = '/' + self.auth_prefix
if self.auth_prefix[-1] != '/':
if not self.auth_prefix.endswith('/'):
self.auth_prefix += '/'
self.token_life = int(conf.get('token_life', 86400))
self.allow_overrides = config_true_value(

View File

@ -280,11 +280,12 @@ class TempURL(object):
['HTTP_' + h.upper().replace('-', '_') for h in headers.split()]
#: Headers to remove from incoming requests. Uppercase WSGI env style,
#: like `HTTP_X_PRIVATE`.
self.incoming_remove_headers = [h for h in headers if h[-1] != '*']
self.incoming_remove_headers = \
[h for h in headers if not h.endswith('*')]
#: Header with match prefixes to remove from incoming requests.
#: Uppercase WSGI env style, like `HTTP_X_SENSITIVE_*`.
self.incoming_remove_headers_startswith = \
[h[:-1] for h in headers if h[-1] == '*']
[h[:-1] for h in headers if h.endswith('*')]
headers = DEFAULT_INCOMING_ALLOW_HEADERS
if 'incoming_allow_headers' in conf:
@ -293,11 +294,12 @@ class TempURL(object):
['HTTP_' + h.upper().replace('-', '_') for h in headers.split()]
#: Headers to allow in incoming requests. Uppercase WSGI env style,
#: like `HTTP_X_MATCHES_REMOVE_PREFIX_BUT_OKAY`.
self.incoming_allow_headers = [h for h in headers if h[-1] != '*']
self.incoming_allow_headers = \
[h for h in headers if not h.endswith('*')]
#: Header with match prefixes to allow in incoming requests. Uppercase
#: WSGI env style, like `HTTP_X_MATCHES_REMOVE_PREFIX_BUT_OKAY_*`.
self.incoming_allow_headers_startswith = \
[h[:-1] for h in headers if h[-1] == '*']
[h[:-1] for h in headers if h.endswith('*')]
headers = DEFAULT_OUTGOING_REMOVE_HEADERS
if 'outgoing_remove_headers' in conf:
@ -305,11 +307,12 @@ class TempURL(object):
headers = [h.title() for h in headers.split()]
#: Headers to remove from outgoing responses. Lowercase, like
#: `x-account-meta-temp-url-key`.
self.outgoing_remove_headers = [h for h in headers if h[-1] != '*']
self.outgoing_remove_headers = \
[h for h in headers if not h.endswith('*')]
#: Header with match prefixes to remove from outgoing responses.
#: Lowercase, like `x-account-meta-private-*`.
self.outgoing_remove_headers_startswith = \
[h[:-1] for h in headers if h[-1] == '*']
[h[:-1] for h in headers if h.endswith('*')]
headers = DEFAULT_OUTGOING_ALLOW_HEADERS
if 'outgoing_allow_headers' in conf:
@ -317,11 +320,12 @@ class TempURL(object):
headers = [h.title() for h in headers.split()]
#: Headers to allow in outgoing responses. Lowercase, like
#: `x-matches-remove-prefix-but-okay`.
self.outgoing_allow_headers = [h for h in headers if h[-1] != '*']
self.outgoing_allow_headers = \
[h for h in headers if not h.endswith('*')]
#: Header with match prefixes to allow in outgoing responses.
#: Lowercase, like `x-matches-remove-prefix-but-okay-*`.
self.outgoing_allow_headers_startswith = \
[h[:-1] for h in headers if h[-1] == '*']
[h[:-1] for h in headers if h.endswith('*')]
#: HTTP user agent to use for subrequests.
self.agent = '%(orig)s TempURL'

View File

@ -223,7 +223,7 @@ def is_valid_hostname(hostname):
"""
if len(hostname) < 1 or len(hostname) > 255:
return False
if hostname[-1] == ".":
if hostname.endswith('.'):
# strip exactly one dot from the right, if present
hostname = hostname[:-1]
allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
@ -328,13 +328,13 @@ def parse_search_value(search_value):
search_value = search_value[i:]
if search_value.startswith('-'):
search_value = search_value[1:]
if len(search_value) and search_value[0].isdigit():
if search_value and search_value[0].isdigit():
i = 1
while i < len(search_value) and search_value[i] in '0123456789.':
i += 1
match['ip'] = search_value[:i]
search_value = search_value[i:]
elif len(search_value) and search_value[0] == '[':
elif search_value and search_value.startswith('['):
i = 1
while i < len(search_value) and search_value[i] != ']':
i += 1
@ -356,14 +356,14 @@ def parse_search_value(search_value):
# replication parameters
if search_value.startswith('R'):
search_value = search_value[1:]
if len(search_value) and search_value[0].isdigit():
if search_value and search_value[0].isdigit():
i = 1
while (i < len(search_value) and
search_value[i] in '0123456789.'):
i += 1
match['replication_ip'] = search_value[:i]
search_value = search_value[i:]
elif len(search_value) and search_value[0] == '[':
elif search_value and search_value.startswith('['):
i = 1
while i < len(search_value) and search_value[i] != ']':
i += 1

View File

@ -970,7 +970,7 @@ class Request(object):
the path segment.
"""
path_info = self.path_info
if not path_info or path_info[0] != '/':
if not path_info or not path_info.startswith('/'):
return None
try:
slash_loc = path_info.index('/', 1)

View File

@ -296,7 +296,7 @@ def config_auto_int_value(value, default):
def append_underscore(prefix):
if prefix and prefix[-1] != '_':
if prefix and not prefix.endswith('_'):
prefix += '_'
return prefix
@ -439,7 +439,8 @@ def get_log_line(req, res, trans_time, additional_info):
def get_trans_id_time(trans_id):
if len(trans_id) >= 34 and trans_id[:2] == 'tx' and trans_id[23] == '-':
if len(trans_id) >= 34 and \
trans_id.startswith('tx') and trans_id[23] == '-':
try:
return int(trans_id[24:34], 16)
except ValueError:
@ -1404,7 +1405,7 @@ class SwiftLogFormatter(logging.Formatter):
record.exc_text = self.formatException(
record.exc_info).replace('\n', '#012')
if record.exc_text:
if msg[-3:] != '#012':
if not msg.endswith('#012'):
msg = msg + '#012'
msg = msg + record.exc_text

View File

@ -1416,7 +1416,7 @@ class ECAppIter(object):
def put_fragments_in_queue(frag_iter, queue):
try:
for fragment in frag_iter:
if fragment[0] == ' ':
if fragment.startswith(' '):
raise Exception('Leading whitespace on fragment.')
queue.put(fragment)
except GreenletExit: