Commit d6567bd1 authored by Jason Madden's avatar Jason Madden

try the build using prospector.

parent bdd1a4ec
......@@ -21,8 +21,11 @@ ignore-paths:
# likewise with scripts
- scripts/
# This file has invalid syntax for Python 3, which is how
# landscape.io runs things
# landscape.io runs things...
- gevent/_util_py2.py
# ...and this file has invalid syntax for Python 2, which is how
# travis currently runs things. sigh.
- gevent/_socket3.py
# This is vendored with minimal changes
- gevent/_tblib.py
# likewise
......
......@@ -4,34 +4,46 @@
# can either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once).
# NOTE: comments must go between lines, not at the end; at the end of the line
# disables that directive and all following!
# NOTE: comments must go ABOVE the statement. In Python 2, mixing in
# comments disables all directives that follow, while in Python 3, putting
# comments at the end of the line does the same thing (though Py3 supports
# mixing)
# invalid-name, ; We get lots of these, especially in scripts. should fix many of them
# protected-access, ; We have many cases of this; legit ones need to be examinid and commented, then this removed
# no-self-use, ; common in superclasses with extension points
# too-few-public-methods, ; Exception and marker classes get tagged with this
# exec-used, ; should tag individual instances with this, there are some but not too many
# global-statement, ; should tag individual instances
# multiple-statements, ; "from gevent import monkey; monkey.patch_all()"
# locally-disabled, ; yes, we know we're doing this. don't replace one warning with another
# cyclic-import, ; most of these are deferred imports
# too-many-arguments, ; these are almost always because that's what the stdlib does
# redefined-builtin, ; likewise: these tend to be keyword arguments like len= in the stdlib
# undefined-all-variable, ; XXX: This crashes with pylint 1.5.4 on Travis (but not locally on Py2/3
# ; or landscape.io on Py3). The file causing the problem is unclear.
# useless-suppression: the only way to avoid repeating it for specific statements everywhere that we
# do Py2/Py3 stuff is to put it here. Sadly this means that we might get better but not realize it.
# see https://github.com/PyCQA/pylint/issues/846
disable=wrong-import-position,
wrong-import-order,
missing-docstring,
ungrouped-imports,
# We get lots of these, especially in scripts. should fix many of them
invalid-name,
# We have many cases of this; legit ones need to be examinid and commented, then this removed
protected-access,
# common in superclasses with extension points
no-self-use,
# Exception and marker classes get tagged with this
too-few-public-methods,
# should tag individual instances with this, there are some but not too many
exec-used,
# should tag individual instances
global-statement,
# "from gevent import monkey; monkey.patch_all()"
multiple-statements,
# yes, we know we're doing this. don't replace one warning with another
locally-disabled,
# most of these are deferred imports
cyclic-import,
# these are almost always because that's what the stdlib does
too-many-arguments,
# likewise: these tend to be keyword arguments like len= in the stdlib
redefined-builtin,
wrong-import-order,
missing-docstring,
ungrouped-imports,
invalid-name,
protected-access,
no-self-use,
too-few-public-methods,
exec-used,
global-statement,
multiple-statements,
locally-disabled,
cyclic-import,
too-many-arguments,
redefined-builtin,
useless-suppression,
# undefined-all-variable
[FORMAT]
# duplicated from setup.cfg
......
......@@ -46,13 +46,14 @@ doc:
whitespace:
! find . -not -path "*.pem" -not -path "./.eggs/*" -not -path "./greentest/htmlcov/*" -not -path "./greentest/.coverage.*" -not -path "./.tox/*" -not -path "*/__pycache__/*" -not -path "*.so" -not -path "*.pyc" -not -path "./.git/*" -not -path "./build/*" -not -path "./libev/*" -not -path "./gevent/libev/*" -not -path "./gevent.egg-info/*" -not -path "./dist/*" -not -path "./.DS_Store" -not -path "./c-ares/*" -not -path "./gevent/gevent.*.[ch]" -not -path "./gevent/corecext.pyx" -not -path "./doc/_build/*" -not -path "./doc/mytheme/static/*" -type f | xargs egrep -l " $$"
pep8:
${PYTHON} `which pep8` .
prospector:
which prospector
which pylint
# debugging
# pylint --rcfile=.pylintrc --init-hook="import sys, code; sys.excepthook = lambda exc, exc_type, tb: print(tb.tb_next.tb_next.tb_next.tb_next.tb_next.tb_next.tb_next.tb_next.tb_next.tb_next.tb_frame.f_locals['self'])" gevent greentest/* || true
${PYTHON} scripts/gprospector.py -X
pyflakes:
${PYTHON} util/pyflakes.py
lint: whitespace pyflakes pep8
lint: whitespace prospector
test_prelim:
which ${PYTHON}
......@@ -86,7 +87,7 @@ travis_test_linters:
coveralls --rcfile=greentest/.coveragerc
.PHONY: clean all doc pep8 whitespace pyflakes lint travistest travis
.PHONY: clean all doc prospector whitespace lint travistest travis
# Managing runtimes
......
......@@ -82,7 +82,7 @@ tests on one version of Python during development, try this::
Before submitting a pull request, it's a good idea to run the tests
across all supported versions of Python, and to check the code quality
using pep8 and pyflakes. This is what is done on Travis CI. Locally it
using prospector. This is what is done on Travis CI. Locally it
can be done using tox::
pip install tox
......
......@@ -2,8 +2,7 @@ setuptools
wheel
cython>=0.23.4
greenlet>=0.4.9
pep8
pyflakes
prospector[with_pyroma]
coverage>=4.0
coveralls>=1.0
cffi
......
......@@ -15,9 +15,9 @@ urls = ['http://www.google.com', 'http://www.yandex.ru', 'http://www.python.org'
if sys.version_info[0] == 3:
from urllib.request import urlopen
from urllib.request import urlopen # pylint:disable=import-error,no-name-in-module
else:
from urllib2 import urlopen
from urllib2 import urlopen # pylint: disable=import-error
def print_head(url):
......@@ -25,6 +25,6 @@ def print_head(url):
data = urlopen(url).read()
print('%s: %s bytes: %r' % (url, len(data), data[:50]))
jobs = [gevent.spawn(print_head, url) for url in urls]
jobs = [gevent.spawn(print_head, _url) for _url in urls]
gevent.wait(jobs)
......@@ -22,6 +22,7 @@ try:
from urlparse import urlparse
from urllib import unquote
except ImportError:
# pylint:disable=import-error,no-name-in-module
from urllib import request as urllib2
from urllib.parse import urlparse
from urllib.parse import unquote
......@@ -66,6 +67,7 @@ def application(env, start_response):
def proxy(path, start_response, proxy_url):
# pylint:disable=too-many-locals
if '://' not in path:
path = 'http://' + path
try:
......
......@@ -11,12 +11,12 @@ urls = ("/", "index",
'/long', 'long_polling')
class index:
class index(object):
def GET(self):
return '<html>Hello, world!<br><a href="/long">/long</a></html>'
class long_polling:
class long_polling(object):
# Since gevent's WSGIServer executes each incoming connection in a separate greenlet
# long running requests such as this one don't block one another;
# and thanks to "monkey.patch_all()" statement at the top, thread-local storage used by web.ctx
......
......@@ -28,7 +28,7 @@ class GreenFileDescriptorIO(RawIOBase):
_write_event = None
def __init__(self, fileno, mode='r', closefd=True):
RawIOBase.__init__(self)
RawIOBase.__init__(self) # Python 2: pylint:disable=no-member,non-parent-init-called
self._closed = False
self._closefd = closefd
self._fileno = fileno
......
......@@ -66,7 +66,7 @@ class SSLContext(orig_SSLContext):
check_hostname = False
class _contextawaresock(socket._gevent_sock_class):
class _contextawaresock(socket._gevent_sock_class): # Python 2: pylint:disable=slots-on-old-class
# We have to pass the raw stdlib socket to SSLContext.wrap_socket.
# That method in turn can pass that object on to things like SNI callbacks.
# It wouldn't have access to any of the attributes on the SSLSocket, like
......
......@@ -5,10 +5,11 @@ or not).
This module is missing 'Thread' class, but includes 'Queue'.
"""
from __future__ import absolute_import
try:
from Queue import Full, Empty
except ImportError:
from queue import Full, Empty
from queue import Full, Empty # pylint:disable=import-error
from collections import deque
import heapq
from time import time as _time, sleep as _sleep
......@@ -280,7 +281,7 @@ class Event(object):
self.__cond.release()
class Queue:
class Queue: # pylint:disable=old-style-class
"""Create a queue object with a given maximum size.
If maxsize is <= 0, the queue size is infinite.
......
......@@ -9,7 +9,7 @@ with other elements of the process.
.. seealso:: :class:`code.InteractiveConsole`
"""
from __future__ import print_function
from __future__ import print_function, absolute_import
import sys
from code import InteractiveConsole
......@@ -114,7 +114,7 @@ class BackdoorServer(StreamServer):
import __builtin__
_locals["__builtins__"] = __builtin__
except ImportError:
import builtins
import builtins # pylint:disable=import-error
_locals["builtins"] = builtins
_locals['__builtins__'] = builtins
return _locals
......
......@@ -18,7 +18,7 @@ try: # Py2
_allowed_module_name_types = (basestring,) # pylint:disable=undefined-variable
__target__ = '__builtin__'
except ImportError:
import builtins
import builtins # pylint: disable=import-error
_allowed_module_name_types = (str,)
__target__ = 'builtins'
......
......@@ -257,7 +257,7 @@ if sys.version_info[0] >= 3:
integer_types = int,
else:
import __builtin__ # pylint:disable=import-error
basestring = __builtin__.basestring
basestring = __builtin__.basestring,
integer_types = (int, __builtin__.long)
......
......@@ -93,7 +93,7 @@ class FileObjectThread(object):
if self.lock is True:
self.lock = Semaphore()
elif not self.lock:
self.lock = DummySemaphore()
self.lock = DummySemaphore() # pylint:disable=redefined-variable-type
if not hasattr(self.lock, '__enter__'):
raise TypeError('Expected a Semaphore or boolean, got %r' % type(self.lock))
if isinstance(fobj, integer_types):
......
......@@ -47,15 +47,15 @@ else:
string_types = __builtin__.basestring,
text_type = __builtin__.unicode
integer_types = (int, __builtin__.long)
xrange = __builtin__.xrange
xrange = __builtin__.xrange # python 2: pylint:disable=redefined-variable-type
from gevent._util_py2 import reraise # pylint:disable=import-error,unused-import,no-name-in-module
if sys.version_info[0] <= 2:
import thread # pylint:disable=import-error,useless-suppression
import thread # pylint:disable=import-error
else:
import _thread as thread
import _thread as thread # python 2 pylint:disable=import-error
# These must be the "real" native thread versions,
# not monkey-patched.
......
......@@ -81,7 +81,7 @@ if sys.version_info[0] >= 3:
PY3 = True
else:
import __builtin__ # pylint:disable=import-error
string_types = __builtin__.basestring
string_types = __builtin__.basestring,
PY3 = False
WIN = sys.platform.startswith("win")
......@@ -244,7 +244,7 @@ def _patch_existing_locks(threading):
class _ModuleLock(object):
pass
else:
_ModuleLock = importlib._bootstrap._ModuleLock
_ModuleLock = importlib._bootstrap._ModuleLock # python 2 pylint: disable=no-member
# It might be possible to walk up all the existing stack frames to find
# locked objects...at least if they use `with`. To be sure, we look at every object
# Since we're supposed to be done very early in the process, there shouldn't be
......
......@@ -76,9 +76,11 @@ class IMapUnordered(Greenlet):
# redundant, and that lets us avoid having to use self.link() instead
# of self.rawlink() to avoid having blocking methods called in the
# hub greenlet.
self._result_semaphore = Semaphore(maxsize)
factory = Semaphore
else:
self._result_semaphore = DummySemaphore()
factory = DummySemaphore
self._result_semaphore = factory(maxsize)
self.count = 0
self.finished = False
# If the queue size is unbounded, then we want to call all
......@@ -666,9 +668,10 @@ class Pool(Group):
if greenlet_class is not None:
self.greenlet_class = greenlet_class
if size is None:
self._semaphore = DummySemaphore()
factory = DummySemaphore
else:
self._semaphore = Semaphore(size)
factory = Semaphore
self._semaphore = factory(size)
def wait_available(self, timeout=None):
"""
......
......@@ -23,7 +23,7 @@ from datetime import datetime
try:
from urllib import unquote
except ImportError:
from urllib.parse import unquote
from urllib.parse import unquote # python 2 pylint:disable=import-error,no-name-in-module
from gevent import socket
import gevent
......@@ -336,11 +336,11 @@ try:
headers_factory = mimetools.Message
except ImportError:
# adapt Python 3 HTTP headers to old API
from http import client
from http import client # pylint:disable=import-error
class OldMessage(client.HTTPMessage):
def __init__(self, **kwargs):
super().__init__(**kwargs)
super(client.HTTPMessage, self).__init__(**kwargs) # pylint:disable=bad-super-call
self.status = ''
def getheader(self, name, default=None):
......@@ -1247,7 +1247,7 @@ class WSGIServer(StreamServer):
except socket.error:
name = str(address[0])
if PY3 and not isinstance(name, str):
name = name.decode('ascii')
name = name.decode('ascii') # python 2 pylint:disable=redefined-variable-type
self.environ['SERVER_NAME'] = name
self.environ.setdefault('SERVER_PORT', str(address[1]))
else:
......
......@@ -30,7 +30,7 @@ import collections
if sys.version_info[0] == 2:
import Queue as __queue__
else:
import queue as __queue__
import queue as __queue__ # python 2: pylint:disable=import-error
Full = __queue__.Full
Empty = __queue__.Empty
......
......@@ -122,7 +122,7 @@ if original_poll is not None:
try:
for fd in self.fds:
self.fds[fd].start(result.add_event, get_fileno(fd), pass_events=True)
if timeout is not None and -1 < timeout:
if timeout is not None and timeout > -1:
timeout /= 1000.0
result.event.wait(timeout=timeout)
return list(result.events)
......
......@@ -98,7 +98,7 @@ class StreamServer(BaseServer):
sock = self.socket
try:
fd, address = sock._accept()
except BlockingIOError:
except BlockingIOError: # python 2: pylint: disable=undefined-variable
if not sock.timeout:
return
raise
......
......@@ -18,7 +18,7 @@ from gevent.hub import PY3
if PY3:
from gevent import _socket3 as _source
from gevent import _socket3 as _source # python 2: pylint:disable=no-name-in-module
else:
from gevent import _socket2 as _source
......
......@@ -19,9 +19,9 @@ __implements__ = ['allocate_lock',
__imports__ = ['error']
if sys.version_info[0] <= 2:
import thread as __thread__ # pylint:disable=import-error,useless-suppression
import thread as __thread__ # pylint:disable=import-error
else:
import _thread as __thread__
import _thread as __thread__ # pylint:disable=import-error
__target__ = '_thread'
__imports__ += ['RLock',
'TIMEOUT_MAX',
......@@ -57,7 +57,7 @@ class LockType(BoundedSemaphore):
_OVER_RELEASE_ERROR = __thread__.error
if PY3:
_TIMEOUT_MAX = __thread__.TIMEOUT_MAX
_TIMEOUT_MAX = __thread__.TIMEOUT_MAX # python 2: pylint:disable=no-member
def acquire(self, blocking=True, timeout=-1):
# Transform the default -1 argument into the None that our
......
......@@ -50,6 +50,7 @@ class _ErrorFormatter(object):
self.formatMessage = FormatMessage
self.errorTab = errorTab
@classmethod
def fromEnvironment(cls):
"""
Get as many of the platform-specific error translation objects as
......@@ -68,7 +69,6 @@ class _ErrorFormatter(object):
except ImportError:
errorTab = None
return cls(WinError, FormatMessage, errorTab)
fromEnvironment = classmethod(fromEnvironment)
def formatError(self, errorcode):
"""
......
from __future__ import print_function
import re
import sys
from prospector.run import main
def _excepthook(e, t, tb):
while tb is not None:
frame = tb.tb_frame
print(frame.f_code, frame.f_code.co_name)
for n in ('self', 'node', 'elt'):
if n in frame.f_locals:
print(n, frame.f_locals[n])
print('---')
tb = tb.tb_next
sys.excepthook = _excepthook
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())
......@@ -27,8 +27,7 @@ basepython =
python2.7
deps =
{[testenv]deps}
pep8
pyflakes
prospector
commands =
make lint
......
#!/usr/bin/env python
from __future__ import print_function
import sys
import re
import subprocess
import glob
IGNORED = r"""
examples/webchat/urls.py:1: 'from django.conf.urls.defaults import *' used; unable to detect undefined names
gevent/_?ssl[23]?.py:\d+: undefined name
gevent/__init__.py:\d+: redefinition of unused 'signal' from line
gevent/__init__.py:\d+: redefinition of unused 'socket' from line
gevent/__init__.py:\d+:.*imported but unused
gevent/_socket[23].py:\d+: undefined name
gevent/_socketcommon.py:\d+: .*imported but unused
gevent/_socketcommon.py:\d+: undefined name
gevent/_sslgte279.py:.*
gevent/core.py:\d+: 'from gevent.corecext import *' used; unable to detect undefined names
gevent/core.py:\d+: 'from gevent.corecffi import *' used; unable to detect undefined names
gevent/coros.py:\d+: '__all__' imported but unused
gevent/coros.py:\d+: 'from gevent.lock import *' used; unable to detect undefined names
gevent/hub.py:\d+: 'reraise' imported but unused
gevent/os.py:\d+: redefinition of unused 'fork' from line
gevent/socket.py:\d+: undefined name
gevent/subprocess.py:\d+: undefined name
gevent/thread.py:\d+: '_local' imported but unused
gevent/threading.py:\d+: '\w+' imported but unused
gevent/wsgi.py:1: 'from gevent.pywsgi import *' used; unable to detect undefined names
greentest/test__queue.py:\d+: undefined name 'GenericGetTestCase'
greentest/test__server_pywsgi.py:
"""
# Travis runs this on Python 2, but this is only defined
# and used, in Python 3
IGNORED += r"""
gevent/server.py:\d+: undefined name 'BlockingIOError'
"""
IGNORED = IGNORED.strip().replace(' *', ' \\*').split('\n')
def is_ignored(line):
for pattern in IGNORED:
if re.match(pattern, line):
return True
def pyflakes(args):
popen = subprocess.Popen('%s `which pyflakes` %s' % (sys.executable, args),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
output, errors = popen.communicate()
if errors:
sys.stderr.write(errors.decode())
if popen.poll() != 1:
sys.stderr.write(output + '\n')
sys.exit('pyflakes returned %r' % popen.poll())
if errors:
sys.exit(1)
assert output
output = output.decode('utf-8')
output = output.strip().split('\n')
failed = False
for line in output:
line = line.strip()
if not is_ignored(line):
print('E %s' % line)
failed = True
#else:
# print('I %s' % line)
if failed:
sys.exit(1)
pyflakes('examples/ greentest/*.py util/ *.py')
if sys.version_info[0] == 3:
ignored_files = ['gevent/_util_py2.py', 'gevent/_socket2.py', 'gevent/_fileobject2.py',
'gevent/builtins.py']
else:
ignored_files = ['gevent/_socket3.py', 'gevent/_fileobject3.py']
ignored_files.append('gevent/wsgi.py')
py = set(glob.glob('gevent/*.py')) - set(ignored_files)
pyflakes(' '.join(py))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment