Repository: benoitc/gunicorn

Issue:
Consider some rewritings
```diff
diff --git a/docs/sitemap_gen.py b/docs/sitemap_gen.py
--- a/docs/sitemap_gen.py
+++ b/docs/sitemap_gen.py
@@ -474,9 +474,7 @@ class URL(object):
       return False
     narrow = encoder.NarrowText(loc, None)
     (scheme, netloc, path, query, frag) = urlparse.urlsplit(narrow)
-    if (not scheme) or (not netloc):
-      return False
-    return True
+    return scheme and netloc
   #end def IsAbsolute
   IsAbsolute = staticmethod(IsAbsolute)
 
@@ -560,26 +558,16 @@ class URL(object):
 
     # Test the lastmod
     if self.lastmod:
-      match = False
       self.lastmod = self.lastmod.upper()
-      for pattern in LASTMOD_PATTERNS:
-        match = pattern.match(self.lastmod)
-        if match:
-          break
-      if not match:
+      if not any(pattern.match(self.lastmod) for pattern in LASTMOD_PATTERNS):
         output.Warn('Lastmod "%s" does not appear to be in ISO8601 format on '
                     'URL: %s' % (self.lastmod, self.loc))
         self.lastmod = None
 
     # Test the changefreq
     if self.changefreq:
-      match = False
       self.changefreq = self.changefreq.lower()
-      for pattern in CHANGEFREQ_PATTERNS:
-        if self.changefreq == pattern:
-          match = True
-          break
-      if not match:
+      if all(self.changefreq != pattern for pattern in CHANGEFREQ_PATTERNS):
         output.Warn('Changefreq "%s" is not a valid change frequency on URL '
                     ': %s' % (self.changefreq, self.loc))
         self.changefreq = None
@@ -1507,7 +1496,7 @@ class InputSitemap(xml.sax.handler.ContentHandler):
 
     # Switch contexts
     if (self._current < 0) or (self._contexts[self._current].AcceptTag(tag)):
-      self._current = self._current + 1
+      self._current += 1
       assert self._current < len(self._contexts)
       self._contexts[self._current].Open()
     else:
@@ -1680,7 +1669,7 @@ class PerURLStatistics:
 
   def Log(self):
     """ Dump out stats to the output. """
-    if len(self._extensions):
+    if self._extensions:
       output.Log('Count of file extensions on URLs:', 1)
       set = self._extensions.keys()
       set.sort()
@@ -1775,7 +1764,7 @@ class Sitemap(xml.sax.handler.ContentHandler):
       input.ProduceURLs(self.ConsumeURL)
 
     # Do last flushes
-    if len(self._set):
+    if self._set:
       self.FlushSet()
     if not self._sitemaps:
       output.Warn('No URLs were recorded, writing an empty sitemap.')
diff --git a/gunicorn/_compat.py b/gunicorn/_compat.py
--- a/gunicorn/_compat.py
+++ b/gunicorn/_compat.py
@@ -236,10 +236,7 @@ if PY26:
                 v = SplitResult(scheme, netloc, url, query, fragment)
                 _parse_cache[key] = v
                 return v
-            for c in url[:i]:
-                if c not in scheme_chars:
-                    break
-            else:
+            if all(c in scheme_chars for c in url[:i]):
                 # make sure "url" is not actually a port number (in which case
                 # "scheme" is really part of the path)
                 rest = url[i+1:]
diff --git a/gunicorn/app/wsgiapp.py b/gunicorn/app/wsgiapp.py
--- a/gunicorn/app/wsgiapp.py
+++ b/gunicorn/app/wsgiapp.py
@@ -30,7 +30,7 @@ class WSGIApplication(Application):
             from .pasterapp import paste_config
             return paste_config(self.cfg, self.cfgurl, self.relpath)
 
-        if len(args) < 1:
+        if not args:
             parser.error("No application module specified.")
 
         self.cfg.set("default_proc_name", args[0])
diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py
--- a/gunicorn/arbiter.py
+++ b/gunicorn/arbiter.py
@@ -489,20 +489,19 @@ class Arbiter(object):
         """
         if not self.timeout:
             return
-        workers = list(self.WORKERS.items())
-        for (pid, worker) in workers:
+        for pid, worker in self.WORKERS.items():
             try:
                 if time.time() - worker.tmp.last_update() <= self.timeout:
                     continue
             except (OSError, ValueError):
                 continue
 
-            if not worker.aborted:
+            if worker.aborted:
+                self.kill_worker(pid, signal.SIGKILL)
+            else:
                 self.log.critical("WORKER TIMEOUT (pid:%s)", pid)
                 worker.aborted = True
                 self.kill_worker(pid, signal.SIGABRT)
-            else:
-                self.kill_worker(pid, signal.SIGKILL)
 
     def reap_workers(self):
         """\
diff --git a/tests/treq.py b/tests/treq.py
--- a/tests/treq.py
+++ b/tests/treq.py
@@ -125,7 +125,7 @@ class request(object):
     def szread(self, func, sizes):
         sz = sizes()
         data = func(sz)
-        if sz >= 0 and len(data) > sz:
+        if 0 <= sz < len(data):
             raise AssertionError("Read more than %d bytes: %s" % (sz, data))
         return data
 
diff --git a/gunicorn/glogging.py b/gunicorn/glogging.py
--- a/gunicorn/glogging.py
+++ b/gunicorn/glogging.py
@@ -425,10 +425,7 @@ class Logger(object):
 
     def _set_syslog_handler(self, log, cfg, fmt, name):
         # setup format
-        if not cfg.syslog_prefix:
-            prefix = cfg.proc_name.replace(":", ".")
-        else:
-            prefix = cfg.syslog_prefix
+        prefix = cfg.syslog_prefix or cfg.proc_name.replace(":", ".")
 
         prefix = "gunicorn.%s.%s" % (prefix, name)
 

```
Consider some rewritings
```diff
diff --git a/docs/sitemap_gen.py b/docs/sitemap_gen.py
--- a/docs/sitemap_gen.py
+++ b/docs/sitemap_gen.py
@@ -474,9 +474,7 @@ class URL(object):
       return False
     narrow = encoder.NarrowText(loc, None)
     (scheme, netloc, path, query, frag) = urlparse.urlsplit(narrow)
-    if (not scheme) or (not netloc):
-      return False
-    return True
+    return scheme and netloc
   #end def IsAbsolute
   IsAbsolute = staticmethod(IsAbsolute)
 
@@ -560,26 +558,16 @@ class URL(object):
 
     # Test the lastmod
     if self.lastmod:
-      match = False
       self.lastmod = self.lastmod.upper()
-      for pattern in LASTMOD_PATTERNS:
-        match = pattern.match(self.lastmod)
-        if match:
-          break
-      if not match:
+      if not any(pattern.match(self.lastmod) for pattern in LASTMOD_PATTERNS):
         output.Warn('Lastmod "%s" does not appear to be in ISO8601 format on '
                     'URL: %s' % (self.lastmod, self.loc))
         self.lastmod = None
 
     # Test the changefreq
     if self.changefreq:
-      match = False
       self.changefreq = self.changefreq.lower()
-      for pattern in CHANGEFREQ_PATTERNS:
-        if self.changefreq == pattern:
-          match = True
-          break
-      if not match:
+      if all(self.changefreq != pattern for pattern in CHANGEFREQ_PATTERNS):
         output.Warn('Changefreq "%s" is not a valid change frequency on URL '
                     ': %s' % (self.changefreq, self.loc))
         self.changefreq = None
@@ -1507,7 +1496,7 @@ class InputSitemap(xml.sax.handler.ContentHandler):
 
     # Switch contexts
     if (self._current < 0) or (self._contexts[self._current].AcceptTag(tag)):
-      self._current = self._current + 1
+      self._current += 1
       assert self._current < len(self._contexts)
       self._contexts[self._current].Open()
     else:
@@ -1680,7 +1669,7 @@ class PerURLStatistics:
 
   def Log(self):
     """ Dump out stats to the output. """
-    if len(self._extensions):
+    if self._extensions:
       output.Log('Count of file extensions on URLs:', 1)
       set = self._extensions.keys()
       set.sort()
@@ -1775,7 +1764,7 @@ class Sitemap(xml.sax.handler.ContentHandler):
       input.ProduceURLs(self.ConsumeURL)
 
     # Do last flushes
-    if len(self._set):
+    if self._set:
       self.FlushSet()
     if not self._sitemaps:
       output.Warn('No URLs were recorded, writing an empty sitemap.')
diff --git a/gunicorn/_compat.py b/gunicorn/_compat.py
--- a/gunicorn/_compat.py
+++ b/gunicorn/_compat.py
@@ -236,10 +236,7 @@ if PY26:
                 v = SplitResult(scheme, netloc, url, query, fragment)
                 _parse_cache[key] = v
                 return v
-            for c in url[:i]:
-                if c not in scheme_chars:
-                    break
-            else:
+            if all(c in scheme_chars for c in url[:i]):
                 # make sure "url" is not actually a port number (in which case
                 # "scheme" is really part of the path)
                 rest = url[i+1:]
diff --git a/gunicorn/app/wsgiapp.py b/gunicorn/app/wsgiapp.py
--- a/gunicorn/app/wsgiapp.py
+++ b/gunicorn/app/wsgiapp.py
@@ -30,7 +30,7 @@ class WSGIApplication(Application):
             from .pasterapp import paste_config
             return paste_config(self.cfg, self.cfgurl, self.relpath)
 
-        if len(args) < 1:
+        if not args:
             parser.error("No application module specified.")
 
         self.cfg.set("default_proc_name", args[0])
diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py
--- a/gunicorn/arbiter.py
+++ b/gunicorn/arbiter.py
@@ -489,20 +489,19 @@ class Arbiter(object):
         """
         if not self.timeout:
             return
-        workers = list(self.WORKERS.items())
-        for (pid, worker) in workers:
+        for pid, worker in self.WORKERS.items():
             try:
                 if time.time() - worker.tmp.last_update() <= self.timeout:
                     continue
             except (OSError, ValueError):
                 continue
 
-            if not worker.aborted:
+            if worker.aborted:
+                self.kill_worker(pid, signal.SIGKILL)
+            else:
                 self.log.critical("WORKER TIMEOUT (pid:%s)", pid)
                 worker.aborted = True
                 self.kill_worker(pid, signal.SIGABRT)
-            else:
-                self.kill_worker(pid, signal.SIGKILL)
 
     def reap_workers(self):
         """\
diff --git a/tests/treq.py b/tests/treq.py
--- a/tests/treq.py
+++ b/tests/treq.py
@@ -125,7 +125,7 @@ class request(object):
     def szread(self, func, sizes):
         sz = sizes()
         data = func(sz)
-        if sz >= 0 and len(data) > sz:
+        if 0 <= sz < len(data):
             raise AssertionError("Read more than %d bytes: %s" % (sz, data))
         return data
 
diff --git a/gunicorn/glogging.py b/gunicorn/glogging.py
--- a/gunicorn/glogging.py
+++ b/gunicorn/glogging.py
@@ -425,10 +425,7 @@ class Logger(object):
 
     def _set_syslog_handler(self, log, cfg, fmt, name):
         # setup format
-        if not cfg.syslog_prefix:
-            prefix = cfg.proc_name.replace(":", ".")
-        else:
-            prefix = cfg.syslog_prefix
+        prefix = cfg.syslog_prefix or cfg.proc_name.replace(":", ".")
 
         prefix = "gunicorn.%s.%s" % (prefix, name)
 

```


Discussion:
Most of the changes look good to me. I'd leave `gunicorn/_compat.py` out since it was copied from the Python standard library and we are going to drop Python 2 support soon.

The same thing can be said for the changes in `gunicorn/util.py`. `import_module` was copied from the Python standard library to support older Python versions.
And the best way to get these changes into master is to submit them as pull requests.
> The same thing can be said for the changes in gunicorn/_compat.py

I made a typo there. `gunicorn/_compat.py` should read `gunicorn/util.py`. I just updated my earlier comment. Let me know if it's still unclear.
Most of the changes look good to me. I'd leave `gunicorn/_compat.py` out since it was copied from the Python standard library and we are going to drop Python 2 support soon.

The same thing can be said for the changes in `gunicorn/util.py`. `import_module` was copied from the Python standard library to support older Python versions.
And the best way to get these changes into master is to submit them as pull requests.
> The same thing can be said for the changes in gunicorn/_compat.py

I made a typo there. `gunicorn/_compat.py` should read `gunicorn/util.py`. I just updated my earlier comment. Let me know if it's still unclear.

Resolving patch:
diff --git a/docs/sitemap_gen.py b/docs/sitemap_gen.py
--- a/docs/sitemap_gen.py
+++ b/docs/sitemap_gen.py
@@ -457,9 +457,7 @@ def IsAbsolute(loc):
       return False
     narrow = encoder.NarrowText(loc, None)
     (scheme, netloc, path, query, frag) = urlparse.urlsplit(narrow)
-    if (not scheme) or (not netloc):
-      return False
-    return True
+    return scheme and netloc
   #end def IsAbsolute
   IsAbsolute = staticmethod(IsAbsolute)
 
@@ -543,26 +541,16 @@ def Validate(self, base_url, allow_fragment):
 
     # Test the lastmod
     if self.lastmod:
-      match = False
       self.lastmod = self.lastmod.upper()
-      for pattern in LASTMOD_PATTERNS:
-        match = pattern.match(self.lastmod)
-        if match:
-          break
-      if not match:
+      if not any(pattern.match(self.lastmod) for pattern in LASTMOD_PATTERNS):
         output.Warn('Lastmod "%s" does not appear to be in ISO8601 format on '
                     'URL: %s' % (self.lastmod, self.loc))
         self.lastmod = None
 
     # Test the changefreq
     if self.changefreq:
-      match = False
       self.changefreq = self.changefreq.lower()
-      for pattern in CHANGEFREQ_PATTERNS:
-        if self.changefreq == pattern:
-          match = True
-          break
-      if not match:
+      if all(self.changefreq != pattern for pattern in CHANGEFREQ_PATTERNS):
         output.Warn('Changefreq "%s" is not a valid change frequency on URL '
                     ': %s' % (self.changefreq, self.loc))
         self.changefreq = None
@@ -1490,7 +1478,7 @@ def startElement(self, tag, attributes):
 
     # Switch contexts
     if (self._current < 0) or (self._contexts[self._current].AcceptTag(tag)):
-      self._current = self._current + 1
+      self._current += 1
       assert self._current < len(self._contexts)
       self._contexts[self._current].Open()
     else:
@@ -1663,7 +1651,7 @@ def Consume(self, url):
 
   def Log(self):
     """ Dump out stats to the output. """
-    if len(self._extensions):
+    if self._extensions:
       output.Log('Count of file extensions on URLs:', 1)
       set = self._extensions.keys()
       set.sort()
@@ -1758,7 +1746,7 @@ def Generate(self):
       input.ProduceURLs(self.ConsumeURL)
 
     # Do last flushes
-    if len(self._set):
+    if self._set:
       self.FlushSet()
     if not self._sitemaps:
       output.Warn('No URLs were recorded, writing an empty sitemap.')
diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py
--- a/gunicorn/arbiter.py
+++ b/gunicorn/arbiter.py
@@ -491,20 +491,19 @@ def murder_workers(self):
         """
         if not self.timeout:
             return
-        workers = list(self.WORKERS.items())
-        for (pid, worker) in workers:
+        for pid, worker in self.WORKERS.items():
             try:
                 if time.time() - worker.tmp.last_update() <= self.timeout:
                     continue
             except (OSError, ValueError):
                 continue
 
-            if not worker.aborted:
+            if worker.aborted:
+                self.kill_worker(pid, signal.SIGKILL)
+            else:
                 self.log.critical("WORKER TIMEOUT (pid:%s)", pid)
                 worker.aborted = True
                 self.kill_worker(pid, signal.SIGABRT)
-            else:
-                self.kill_worker(pid, signal.SIGKILL)
 
     def reap_workers(self):
         """\
diff --git a/gunicorn/glogging.py b/gunicorn/glogging.py
--- a/gunicorn/glogging.py
+++ b/gunicorn/glogging.py
@@ -415,10 +415,7 @@ def _set_handler(self, log, output, fmt, stream=None):
 
     def _set_syslog_handler(self, log, cfg, fmt, name):
         # setup format
-        if not cfg.syslog_prefix:
-            prefix = cfg.proc_name.replace(":", ".")
-        else:
-            prefix = cfg.syslog_prefix
+        prefix = cfg.syslog_prefix or cfg.proc_name.replace(":", ".")
 
         prefix = "gunicorn.%s.%s" % (prefix, name)
 


Test patch:
diff --git a/tests/treq.py b/tests/treq.py
--- a/tests/treq.py
+++ b/tests/treq.py
@@ -124,7 +124,7 @@ def size_random(self):
     def szread(self, func, sizes):
         sz = sizes()
         data = func(sz)
-        if sz >= 0 and len(data) > sz:
+        if 0 <= sz < len(data):
             raise AssertionError("Read more than %d bytes: %s" % (sz, data))
         return data