Commit 67542688 authored by Jason Madden's avatar Jason Madden

Merge pull request #769 from gevent/landscape

Switch to using prospector for lint checks
parents 5ef43ad7 d228edda
doc-warnings: no # experimental, raises an exception
test-warnings: no
strictness: veryhigh
max-line-length: 160
# We don't use any of the auto-detected things, and
# auto-detection slows down startup
autodetect: false
requirements:
- dev-requirements.txt
python-targets:
- 2
- 3
ignore-paths:
- examples/webchat/
- doc/
- build
- dist
- .eggs
# util creates lots of warnings. ideally they should be fixed,
# but that code doesn't change often
- util
# likewise with scripts
- scripts/
# This file has invalid syntax for Python 3, which is how
# 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
- greentest/six.py
# This triggers https://github.com/PyCQA/pylint/issues/846 on Travis,
# but the file is really small, so it's better to skip this one
# file than disable that whole check.
- gevent/core.py
# sadly, this one is complicated
- setup.py
- greentest/getaddrinfo_module.py
ignore-patterns:
# disabled code
- greentest/xtest_.*py
# standard library code
- ^greentest/2.*
- ^greentest/3.*
# benchmarks that aren't used/changed much
- ^greentest/bench_.*py
pyroma:
run: true
mccabe:
# We have way too many violations of the complexity measure.
# We should enable this and fix them one at a time, but that's
# more refactoring than I want to do initially.
run: false
pyflakes:
disable:
# F821: undefined name; caught better by pylint, where it can be
# controlled for the whole file/per-line
- F821
# F401: unused import; same story
- F401
# F811: redefined function; same story
- F811
# F403: wildcard import; same story
- F403
pep8:
disable:
# N805: first arg should be self; fails on metaclasses and
# classmethods; pylint does a better job
- N805
# N802: function names should be lower-case; comes from Windows
# funcs and unittest-style asserts and factory funcs
- N802
# N801: class names should use CapWords
- N801
# N803: argument name should be lower-case; comes up with using
# the class name as a keyword-argument
- N803
# N813: camelCase imported as lowercase; socketcommon
- N813
# N806: variable in function should be lowercase; but sometimes we
# want constant-looking names, especially for closures
- N806
# N812: lowercase imported as non-lowercase; from greenlet import
# greenlet as RawGreenlet
- N812
# E261: at least two spaces before inline comment. Really? Who does
# that?
- E261
# E265: Block comment should start with "# ". This arises from
# commenting out individual lines of code.
- E265
# N806: variable in function should be lowercase; but sometimes we
# want constant-looking names, especially for closures
- N806
# W503 line break before binary operator (I like and/or on the
# next line, it makes more sense)
- W503
# E266: too many leading '#' for block comment. (Multiple # can
# set off blocks)
- E266
# E402 module level import not at top of file. (happens in
# setup.py, some test cases)
- E402
# E702: multiple expressions on one line semicolon
# (happens for monkey-patch))
- E702
# E731: do not assign a lambda expression, use a def
# simpler than a def sometimes, and prevents redefinition warnings
- E731
# E302/303: Too many/too few blank lines (between classes, etc)
# This is *really* nitpicky.
- E302
- E303
[pep8]
ignore=E702,E265,E402,E731,E266,E261,W503,E129
max_line_length=160
exclude=.runtimes,.eggs,.tox,.git,build,2.6,2.7,2.7.8,2.7pypy,3.3,3.5,test_support.py,test_queue.py,patched_tests_setup.py,test_threading_2.py,lock_tests.py,_sslgte279.py,3.4
[MESSAGES CONTROL]
# Disable the message, report, category or checker with the given id(s). You
# 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 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. UPDATE: identified and disabled
# that file.
# see https://github.com/PyCQA/pylint/issues/846
# 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.
disable=wrong-import-position,
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
max-line-length=160
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
#notes=FIXME,XXX,TODO
# Disable that, we don't want them in the report (???)
notes=
[VARIABLES]
dummy-variables-rgx=_.*
[TYPECHECK]
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
# gevent: this is helpful for py3/py2 code.
generated-members=exc_clear
# List of classes names for which member attributes should not be checked
# (useful for classes with attributes dynamically set). This supports can work
# with qualified names.
# greenlet, Greenlet, parent, dead: all attempts to fix issues in greenlet.py
# only seen on the service, e.g., self.parent.loop: class parent has no loop
ignored-classes=SSLContext, SSLSocket, greenlet, Greenlet, parent, dead
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=gevent._corecffi
[DESIGN]
max-attributes=10
[BASIC]
bad-functions=input
# Prospector turns ot unsafe-load-any-extension by default, but
# pylint leaves it off. This is the proximal cause of the
# undefined-all-variable crash.
#unsafe-load-any-extension = no
......@@ -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
......
......@@ -11,6 +11,14 @@
- Update libev to version 4.22.
- Update tblib to 1.3.0.
- Update c-ares to version 1.11.0 (`release notes <https://raw.githubusercontent.com/c-ares/c-ares/cares-1_11_0/RELEASE-NOTES>`_).
- Remove module ``gevent.coros`` which was replaced by ``gevent.lock``
and has been deprecated since 1.0b2.
- The ``ref`` parameter to :func:`gevent.os.fork_and_watch` was being ignored.
- Python 3: :class:`gevent.queue.Channel` is now correctly iterable, instead of
raising a :exc:`TypeError`.
- Nested callbacks that set and clear an Event no longer cause
``wait`` to return prematurely. Reported in :issue:`771` by Sergey
Vasilyev.
1.1.0 (Mar 5, 2016)
===================
......
......@@ -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)
......@@ -2,6 +2,7 @@
[1] http://pypi.python.org/pypi/py-sendfile/
"""
# pylint:disable=import-error
from errno import EAGAIN
from sendfile import sendfile as original_sendfile
from gevent.socket import wait_write
......
......@@ -25,7 +25,7 @@ class PortForwarder(StreamServer):
StreamServer.__init__(self, listener, **kwargs)
self.dest = dest
def handle(self, source, address):
def handle(self, source, address): # pylint:disable=method-hidden
log('%s:%s accepted', *address[:2])
try:
dest = create_connection(self.dest)
......
from __future__ import print_function
# pylint:disable=import-error,broad-except,bare-except
import sys
import contextlib
......@@ -146,7 +147,7 @@ class PostgresConnectionPool(DatabaseConnectionPool):
return self.connect(*self.args, **self.kwargs)
if __name__ == '__main__':
def main():
import time
pool = PostgresConnectionPool("dbname=postgres", maxsize=3)
start = time.time()
......@@ -155,3 +156,6 @@ if __name__ == '__main__':
gevent.wait()
delay = time.time() - start
print('Running "select pg_sleep(1);" 4 times with 3 connections. Should take about 2 seconds: %.2fs' % delay)
if __name__ == '__main__':
main()
......@@ -11,7 +11,7 @@ from gevent.server import DatagramServer
class EchoServer(DatagramServer):
def handle(self, data, address):
def handle(self, data, address): # pylint:disable=method-hidden
print('%s: got %r' % (address[0], data))
self.socket.sendto(('Received %s bytes' % len(data)).encode('utf-8'), address)
......
......@@ -4,6 +4,7 @@ from gevent import socket
def application(environ, start_response):
assert environ
start_response('200 OK', [])
return []
......
......@@ -16,11 +16,13 @@ import sys
import re
import traceback
from cgi import escape
try:
import urllib2
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
......@@ -65,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:
......@@ -74,13 +77,14 @@ def proxy(path, start_response, proxy_url):
response = ex
print('%s: %s %s' % (path, response.code, response.msg))
headers = [(k, v) for (k, v) in response.headers.items() if k not in drop_headers]
scheme, netloc, path, params, query, fragment = urlparse(path)
scheme, netloc, path, _params, _query, _fragment = urlparse(path)
host = (scheme or 'http') + '://' + netloc
except Exception as ex:
except Exception as ex: # pylint:disable=broad-except
sys.stderr.write('error while reading %s:\n' % path)
traceback.print_exc()
tb = traceback.format_exc()
start_response('502 Bad Gateway', [('Content-Type', 'text/html')])
# pylint:disable=deprecated-method
error_str = escape(str(ex) or ex.__class__.__name__ or 'Error')
error_str = '<h1>%s</h1><h2>%s</h2><pre>%s</pre>' % (error_str, escape(path), escape(tb))
return [_as_bytes(error_str)]
......
......@@ -5,18 +5,18 @@ from __future__ import print_function
from gevent import monkey; monkey.patch_all()
from gevent.pywsgi import WSGIServer
import time
import web
import web # pylint:disable=import-error
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
......
......@@ -43,13 +43,16 @@ __all__ = ['get_hub',
import sys
if sys.platform == 'win32':
import socket # trigger WSAStartup call
# trigger WSAStartup call
import socket # pylint:disable=unused-import,useless-suppression
del socket
from gevent.hub import get_hub, iwait, wait, PYPY
from gevent.greenlet import Greenlet, joinall, killall
joinall = joinall # export for pylint
spawn = Greenlet.spawn
spawn_later = Greenlet.spawn_later
from gevent.timeout import Timeout, with_timeout
from gevent.hub import getcurrent, GreenletExit, spawn_raw, sleep, idle, kill, reinit
try:
......@@ -78,18 +81,18 @@ from gevent import signal as _signal_module
class _signal_metaclass(type):
def __getattr__(self, name):
def __getattr__(cls, name):
return getattr(_signal_module, name)
def __setattr__(self, name, value):
def __setattr__(cls, name, value):
# Because we can't know whether to try to go to the module
# or the class, we don't allow setting an attribute after the fact
raise TypeError("Cannot set attribute")
def __instancecheck__(self, instance):
def __instancecheck__(cls, instance):
return isinstance(instance, _signal_class)
def __dir__(self):
def __dir__(cls):
return dir(_signal_module)
......@@ -97,7 +100,7 @@ class signal(object):
__doc__ = _signal_module.__doc__
def __new__(self, *args, **kwargs):
def __new__(cls, *args, **kwargs):
return _signal_class(*args, **kwargs)
......@@ -116,11 +119,11 @@ del sys
# the following makes hidden imports visible to freezing tools like
# py2exe. see https://github.com/gevent/gevent/issues/181
def __dependencies_for_freezing():
from gevent import core, resolver_thread, resolver_ares, socket,\
from gevent import core, resolver_thread, resolver_ares, socket as _socket,\
threadpool, thread, threading, select, subprocess
import pprint
import traceback
import signal
import signal as _signal
del __dependencies_for_freezing
......@@ -131,5 +134,6 @@ if PYPY:
# DistutilsModuleError (on OS X) depending on who first imports and inits
# the hub. See https://github.com/gevent/gevent/issues/619 (There
# is no automated test for this.)
from gevent.core import loop
# XXX: As of 1.1, which prebuilds at install time, this is probably pointless
from gevent.core import loop # pylint:disable=no-name-in-module
del loop
......@@ -24,8 +24,11 @@ class GreenFileDescriptorIO(RawIOBase):
# the type's tp_dealloc slot; prior to Python 3, the object doesn't
# appear to have a __del__ method, even though it functionally does)
_read_event = None
_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
......@@ -33,15 +36,14 @@ class GreenFileDescriptorIO(RawIOBase):
self._readable = 'r' in mode
self._writable = 'w' in mode
self.hub = get_hub()
io = self.hub.loop.io
io_watcher = self.hub.loop.io
if self._readable:
self._read_event = io(fileno, 1)
else:
self._read_event = None
self._read_event = io_watcher(fileno, 1)
if self._writable:
self._write_event = io(fileno, 2)
else:
self._write_event = None
self._write_event = io_watcher(fileno, 2)
self._seekable = None
def readable(self):
......@@ -231,10 +233,12 @@ class FileObjectPosix(object):
bufsize = 1
if mode == 'r':
self.io = BufferedReader(self.fileio, bufsize)
IOFamily = BufferedReader
else:
assert mode == 'w'
self.io = BufferedWriter(self.fileio, bufsize)
IOFamily = BufferedWriter
self.io = IOFamily(self.fileio, bufsize)
#else: # QQQ: not used, not reachable
#
# self.io = BufferedRandom(self.fileio, bufsize)
......
......@@ -99,7 +99,7 @@ class Semaphore(object):
return
try:
link(self) # Must use Cython >= 0.23.4 on PyPy else this leaks memory
except:
except: # pylint:disable=bare-except
getcurrent().handle_error((link, self), *sys.exc_info())
if self._dirty:
# We mutated self._links so we need to start over
......
......@@ -2,6 +2,9 @@
"""
Python 2 socket module.
"""
# Our import magic sadly makes this warning useless
# pylint: disable=undefined-variable
import time
from gevent import _socketcommon
from gevent.hub import PYPY
......@@ -41,7 +44,7 @@ else:
# changing the behaviour of the stdlib if we're just imported; OTOH,
# under Python 2.6/2.7, test_urllib2net.py asserts that the class IS
# socket._fileobject (sigh), so we have to work around that.
class _fileobject(_fileobject):
class _fileobject(_fileobject): # pylint:disable=function-redefined
def __enter__(self):
return self
......@@ -71,7 +74,7 @@ else:
class _closedsocket(object):
__slots__ = []
def _dummy(*args, **kwargs):
def _dummy(*args, **kwargs): # pylint:disable=no-method-argument,unused-argument
raise error(EBADF, 'Bad file descriptor')
# All _delegate_methods must also be initialized here.
send = recv = recv_into = sendto = recvfrom = recvfrom_into = _dummy
......@@ -129,6 +132,7 @@ class socket(object):
return '<%s %s>' % (type(self).__name__, self._formatinfo())
def _formatinfo(self):
# pylint:disable=broad-except
try:
fileno = self.fileno()
except Exception as ex:
......@@ -243,7 +247,7 @@ class socket(object):
except timeout:
return EAGAIN
except error as ex:
if type(ex) is error:
if type(ex) is error: # pylint:disable=unidiomatic-typecheck
return ex.args[0]
else:
raise # gaierror is not silented by connect_ex
......@@ -396,7 +400,7 @@ class socket(object):
# example, bench_sendall.py yields ~264MB/s, while using 1MB yields
# ~653MB/s (matching CPython). 1MB is arbitrary and might be better
# chosen, say, to match a page size?
chunk_size = max(self.getsockopt(SOL_SOCKET, SO_SNDBUF), 1024 * 1024)
chunk_size = max(self.getsockopt(SOL_SOCKET, SO_SNDBUF), 1024 * 1024) # pylint:disable=no-member
data_sent = 0
end = None
......@@ -465,7 +469,7 @@ class socket(object):
# delegate the functions that we haven't implemented to the real socket object
_s = "def %s(self, *args): return self._sock.%s(*args)\n\n"
_m = None
for _m in set(_socketmethods) - set(locals()):
exec(_s % (_m, _m,))
del _m, _s
......@@ -510,6 +514,8 @@ if hasattr(__socket__, 'ssl'):
def ssl(sock, keyfile=None, certfile=None):
# deprecated in 2.7.9 but still present;
# sometimes backported by distros. See ssl.py
# Note that we import gevent.ssl, not _ssl2, to get the correct
# version.
from gevent import ssl as _sslmod
# wrap_socket is 2.7.9/backport, sslwrap_simple is older. They take
# the same arguments.
......
......@@ -2,6 +2,11 @@
"""
Python 3 socket module.
"""
# Our import magic sadly makes this warning useless
# pylint: disable=undefined-variable
# pylint: disable=too-many-statements,too-many-branches
# pylint: disable=too-many-public-methods,unused-argument
import io
import os
import sys
......@@ -22,7 +27,7 @@ __imports__ = _socketcommon.__imports__
__dns__ = _socketcommon.__dns__
SocketIO = __socket__.SocketIO
SocketIO = __socket__.SocketIO # pylint:disable=no-member
def _get_memory(data):
......@@ -88,7 +93,7 @@ class socket(object):
def type(self):
# See https://github.com/gevent/gevent/pull/399
if self.timeout != 0.0:
return self._sock.type & ~_socket.SOCK_NONBLOCK
return self._sock.type & ~_socket.SOCK_NONBLOCK # pylint:disable=no-member
else:
return self._sock.type
......@@ -103,7 +108,7 @@ class socket(object):
"""Wrap __repr__() to reveal the real class name."""
try:
s = _socket.socket.__repr__(self._sock)
except Exception as ex:
except Exception as ex: # pylint:disable=broad-except
# Observed on Windows Py3.3, printing the repr of a socket
# that just sufferred a ConnectionResetError [WinError 10054]:
# "OverflowError: no printf formatter to display the socket descriptor in decimal"
......@@ -217,7 +222,7 @@ class socket(object):
if reading and writing:
buffer = io.BufferedRWPair(raw, raw, buffering)
elif reading:
buffer = io.BufferedReader(raw, buffering)
buffer = io.BufferedReader(raw, buffering) # pylint:disable=redefined-variable-type
else:
assert writing
buffer = io.BufferedWriter(raw, buffering)
......@@ -292,7 +297,7 @@ class socket(object):
except timeout:
return EAGAIN
except error as ex:
if type(ex) is error:
if type(ex) is error: # pylint:disable=unidiomatic-typecheck
return ex.args[0]
else:
raise # gaierror is not silented by connect_ex
......@@ -423,7 +428,7 @@ class socket(object):
# because it's not cooperative.
def _sendfile_use_sendfile(self, file, offset=0, count=None):
# This is called directly by tests
raise __socket__._GiveupOnSendfile()
raise __socket__._GiveupOnSendfile() # pylint:disable=no-member
def _sendfile_use_send(self, file, offset=0, count=None):
self._check_sendfile_params(file, offset, count)
......@@ -500,6 +505,7 @@ class socket(object):
# get/set_inheritable new in 3.4
if hasattr(os, 'get_inheritable') or hasattr(os, 'get_handle_inheritable'):
# pylint:disable=no-member
if os.name == 'nt':
def get_inheritable(self):
return os.get_handle_inheritable(self.fileno())
......@@ -528,7 +534,7 @@ if sys.version_info[:2] == (3, 4) and sys.version_info[:3] <= (3, 4, 2):
# Therefore, on these old versions, we must preserve it as an enum; while this
# seems like it could lead to non-green behaviour, code on those versions
# cannot possibly be using SocketType as a class anyway.
SocketType = __socket__.SocketType
SocketType = __socket__.SocketType # pylint:disable=no-member
# Fixup __all__; note that we get exec'd multiple times during unit tests
if 'SocketType' in __implements__:
__implements__.remove('SocketType')
......@@ -588,9 +594,9 @@ elif 'socketpair' in __implements__:
# PyPy needs drop and reuse
def _do_reuse_or_drop(socket, methname):
def _do_reuse_or_drop(sock, methname):
try:
method = getattr(socket, methname)
method = getattr(sock, methname)
except (AttributeError, TypeError):
pass
else:
......@@ -657,7 +663,7 @@ class _basefileobject(object):
def __del__(self):
try:
self.close()
except:
except: # pylint:disable=bare-except
# close() may fail if __init__ didn't complete
pass
......@@ -692,7 +698,7 @@ class _basefileobject(object):
self._wbuf.append(data)
self._wbuf_len += len(data)
if (self._wbufsize == 0 or (self._wbufsize == 1 and b'\n' in data) or
(self._wbufsize > 1 and self._wbuf_len >= self._wbufsize)):
(self._wbufsize > 1 and self._wbuf_len >= self._wbufsize)):
self.flush()
def writelines(self, list):
......@@ -701,7 +707,7 @@ class _basefileobject(object):
lines = filter(None, map(str, list))
self._wbuf_len += sum(map(len, lines))
self._wbuf.extend(lines)
if (self._wbufsize <= 1 or self._wbuf_len >= self._wbufsize):
if self._wbufsize <= 1 or self._wbuf_len >= self._wbufsize:
self.flush()
def read(self, size=-1):
......@@ -772,6 +778,7 @@ class _basefileobject(object):
return buf.getvalue()
def readline(self, size=-1):
# pylint:disable=too-many-return-statements
buf = self._rbuf
buf.seek(0, 2) # seek end
if buf.tell() > 0:
......@@ -783,7 +790,7 @@ class _basefileobject(object):
self._rbuf.write(buf.read())
return bline
del bline
if size < 0:
if size < 0: # pylint:disable=too-many-nested-blocks
# Read until \n or EOF, whichever comes first
if self._rbufsize <= 1:
# Speed up unbuffered case
......@@ -928,7 +935,7 @@ else:
def __del__(self):
try:
self.close()
except:
except: # pylint:disable=bare-except
# close() may fail if __init__ didn't complete
pass
......
......@@ -2,60 +2,69 @@
from __future__ import absolute_import
# standard functions and classes that this module re-implements in a gevent-aware way:
_implements = ['create_connection',
'socket',
'SocketType',
'fromfd',
'socketpair']
__dns__ = ['getaddrinfo',
'gethostbyname',
'gethostbyname_ex',
'gethostbyaddr',
'getnameinfo',
'getfqdn']
_implements = [
'create_connection',
'socket',
'SocketType',
'fromfd',
'socketpair',
]
__dns__ = [
'getaddrinfo',
'gethostbyname',
'gethostbyname_ex',
'gethostbyaddr',
'getnameinfo',
'getfqdn',
]
_implements += __dns__
# non-standard functions that this module provides:
__extensions__ = ['cancel_wait',
'wait_read',
'wait_write',
'wait_readwrite']
__extensions__ = [
'cancel_wait',
'wait_read',
'wait_write',
'wait_readwrite',
]
# standard functions and classes that this module re-imports
__imports__ = ['error',
'gaierror',
'herror',
'htonl',
'htons',
'ntohl',
'ntohs',
'inet_aton',
'inet_ntoa',
'inet_pton',
'inet_ntop',
'timeout',
'gethostname',
'getprotobyname',
'getservbyname',
'getservbyport',
'getdefaulttimeout',
'setdefaulttimeout',
# Windows:
'errorTab',
]
__py3_imports__ = [# Python 3
'AddressFamily',
'SocketKind',
'CMSG_LEN',
'CMSG_SPACE',
'dup',
'if_indextoname',
'if_nameindex',
'if_nametoindex',
'sethostname']
__imports__ = [
'error',
'gaierror',
'herror',
'htonl',
'htons',
'ntohl',
'ntohs',
'inet_aton',
'inet_ntoa',
'inet_pton',
'inet_ntop',
'timeout',
'gethostname',
'getprotobyname',
'getservbyname',
'getservbyport',
'getdefaulttimeout',
'setdefaulttimeout',
# Windows:
'errorTab',
]
__py3_imports__ = [
# Python 3
'AddressFamily',
'SocketKind',
'CMSG_LEN',
'CMSG_SPACE',
'dup',
'if_indextoname',
'if_nameindex',
'if_nametoindex',
'sethostname',
]
__imports__.extend(__py3_imports__)
......@@ -66,7 +75,7 @@ from gevent.hub import ConcurrentObjectUseError
from gevent.timeout import Timeout
is_windows = sys.platform == 'win32'
# pylint:disable=no-name-in-module,unused-import
if is_windows:
# no such thing as WSAEPERM or error code 10001 according to winsock.h or MSDN
from errno import WSAEINVAL as EINVAL
......@@ -94,21 +103,21 @@ import _socket
_realsocket = _socket.socket
import socket as __socket__
for name in __imports__[:]:
_name = _value = None
for _name in __imports__[:]:
try:
value = getattr(__socket__, name)
globals()[name] = value
_value = getattr(__socket__, _name)
globals()[_name] = _value
except AttributeError:
__imports__.remove(name)
__imports__.remove(_name)
for name in __socket__.__all__:
value = getattr(__socket__, name)
if isinstance(value, integer_types) or isinstance(value, string_types):
globals()[name] = value
__imports__.append(name)
for _name in __socket__.__all__:
_value = getattr(__socket__, _name)
if isinstance(_value, integer_types) or isinstance(_value, string_types):
globals()[_name] = _value
__imports__.append(_name)
del name, value
del _name, _value
class _NONE(object):
......@@ -117,7 +126,7 @@ class _NONE(object):
return "<default value>"
_NONE = _NONE()
_timeout_error = timeout
_timeout_error = timeout # pylint: disable=undefined-variable
def wait(io, timeout=None, timeout_exc=_NONE):
......@@ -179,6 +188,7 @@ def wait_write(fileno, timeout=None, timeout_exc=_NONE, event=_NONE):
.. seealso:: :func:`cancel_wait`
"""
# pylint:disable=unused-argument
io = get_hub().loop.io(fileno, 2)
return wait(io, timeout, timeout_exc)
......@@ -196,11 +206,12 @@ def wait_readwrite(fileno, timeout=None, timeout_exc=_NONE, event=_NONE):
.. seealso:: :func:`cancel_wait`
"""
# pylint:disable=unused-argument
io = get_hub().loop.io(fileno, 3)
return wait(io, timeout, timeout_exc)
#: The exception raised by default on a call to :func:`cancel_wait`
cancel_wait_ex = error(EBADF, 'File descriptor was closed in another greenlet')
cancel_wait_ex = error(EBADF, 'File descriptor was closed in another greenlet') # pylint: disable=undefined-variable
def cancel_wait(watcher, error=cancel_wait_ex):
......@@ -300,11 +311,12 @@ def getfqdn(name=''):
possibly existing aliases. In case no FQDN is available, hostname
from gethostname() is returned.
"""
# pylint: disable=undefined-variable
name = name.strip()
if not name or name == '0.0.0.0':
name = gethostname()
try:
hostname, aliases, ipaddrs = gethostbyaddr(name)
hostname, aliases, _ = gethostbyaddr(name)
except error:
pass
else:
......
......@@ -8,12 +8,12 @@ This module implements cooperative SSL socket wrappers.
"""
from __future__ import absolute_import
# Our import magic sadly makes this warning useless
# pylint: disable=undefined-variable,arguments-differ,no-member
import ssl as __ssl__
try:
_ssl = __ssl__._ssl
except AttributeError:
_ssl = __ssl__._ssl2
_ssl = __ssl__._ssl
import sys
import errno
......@@ -440,8 +440,7 @@ def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv23, ca_certs=None):
If 'ca_certs' is specified, validate the server cert against it.
If 'ssl_version' is specified, use it in the connection attempt."""
host, port = addr
if (ca_certs is not None):
if ca_certs is not None:
cert_reqs = CERT_REQUIRED
else:
cert_reqs = CERT_NONE
......
......@@ -6,11 +6,13 @@ For the documentation, refer to :mod:`ssl` module manual.
This module implements cooperative SSL socket wrappers.
"""
# Our import magic sadly makes this warning useless
# pylint: disable=undefined-variable
from __future__ import absolute_import
import ssl as __ssl__
_ssl = __ssl__._ssl
_ssl = __ssl__._ssl # pylint:disable=no-member
import errno
from gevent.socket import socket, timeout_default
......@@ -28,24 +30,24 @@ __implements__ = [
__imports__ = []
name = value = None
for name in dir(__ssl__):
if name in __implements__:
_name = _value = None
for _name in dir(__ssl__):
if _name in __implements__:
continue
if name.startswith('__'):
if _name.startswith('__'):
continue
if name == 'socket':
if _name == 'socket':
# SSLSocket *must* subclass gevent.socket.socket; see issue 597
continue
value = getattr(__ssl__, name)
globals()[name] = value
__imports__.append(name)
_value = getattr(__ssl__, _name)
globals()[_name] = _value
__imports__.append(_name)
del name, value
del _name, _value
__all__ = __implements__ + __imports__
orig_SSLContext = __ssl__.SSLContext
orig_SSLContext = __ssl__.SSLContext # pylint:disable=no-member
class SSLContext(orig_SSLContext):
......@@ -64,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
......@@ -101,6 +103,8 @@ class SSLSocket(socket):
for Python 3.
"""
# pylint:disable=too-many-instance-attributes,too-many-public-methods
_gevent_sock_class = _contextawaresock
def __init__(self, sock=None, keyfile=None, certfile=None,
......@@ -111,7 +115,7 @@ class SSLSocket(socket):
suppress_ragged_eofs=True, npn_protocols=None, ciphers=None,
server_hostname=None,
_context=None):
# pylint:disable=too-many-locals,too-many-statements,too-many-branches
if _context:
self._context = _context
else:
......@@ -222,6 +226,7 @@ class SSLSocket(socket):
def read(self, len=1024, buffer=None):
"""Read up to LEN bytes and return them.
Return zero-length string on EOF."""
# pylint:disable=too-many-branches
self._checkClosed()
if not self._sslobj:
raise ValueError("Read on closed or unwrapped SSL socket.")
......@@ -293,7 +298,7 @@ class SSLSocket(socket):
# 3.5+
def selected_alpn_protocol(self):
self._checkClosed()
if not self._sslobj or not _ssl.HAS_ALPN:
if not self._sslobj or not _ssl.HAS_ALPN: # pylint:disable=no-member
return None
else:
return self._sslobj.selected_alpn_protocol()
......@@ -582,8 +587,8 @@ def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv23, ca_certs=None):
If 'ca_certs' is specified, validate the server cert against it.
If 'ssl_version' is specified, use it in the connection attempt."""
host, port = addr
if (ca_certs is not None):
_, _ = addr
if ca_certs is not None:
cert_reqs = CERT_REQUIRED
else:
cert_reqs = CERT_NONE
......
......@@ -8,9 +8,14 @@ This module implements cooperative SSL socket wrappers.
"""
from __future__ import absolute_import
# Our import magic sadly makes this warning useless
# pylint: disable=undefined-variable
# pylint: disable=too-many-instance-attributes,too-many-locals,too-many-statements,too-many-branches
# pylint: disable=arguments-differ,too-many-public-methods
import ssl as __ssl__
_ssl = __ssl__._ssl
_ssl = __ssl__._ssl # pylint:disable=no-member
import errno
from gevent._socket2 import socket
......@@ -19,33 +24,35 @@ from gevent.socket import error as socket_error
from gevent.socket import timeout as _socket_timeout
from gevent.hub import PYPY
__implements__ = ['SSLContext',
'SSLSocket',
'wrap_socket',
'get_server_certificate',
'create_default_context',
'_create_unverified_context',
'_create_default_https_context',
'_create_stdlib_context']
__implements__ = [
'SSLContext',
'SSLSocket',
'wrap_socket',
'get_server_certificate',
'create_default_context',
'_create_unverified_context',
'_create_default_https_context',
'_create_stdlib_context',
]
__imports__ = []
# Import all symbols from Python's ssl.py, except those that we are implementing
# and "private" symbols.
value = None
for name in dir(__ssl__):
if name in __implements__:
_name = _value = None
for _name in dir(__ssl__):
if _name in __implements__:
continue
if name.startswith('__'):
if _name.startswith('__'):
continue
if name == 'socket':
if _name == 'socket':
# SSLSocket *must* subclass gevent.socket.socket; see issue 597
continue
value = getattr(__ssl__, name)
globals()[name] = value
__imports__.append(name)
_value = getattr(__ssl__, _name)
globals()[_name] = _value
__imports__.append(_name)
del name, value
del _name, _value
try:
_delegate_methods
......@@ -54,7 +61,7 @@ except NameError: # PyPy doesn't expose this detail
__all__ = __implements__ + __imports__
orig_SSLContext = __ssl__.SSLContext
orig_SSLContext = __ssl__.SSLContext # pylint: disable=no-member
class SSLContext(orig_SSLContext):
......@@ -95,7 +102,7 @@ def create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None,
if purpose == Purpose.SERVER_AUTH:
# verify certs and host name in client mode
context.verify_mode = CERT_REQUIRED
context.check_hostname = True
context.check_hostname = True # pylint: disable=attribute-defined-outside-init
elif purpose == Purpose.CLIENT_AUTH:
# Prefer the server's ciphers by default so that we get stronger
# encryption
......@@ -118,9 +125,9 @@ def create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None,
return context
def _create_unverified_context(protocol=PROTOCOL_SSLv23, cert_reqs=None,
check_hostname=False, purpose=Purpose.SERVER_AUTH,
certfile=None, keyfile=None,
cafile=None, capath=None, cadata=None):
check_hostname=False, purpose=Purpose.SERVER_AUTH,
certfile=None, keyfile=None,
cafile=None, capath=None, cadata=None):
"""Create a SSLContext object for Python stdlib modules
All Python stdlib modules shall use this function to create SSLContext
......@@ -140,7 +147,7 @@ def _create_unverified_context(protocol=PROTOCOL_SSLv23, cert_reqs=None,
if cert_reqs is not None:
context.verify_mode = cert_reqs
context.check_hostname = check_hostname
context.check_hostname = check_hostname # pylint: disable=attribute-defined-outside-init
if keyfile and not certfile:
raise ValueError("certfile must be specified")
......@@ -180,7 +187,8 @@ class SSLSocket(socket):
suppress_ragged_eofs=True, npn_protocols=None, ciphers=None,
server_hostname=None,
_context=None):
# fileno is ignored
# pylint: disable=unused-argument
if _context:
self._context = _context
else:
......@@ -281,8 +289,8 @@ class SSLSocket(socket):
self._sslobj.context = ctx
def dup(self):
raise NotImplemented("Can't dup() %s instances" %
self.__class__.__name__)
raise NotImplementedError("Can't dup() %s instances" %
self.__class__.__name__)
def _checkClosed(self, msg=None):
# raise an exception here if you wish to check for spurious closes
......@@ -368,7 +376,7 @@ class SSLSocket(socket):
# 2.7.10+
def selected_alpn_protocol(self):
self._checkClosed()
if not self._sslobj or not _ssl.HAS_ALPN:
if not self._sslobj or not _ssl.HAS_ALPN: # pylint:disable=no-member
return None
else:
return self._sslobj.selected_alpn_protocol()
......@@ -465,8 +473,8 @@ class SSLSocket(socket):
if self._sslobj:
if flags != 0:
raise ValueError(
"non-zero flags not allowed in calls to recv_into() on %s" %
self.__class__)
"non-zero flags not allowed in calls to recv_into() on %s" %
self.__class__)
return self.read(nbytes, buffer)
else:
return socket.recv_into(self, buffer, nbytes, flags)
......@@ -555,7 +563,7 @@ class SSLSocket(socket):
def _real_close(self):
self._sslobj = None
socket._real_close(self)
socket._real_close(self) # pylint: disable=no-member
def do_handshake(self):
"""Perform a TLS/SSL handshake."""
......@@ -619,9 +627,9 @@ class SSLSocket(socket):
newsock, addr = socket.accept(self)
newsock = self.context.wrap_socket(newsock,
do_handshake_on_connect=self.do_handshake_on_connect,
suppress_ragged_eofs=self.suppress_ragged_eofs,
server_side=True)
do_handshake_on_connect=self.do_handshake_on_connect,
suppress_ragged_eofs=self.suppress_ragged_eofs,
server_side=True)
return newsock, addr
def makefile(self, mode='r', bufsize=-1):
......@@ -644,8 +652,8 @@ class SSLSocket(socket):
raise ValueError("Unsupported channel binding type")
if cb_type != "tls-unique":
raise NotImplementedError(
"{0} channel binding type not implemented"
.format(cb_type))
"{0} channel binding type not implemented"
.format(cb_type))
if self._sslobj is None:
return None
return self._sslobj.tls_unique_cb()
......@@ -696,7 +704,7 @@ def get_server_certificate(addr, ssl_version=PROTOCOL_SSLv23, ca_certs=None):
If 'ca_certs' is specified, validate the server cert against it.
If 'ssl_version' is specified, use it in the connection attempt."""
host, port = addr
_, _ = addr
if ca_certs is not None:
cert_reqs = CERT_REQUIRED
else:
......
......@@ -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
......@@ -90,6 +91,7 @@ class RLock(object):
class Condition(object):
# pylint:disable=method-hidden
def __init__(self, lock=None):
if lock is None:
......@@ -127,7 +129,7 @@ class Condition(object):
def _release_save(self):
self.__lock.release() # No state to save
def _acquire_restore(self, x):
def _acquire_restore(self, x): # pylint:disable=unused-argument
self.__lock.acquire() # Ignore saved state
def _is_owned(self):
......@@ -234,7 +236,7 @@ class BoundedSemaphore(Semaphore):
self._initial_value = value
def release(self):
if self.Semaphore__value >= self._initial_value:
if self.Semaphore__value >= self._initial_value: # pylint:disable=no-member
raise ValueError("Semaphore released too many times")
return Semaphore.release(self)
......@@ -279,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.
......@@ -462,6 +464,7 @@ class Queue:
# Initialize the queue representation
def _init(self, maxsize):
# pylint:disable=unused-argument
self.queue = deque()
def _qsize(self, len=len):
......@@ -489,9 +492,11 @@ class PriorityQueue(Queue):
return len(self.queue)
def _put(self, item, heappush=heapq.heappush):
# pylint:disable=arguments-differ
heappush(self.queue, item)
def _get(self, heappop=heapq.heappop):
# pylint:disable=arguments-differ
return heappop(self.queue)
......
......@@ -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
......@@ -32,11 +32,12 @@ except AttributeError:
class _Greenlet_stdreplace(Greenlet):
# A greenlet that replaces sys.std[in/out/err] while running.
_fileobj = None
saved = None
def switch(self, *args, **kw):
if self._fileobj is not None:
self.switch_in()
Greenlet.switch(self, *args, **kw)
Greenlet.switch(self, *args, **kw) # pylint:disable=no-member
def switch_in(self):
self.saved = sys.stdin, sys.stderr, sys.stdout
......@@ -113,12 +114,12 @@ 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
def handle(self, conn, address):
def handle(self, conn, _address): # pylint: disable=method-hidden
"""
Interact with one remote user.
......
......@@ -66,6 +66,8 @@ class BaseServer(object):
closing of the socket, fixing ResourceWarnings under Python 3 and PyPy.
"""
# pylint: disable=too-many-instance-attributes,bare-except,broad-except
#: the number of seconds to sleep in case there was an error in accept() call
#: for consecutive errors the delay will double until it reaches max_delay
#: when accept() finally succeeds the delay will be reset to min_delay again
......@@ -92,6 +94,10 @@ class BaseServer(object):
self._stop_event.set()
self._watcher = None
self._timer = None
self._handle = None
# XXX: FIXME: Subclasses rely on the presence or absence of the
# `socket` attribute to determine whether we are open/should be opened.
# Instead, have it be None.
self.pool = None
try:
self.set_listener(listener)
......@@ -213,6 +219,8 @@ class BaseServer(object):
break
def full(self):
# copied from self.pool
# pylint: disable=method-hidden
return False
def __repr__(self):
......
......@@ -15,10 +15,10 @@ from gevent.lock import RLock
try: # Py2
import __builtin__ as builtins
_allowed_module_name_types = (basestring,)
_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'
......
# pylint: disable=too-many-lines, protected-access, redefined-outer-name
# pylint: disable=too-many-lines, protected-access, redefined-outer-name, not-callable
from __future__ import absolute_import, print_function
import sys
import os
......@@ -6,13 +6,15 @@ import traceback
import signal as signalmodule
__all__ = ['get_version',
'get_header_version',
'supported_backends',
'recommended_backends',
'embeddable_backends',
'time',
'loop']
__all__ = [
'get_version',
'get_header_version',
'supported_backends',
'recommended_backends',
'embeddable_backends',
'time',
'loop',
]
try:
import gevent._corecffi
......@@ -21,10 +23,10 @@ except ImportError:
# Not built yet
import gevent._corecffi_build
gevent._corecffi_build.ffi.compile()
import gevent._corecffi
import gevent._corecffi # pylint: disable=no-member,no-name-in-module,useless-suppression
ffi = gevent._corecffi.ffi
libev = gevent._corecffi.lib
ffi = gevent._corecffi.ffi # pylint:disable=no-member
libev = gevent._corecffi.lib # pylint:disable=no-member
if hasattr(libev, 'vfd_open'):
# Must be on windows
......@@ -107,24 +109,24 @@ def _python_callback(handle, revents):
# to the 'onerror' handler, which
# is not what we want; that can permanently wedge the loop depending
# on which callback was executing
watcher = ffi.from_handle(handle)
args = watcher.args
the_watcher = ffi.from_handle(handle)
args = the_watcher.args
if args is None:
# Legacy behaviour from corecext: convert None into ()
# See test__core_watcher.py
args = _NOARGS
if len(args) > 0 and args[0] == GEVENT_CORE_EVENTS:
args = (revents, ) + args[1:]
watcher.callback(*args)
except:
watcher._exc_info = sys.exc_info()
the_watcher.callback(*args)
except: # pylint:disable=bare-except
the_watcher._exc_info = sys.exc_info()
# Depending on when the exception happened, the watcher
# may or may not have been stopped. We need to make sure its
# memory stays valid so we can stop it at the ev level if needed.
watcher.loop._keepaliveset.add(watcher)
the_watcher.loop._keepaliveset.add(the_watcher)
return -1
else:
if watcher in watcher.loop._keepaliveset:
if the_watcher in the_watcher.loop._keepaliveset:
# It didn't stop itself
return 0
return 1 # It stopped itself
......@@ -146,9 +148,9 @@ def _python_handle_error(handle, revents):
if revents & (libev.EV_READ | libev.EV_WRITE):
try:
watcher.stop()
except:
except: # pylint:disable=bare-except
watcher.loop.handle_error(watcher, *sys.exc_info())
return
return # pylint:disable=lost-exception
libev.python_handle_error = _python_handle_error
......@@ -254,8 +256,8 @@ if sys.version_info[0] >= 3:
basestring = (bytes, str)
integer_types = int,
else:
import __builtin__
basestring = __builtin__.basestring
import __builtin__ # pylint:disable=import-error
basestring = __builtin__.basestring,
integer_types = (int, __builtin__.long)
......@@ -289,9 +291,9 @@ def _check_flags(flags):
flags &= libev.EVBACKEND_MASK
if not flags:
return
if not (flags & libev.EVBACKEND_ALL):
if not flags & libev.EVBACKEND_ALL:
raise ValueError('Invalid value for backend: 0x%x' % flags)
if not (flags & libev.ev_supported_backends()):
if not flags & libev.ev_supported_backends():
as_list = [_str_hex(x) for x in _flags_to_list(flags)]
raise ValueError('Unsupported backend: %s' % '|'.join(as_list))
......@@ -333,6 +335,7 @@ def _loop_callback(*args, **kwargs):
class loop(object):
# pylint:disable=too-many-public-methods
error_handler = None
......@@ -406,7 +409,7 @@ class loop(object):
# work to rethrow the exception is done by the onerror callback
pass
def _run_callbacks(self, evloop, _, revents):
def _run_callbacks(self, _evloop, _, _revents):
count = 1000
libev.ev_timer_stop(self._ptr, self._timer0)
while self._callbacks and count > 0:
......@@ -424,7 +427,7 @@ class loop(object):
try:
callback(*args)
except:
except: # pylint:disable=bare-except
# If we allow an exception to escape this method (while we are running the ev callback),
# then CFFI will print the error and libev will continue executing.
# There are two problems with this. The first is that the code after
......@@ -442,11 +445,11 @@ class loop(object):
# We take a similar approach (but are extra careful about printing)
try:
self.handle_error(cb, *sys.exc_info())
except:
except: # pylint:disable=bare-except
try:
print("Exception while handling another error", file=sys.stderr)
traceback.print_exc()
except:
except: # pylint:disable=bare-except
pass # Nothing we can do here
finally:
# Note, this must be reset here, because cb.args is used as a flag in callback class,
......@@ -493,11 +496,11 @@ class loop(object):
def _handle_syserr(self, message, errno):
try:
errno = os.strerror(errno)
except:
except: # pylint:disable=bare-except
traceback.print_exc()
try:
message = '%s: %s' % (message, errno)
except:
except: # pylint:disable=bare-except
traceback.print_exc()
self.handle_error(None, SystemError, SystemError(message), None)
......@@ -511,7 +514,7 @@ class loop(object):
else:
self._default_handle_error(context, type, value, tb)
def _default_handle_error(self, context, type, value, tb):
def _default_handle_error(self, context, type, value, tb): # pylint:disable=unused-argument
# note: Hub sets its own error handler so this is not used by gevent
# this is here to make core.loop usable without the rest of gevent
traceback.print_exception(type, value, tb)
......@@ -750,7 +753,7 @@ class watcher(object):
@classmethod
def _init_subclasses(cls):
for subclass in cls.__subclasses__():
for subclass in cls.__subclasses__(): # pylint:disable=no-member
watcher_type = subclass._watcher_type
subclass._watcher_struct_pointer_type = ffi.typeof('struct ' + watcher_type + '*')
subclass._watcher_callback = ffi.addressof(libev,
......
# This module definitely remains in 1.0.x, probably in versions after that too.
import warnings
warnings.warn('gevent.coros has been renamed to gevent.lock', DeprecationWarning, stacklevel=2)
from gevent.lock import *
from gevent.lock import __all__
......@@ -78,9 +78,10 @@ class _AbstractLinkable(object):
if link in self._links:
try:
link(self)
except:
except: # pylint:disable=bare-except
self.hub.handle_error((link, self), *sys.exc_info())
def _wait_core(self, timeout, catch=Timeout):
# The core of the wait implementation, handling
# switching and linking. If *catch* is set to (),
......@@ -108,6 +109,7 @@ class _AbstractLinkable(object):
self.unlink(switch)
def _wait_return_value(self, waited, wait_success):
# pylint:disable=unused-argument
return None
def _wait(self, timeout=None):
......@@ -382,6 +384,7 @@ class AsyncResult(_AbstractLinkable):
return self.get(block=False)
def _wait_return_value(self, waited, gotit):
# pylint:disable=unused-argument
# Always return the value. Since this is a one-shot event,
# no race condition should reset it.
return self.value
......
......@@ -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):
......@@ -133,7 +133,7 @@ class FileObjectThread(object):
def close():
try:
fobj.close()
except:
except: # pylint:disable=bare-except
return sys.exc_info()
exc_info = self.threadpool.apply(close)
if exc_info:
......@@ -168,19 +168,21 @@ class FileObjectThread(object):
raise StopIteration
__next__ = next
def _wraps(method):
def x(self, *args, **kwargs):
fobj = self.io
if fobj is None:
raise FileObjectClosed
return self._apply(getattr(fobj, method), args, kwargs)
x.__name__ = method
return x
for method in ('read', 'readinto', 'readline', 'readlines', 'write', 'writelines', 'xreadlines'):
locals()[method] = _wraps(method)
del method
del _wraps
def _wraps(method):
def x(self, *args, **kwargs):
fobj = self.io
if fobj is None:
raise FileObjectClosed
return self._apply(getattr(fobj, method), args, kwargs)
x.__name__ = method
return x
_method = None
for _method in ('read', 'readinto', 'readline', 'readlines', 'write', 'writelines', 'xreadlines'):
setattr(FileObjectThread, _method, _wraps(_method))
del _method
del _wraps
try:
......@@ -203,7 +205,7 @@ class FileObjectBlock(object):
self.io = fobj
def __repr__(self):
return '<%s %r>' % (self.io, )
return '<%s %r>' % (self.__class__.__name__, self.io, )
def __getattr__(self, item):
assert item != '_fobj'
......
# Copyright (c) 2009-2012 Denis Bilenko. See LICENSE for details.
from __future__ import absolute_import
import sys
from greenlet import greenlet
from gevent.hub import GreenletExit
from gevent.hub import InvalidSwitchError
from gevent.hub import PY3
......@@ -8,7 +9,6 @@ from gevent.hub import PYPY
from gevent.hub import Waiter
from gevent.hub import get_hub
from gevent.hub import getcurrent
from gevent.hub import greenlet
from gevent.hub import iwait
from gevent.hub import reraise
from gevent.hub import wait
......@@ -18,13 +18,15 @@ from gevent._tblib import load_traceback
from collections import deque
__all__ = ['Greenlet',
'joinall',
'killall']
__all__ = [
'Greenlet',
'joinall',
'killall',
]
if PYPY:
import _continuation
import _continuation # pylint:disable=import-error
_continulet = _continuation.continulet
......@@ -103,6 +105,7 @@ class _lazy(object):
class Greenlet(greenlet):
"""A light-weight cooperatively-scheduled execution unit.
"""
# pylint:disable=too-many-public-methods,too-many-instance-attributes
value = None
_exc_info = ()
......@@ -288,27 +291,29 @@ class Greenlet(greenlet):
result += ': ' + formatted
return result + '>'
_formatted_info = None
def _formatinfo(self):
try:
return self._formatted_info
except AttributeError:
pass
info = self._formatted_info
if info is not None:
return info
try:
result = getfuncname(self.__dict__['_run'])
except Exception:
pass
else:
args = []
if self.args:
args = [repr(x)[:50] for x in self.args]
if self._kwargs:
args.extend(['%s=%s' % (key, repr(value)[:50]) for (key, value) in self._kwargs.items()])
if args:
result += '(' + ', '.join(args) + ')'
# it is important to save the result here, because once the greenlet exits '_run' attribute will be removed
self._formatted_info = result
return result
return ''
except Exception: # pylint:disable=broad-except
# Don't cache
return ''
args = []
if self.args:
args = [repr(x)[:50] for x in self.args]
if self._kwargs:
args.extend(['%s=%s' % (key, repr(value)[:50]) for (key, value) in self._kwargs.items()])
if args:
result += '(' + ', '.join(args) + ')'
# it is important to save the result here, because once the greenlet exits '_run' attribute will be removed
self._formatted_info = result
return result
@property
def exception(self):
......@@ -532,7 +537,7 @@ class Greenlet(greenlet):
try:
result = self._run(*self.args, **self.kwargs)
except:
except: # pylint:disable=bare-except
self._report_error(sys.exc_info())
return
self._report_result(result)
......@@ -548,6 +553,8 @@ class Greenlet(greenlet):
Previously, if no callable object was passed to the constructor, the spawned greenlet would
later fail with an AttributeError.
"""
# We usually override this in __init__
# pylint: disable=method-hidden
return
def rawlink(self, callback):
......@@ -559,7 +566,7 @@ class Greenlet(greenlet):
"""
if not callable(callback):
raise TypeError('Expected callable: %r' % (callback, ))
self._links.append(callback)
self._links.append(callback) # pylint:disable=no-member
if self.ready() and self._links and not self._notifier:
self._notifier = self.parent.loop.run_callback(self._notify_links)
......@@ -569,29 +576,34 @@ class Greenlet(greenlet):
The *callback* will be called with this instance as an argument
once this greenlet's dead. A callable is called in its own greenlet.
"""
# XXX: Is the redefinition of SpawnedLink supposed to just be an
# optimization, or do people use it? It's not documented
# pylint:disable=redefined-outer-name
self.rawlink(SpawnedLink(callback))
def unlink(self, callback):
"""Remove the callback set by :meth:`link` or :meth:`rawlink`"""
try:
self._links.remove(callback)
self._links.remove(callback) # pylint:disable=no-member
except ValueError:
pass
def link_value(self, callback, SpawnedLink=SuccessSpawnedLink):
"""Like :meth:`link` but *callback* is only notified when the greenlet has completed successfully."""
# pylint:disable=redefined-outer-name
self.link(callback, SpawnedLink=SpawnedLink)
def link_exception(self, callback, SpawnedLink=FailureSpawnedLink):
"""Like :meth:`link` but *callback* is only notified when the greenlet dies because of an unhandled exception."""
# pylint:disable=redefined-outer-name
self.link(callback, SpawnedLink=SpawnedLink)
def _notify_links(self):
while self._links:
link = self._links.popleft()
link = self._links.popleft() # pylint:disable=no-member
try:
link(self)
except:
except: # pylint:disable=bare-except
self.parent.handle_error((link, self), *sys.exc_info())
......@@ -602,18 +614,21 @@ class _dummy_event(object):
def stop(self):
pass
def start(self, cb): # pylint:disable=unused-argument
raise AssertionError("Cannot start the dummy event")
_cancelled_start_event = _dummy_event()
_start_completed_event = _dummy_event()
del _dummy_event
def _kill(greenlet, exception, waiter):
def _kill(glet, exception, waiter):
try:
greenlet.throw(exception)
except:
glet.throw(exception)
except: # pylint:disable=bare-except
# XXX do we need this here?
greenlet.parent.handle_error(greenlet, *sys.exc_info())
glet.parent.handle_error(glet, *sys.exc_info())
if waiter is not None:
waiter.switch()
......@@ -647,7 +662,7 @@ def _killall3(greenlets, exception, waiter):
if not g.dead:
try:
g.throw(exception)
except:
except: # pylint:disable=bare-except
g.parent.handle_error(g, *sys.exc_info())
if not g.dead:
diehards.append(g)
......@@ -659,7 +674,7 @@ def _killall(greenlets, exception):
if not g.dead:
try:
g.throw(exception)
except:
except: # pylint:disable=bare-except
g.parent.handle_error(g, *sys.exc_info())
......
......@@ -3,24 +3,28 @@
Event-loop hub.
"""
from __future__ import absolute_import
# XXX: FIXME: Refactor to make this smaller
# pylint:disable=too-many-lines
from functools import partial as _functools_partial
import os
import sys
import traceback
from greenlet import greenlet, getcurrent, GreenletExit
from greenlet import greenlet as RawGreenlet, getcurrent, GreenletExit
__all__ = ['getcurrent',
'GreenletExit',
'spawn_raw',
'sleep',
'kill',
'signal',
'reinit',
'get_hub',
'Hub',
'Waiter']
__all__ = [
'getcurrent',
'GreenletExit',
'spawn_raw',
'sleep',
'kill',
'signal',
'reinit',
'get_hub',
'Hub',
'Waiter',
]
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] >= 3
......@@ -33,25 +37,25 @@ if PY3:
text_type = str
xrange = range
def reraise(tp, value, tb=None):
def reraise(t, value, tb=None): # pylint:disable=unused-argument
if value.__traceback__ is not tb:
raise value.with_traceback(tb)
raise value
else:
import __builtin__
import __builtin__ # pylint:disable=import-error
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
from gevent._util_py2 import reraise # pylint:disable=import-error,unused-import,no-name-in-module
if sys.version_info[0] <= 2:
import thread
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.
......@@ -155,10 +159,10 @@ def spawn_raw(function, *args, **kwargs):
# implemented twice in core.ppyx and corecffi.py) so do it with a partial
if kwargs:
function = _functools_partial(function, *args, **kwargs)
g = greenlet(function, hub)
g = RawGreenlet(function, hub)
hub.loop.run_callback(g.switch)
else:
g = greenlet(function, hub)
g = RawGreenlet(function, hub)
hub.loop.run_callback(g.switch, *args)
return g
......@@ -287,13 +291,13 @@ class signal(object):
try:
greenlet = self.greenlet_class(self.handle)
greenlet.switch()
except:
self.hub.handle_error(None, *sys._exc_info())
except: # pylint:disable=bare-except
self.hub.handle_error(None, *sys._exc_info()) # pylint:disable=no-member
def handle(self):
try:
self.handler(*self.args, **self.kwargs)
except:
except: # pylint:disable=bare-except
self.hub.handle_error(None, *sys.exc_info())
......@@ -401,24 +405,31 @@ def set_hub(hub):
def _import(path):
# pylint:disable=too-many-branches
if isinstance(path, list):
if not path:
raise ImportError('Cannot import from empty list: %r' % (path, ))
for item in path[:-1]:
try:
return _import(item)
except ImportError:
pass
return _import(path[-1])
if not isinstance(path, string_types):
return path
if '.' not in path:
raise ImportError("Cannot import %r (required format: [path/][package.]module.class)" % path)
if '/' in path:
package_path, path = path.rsplit('/', 1)
sys.path = [package_path] + sys.path
else:
package_path = None
try:
module, item = path.rsplit('.', 1)
x = __import__(module)
......@@ -455,7 +466,7 @@ _resolvers = {'ares': 'gevent.resolver_ares.Resolver',
_DEFAULT_LOOP_CLASS = 'gevent.core.loop'
class Hub(greenlet):
class Hub(RawGreenlet):
"""A greenlet that runs the event loop.
It is created automatically by :func:`get_hub`.
......@@ -504,7 +515,7 @@ class Hub(greenlet):
threadpool_size = 10
def __init__(self, loop=None, default=None):
greenlet.__init__(self)
RawGreenlet.__init__(self)
if hasattr(loop, 'run'):
if default is not None:
raise TypeError("Unexpected argument: default")
......@@ -531,7 +542,7 @@ class Hub(greenlet):
else:
try:
info = self.loop._format()
except Exception as ex:
except Exception as ex: # pylint:disable=broad-except
info = str(ex) or repr(ex) or 'error'
result = '<%s at 0x%x %s' % (self.__class__.__name__, id(self), info)
if self._resolver is not None:
......@@ -574,7 +585,7 @@ class Hub(greenlet):
cb = None
try:
cb = self.loop.run_callback(current.switch)
except:
except: # pylint:disable=bare-except
traceback.print_exc()
try:
self.parent.throw(type, value)
......@@ -594,7 +605,7 @@ class Hub(greenlet):
if not isinstance(context, str):
try:
context = self.format_context(context)
except:
except: # pylint:disable=bare-except
traceback.print_exc()
context = repr(context)
sys.stderr.write('%s failed with %s\n\n' % (context, getattr(type, '__name__', 'exception'), ))
......@@ -603,7 +614,7 @@ class Hub(greenlet):
switch_out = getattr(getcurrent(), 'switch_out', None)
if switch_out is not None:
switch_out()
return greenlet.switch(self)
return RawGreenlet.switch(self)
def switch_out(self):
raise BlockingSwitchOutError('Impossible to call blocking function in the event loop callback')
......@@ -841,7 +852,7 @@ class Waiter(object):
switch = greenlet.switch
try:
switch(value)
except:
except: # pylint:disable=bare-except
self.hub.handle_error(switch, *sys.exc_info())
def switch_args(self, *args):
......@@ -857,7 +868,7 @@ class Waiter(object):
throw = greenlet.throw
try:
throw(*throw_args)
except:
except: # pylint:disable=bare-except
self.hub.handle_error(throw, *sys.exc_info())
def get(self):
......@@ -906,7 +917,7 @@ class _MultipleWaiter(Waiter):
# here can be impractical (see https://github.com/gevent/gevent/issues/652)
self._values = list()
def switch(self, value):
def switch(self, value): # pylint:disable=signature-differs
self._values.append(value)
Waiter.switch(self, True)
......@@ -966,12 +977,12 @@ def iwait(objects, timeout=None, count=None):
finally:
if timeout is not None:
timer.stop()
for obj in objects:
unlink = getattr(obj, 'unlink', None)
for aobj in objects:
unlink = getattr(aobj, 'unlink', None)
if unlink:
try:
unlink(switch)
except:
except: # pylint:disable=bare-except
traceback.print_exc()
......
......@@ -3,10 +3,15 @@
from __future__ import absolute_import
from gevent.hub import getcurrent, PYPY
from gevent._semaphore import Semaphore, BoundedSemaphore
from gevent._semaphore import Semaphore, BoundedSemaphore # pylint:disable=no-name-in-module,import-error
__all__ = ['Semaphore', 'DummySemaphore', 'BoundedSemaphore', 'RLock']
__all__ = [
'Semaphore',
'DummySemaphore',
'BoundedSemaphore',
'RLock',
]
# On PyPy, we don't compile the Semaphore class with Cython. Under
# Cython, each individual method holds the GIL for its entire
......@@ -17,10 +22,34 @@ __all__ = ['Semaphore', 'DummySemaphore', 'BoundedSemaphore', 'RLock']
# to use locks *other* than the one being traced.)
if PYPY:
# TODO: Need to use monkey.get_original?
from thread import allocate_lock as _allocate_lock
from thread import get_ident as _get_ident
from thread import allocate_lock as _allocate_lock # pylint:disable=import-error,useless-suppression
from thread import get_ident as _get_ident # pylint:disable=import-error,useless-suppression
_sem_lock = _allocate_lock()
def untraceable(f):
# Don't allow re-entry to these functions in a single thread, as can
# happen if a sys.settrace is used
def wrapper(self):
me = _get_ident()
try:
count = self._locking[me]
except KeyError:
count = self._locking[me] = 1
else:
count = self._locking[me] = count + 1
if count:
return
try:
return f(self)
finally:
count = count - 1
if not count:
del self._locking[me]
else:
self._locking[me] = count
return wrapper
class _OwnedLock(object):
def __init__(self):
......@@ -29,30 +58,6 @@ if PYPY:
self._locking = {}
self._count = 0
def untraceable(f):
# Don't allow re-entry to these functions in a single thread, as can
# happen if a sys.settrace is used
def wrapper(self):
me = _get_ident()
try:
count = self._locking[me]
except KeyError:
count = self._locking[me] = 1
else:
count = self._locking[me] = count + 1
if count:
return
try:
return f(self)
finally:
count = count - 1
if not count:
del self._locking[me]
else:
self._locking[me] = count
return wrapper
@untraceable
def acquire(self):
me = _get_ident()
......@@ -75,8 +80,11 @@ if PYPY:
# on exit. acquire and wait can call _do_wait, which must release it on entry
# and re-acquire it for them on exit.
class _around(object):
before = None
after = None
__slots__ = ('before', 'after')
def __init__(self, before, after):
self.before = before
self.after = after
def __enter__(self):
self.before()
......@@ -100,17 +108,15 @@ if PYPY:
def __init__(self, *args, **kwargs):
l = self._lock_lock = _OwnedLock()
self._lock_locked = _around()
self._lock_locked.before = l.acquire
self._lock_locked.after = l.release
self._lock_unlocked = _around()
self._lock_unlocked.before = l.release
self._lock_unlocked.after = l.acquire
self._lock_locked = _around(l.acquire, l.release)
self._lock_unlocked = _around(l.release, l.acquire)
_Sem_init(self, *args, **kwargs)
Semaphore.__init__ = __init__
del _decorate
del untraceable
class DummySemaphore(object):
......@@ -178,6 +184,7 @@ class DummySemaphore(object):
.. versionchanged:: 1.1a1
Always return *true*.
"""
# pylint:disable=unused-argument
return True
def __enter__(self):
......
......@@ -80,14 +80,11 @@ if sys.version_info[0] >= 3:
string_types = str,
PY3 = True
else:
import __builtin__
string_types = __builtin__.basestring
import __builtin__ # pylint:disable=import-error
string_types = __builtin__.basestring,
PY3 = False
if sys.platform.startswith("win"):
WIN = True
else:
WIN = False
WIN = sys.platform.startswith("win")
# maps module name -> {attribute name: original item}
# e.g. "time" -> {"sleep": built-in function sleep}
......@@ -133,19 +130,19 @@ def get_original(mod_name, item_name):
else:
return _get_original(mod_name, item_name)
_NONE = object()
def patch_item(module, attr, newitem):
NONE = object()
olditem = getattr(module, attr, NONE)
if olditem is not NONE:
olditem = getattr(module, attr, _NONE)
if olditem is not _NONE:
saved.setdefault(module.__name__, {}).setdefault(attr, olditem)
setattr(module, attr, newitem)
def remove_item(module, attr):
NONE = object()
olditem = getattr(module, attr, NONE)
if olditem is NONE:
olditem = getattr(module, attr, _NONE)
if olditem is _NONE:
return
saved.setdefault(module.__name__, {}).setdefault(attr, olditem)
delattr(module, attr)
......@@ -247,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
......@@ -294,6 +291,9 @@ def patch_thread(threading=True, _threading_local=True, Event=False, logging=Tru
.. versionchanged:: 1.1b1
Add *logging* and *existing_locks* params.
"""
# XXX: Simplify
# pylint:disable=too-many-branches
# Description of the hang:
# There is an incompatibility with patching 'thread' and the 'multiprocessing' module:
# The problem is that multiprocessing.queues.Queue uses a half-duplex multiprocessing.Pipe,
......@@ -326,18 +326,18 @@ def patch_thread(threading=True, _threading_local=True, Event=False, logging=Tru
patch_module('thread')
if threading:
threading = patch_module('threading')
threading_mod = patch_module('threading')
if Event:
from gevent.event import Event
patch_item(threading, 'Event', Event)
patch_item(threading_mod, 'Event', Event)
if existing_locks:
_patch_existing_locks(threading)
_patch_existing_locks(threading_mod)
if logging and 'logging' in sys.modules:
logging = __import__('logging')
patch_item(logging, '_lock', threading.RLock())
patch_item(logging, '_lock', threading_mod.RLock())
for wr in logging._handlerList:
# In py26, these are actual handlers, not weakrefs
handler = wr() if callable(wr) else wr
......@@ -345,7 +345,7 @@ def patch_thread(threading=True, _threading_local=True, Event=False, logging=Tru
continue
if not hasattr(handler, 'lock'):
raise TypeError("Unknown/unsupported handler %r" % handler)
handler.lock = threading.RLock()
handler.lock = threading_mod.RLock()
if _threading_local:
_threading_local = __import__('_threading_local')
......@@ -359,15 +359,15 @@ def patch_thread(threading=True, _threading_local=True, Event=False, logging=Tru
# (which is already running) cannot wait for the main thread---it
# hangs forever. We patch around this if possible. See also
# gevent.threading.
threading = __import__('threading')
threading_mod = __import__('threading')
greenlet = __import__('greenlet')
if threading.current_thread() == threading.main_thread():
main_thread = threading.main_thread()
if threading_mod.current_thread() == threading_mod.main_thread():
main_thread = threading_mod.main_thread()
_greenlet = main_thread._greenlet = greenlet.getcurrent()
from gevent.hub import sleep
def join(timeout=None):
if threading.current_thread() is main_thread:
if threading_mod.current_thread() is main_thread:
raise RuntimeError("Cannot join current thread")
if _greenlet.dead or not main_thread.is_alive():
return
......@@ -384,11 +384,11 @@ def patch_thread(threading=True, _threading_local=True, Event=False, logging=Tru
# matters if threading was imported before monkey-patching
# thread
oldid = main_thread.ident
main_thread._ident = threading.get_ident()
if oldid in threading._active:
threading._active[main_thread.ident] = threading._active[oldid]
main_thread._ident = threading_mod.get_ident()
if oldid in threading_mod._active:
threading_mod._active[main_thread.ident] = threading_mod._active[oldid]
if oldid != main_thread.ident:
del threading._active[oldid]
del threading_mod._active[oldid]
else:
_queue_warning("Monkey-patching not on the main thread; "
"threading.main_thread().join() will hang from a greenlet",
......@@ -407,12 +407,12 @@ def patch_socket(dns=True, aggressive=True):
# However, because gevent.socket.socket.connect is a Python function, the exception raised by it causes
# _socket object to be referenced by the frame, thus causing the next invocation of bind(source_address) to fail.
if dns:
items = socket.__implements__
items = socket.__implements__ # pylint:disable=no-member
else:
items = set(socket.__implements__) - set(socket.__dns__)
items = set(socket.__implements__) - set(socket.__dns__) # pylint:disable=no-member
patch_module('socket', items=items)
if aggressive:
if 'ssl' not in socket.__implements__:
if 'ssl' not in socket.__implements__: # pylint:disable=no-member
remove_item(socket, 'ssl')
......@@ -423,7 +423,7 @@ def patch_dns():
by that method if requested.
"""
from gevent import socket
patch_module('socket', items=socket.__dns__)
patch_module('socket', items=socket.__dns__) # pylint:disable=no-member
def patch_ssl():
......@@ -471,7 +471,7 @@ def patch_select(aggressive=True):
select = __import__('select')
selectors = __import__('selectors')
if selectors.SelectSelector._select is select.select:
def _select(self, *args, **kwargs):
def _select(self, *args, **kwargs): # pylint:disable=unused-argument
return select.select(*args, **kwargs)
selectors.SelectSelector._select = _select
......@@ -555,6 +555,8 @@ def patch_all(socket=True, dns=True, time=True, select=True, thread=True, os=Tru
and ``signal=True``. This will cause SIGCHLD handlers to not be called. This may
be an error in the future.
"""
# pylint:disable=too-many-locals,too-many-branches
# Check to see if they're changing the patched list
_warnings, first_time = _check_repatching(**locals())
if not _warnings and not first_time:
......@@ -640,7 +642,7 @@ def main():
def _get_script_help():
from inspect import getargspec
patch_all_args = getargspec(patch_all)[0]
patch_all_args = getargspec(patch_all)[0] # pylint:disable=deprecated-method
modules = [x for x in patch_all_args if 'patch_' + x in globals()]
script_help = """gevent.monkey - monkey patch the standard modules to use gevent.
......
......@@ -140,6 +140,8 @@ def tp_write(fd, buf):
if hasattr(os, 'fork'):
# pylint:disable=function-redefined,redefined-outer-name
_raw_fork = os.fork
def fork_gevent():
......@@ -338,7 +340,7 @@ if hasattr(os, 'fork'):
if pid:
# parent
loop = loop or get_hub().loop
watcher = loop.child(pid)
watcher = loop.child(pid, ref=ref)
_watched_children[pid] = watcher
watcher.start(_on_child, watcher, callback)
return pid
......
......@@ -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
......@@ -113,7 +115,7 @@ class IMapUnordered(Greenlet):
g.rawlink(self._on_result)
return g
def _run(self):
def _run(self): # pylint:disable=method-hidden
try:
func = self.func
for item in self.iterable:
......@@ -241,7 +243,7 @@ class GroupMappingMixin(object):
def apply_cb(self, func, args=None, kwds=None, callback=None):
"""
:meth:`apply` the given *func(\*args, \*\*kwds)*, and, if a *callback* is given, run it with the
:meth:`apply` the given *func(\\*args, \\*\\*kwds)*, and, if a *callback* is given, run it with the
results of *func* (unless an exception was raised.)
The *callback* may be called synchronously or asynchronously. If called
......@@ -556,23 +558,23 @@ class Group(GroupMappingMixin):
"""
timer = Timeout._start_new_or_dummy(timeout)
try:
try:
while self.greenlets:
for greenlet in list(self.greenlets):
if greenlet not in self.dying:
try:
kill = greenlet.kill
except AttributeError:
_kill(greenlet, exception)
else:
kill(exception, block=False)
self.dying.add(greenlet)
if not block:
break
joinall(self.greenlets)
except Timeout as ex:
if ex is not timer:
raise
while self.greenlets:
for greenlet in list(self.greenlets):
if greenlet in self.dying:
continue
try:
kill = greenlet.kill
except AttributeError:
_kill(greenlet, exception)
else:
kill(exception, block=False)
self.dying.add(greenlet)
if not block:
break
joinall(self.greenlets)
except Timeout as ex:
if ex is not timer:
raise
finally:
timer.cancel()
......@@ -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):
"""
......
......@@ -9,6 +9,9 @@ created for each request. The server can be customized to use
different subclasses of :class:`WSGIHandler`.
"""
# FIXME: Can we refactor to make smallor?
# pylint:disable=too-many-lines
import errno
from io import BytesIO
import string
......@@ -20,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
......@@ -106,6 +109,7 @@ class Input(object):
'chunked_input', 'chunk_length', '_chunked_input_error')
def __init__(self, rfile, content_length, socket=None, chunked_input=False):
# pylint:disable=redefined-outer-name
self.rfile = rfile
self.content_length = content_length
self.socket = socket
......@@ -250,6 +254,7 @@ class Input(object):
return int(buf.getvalue(), 16)
def _chunked_read(self, length=None, use_readline=False):
# pylint:disable=too-many-branches
rfile = self.rfile
self._send_100_continue()
......@@ -312,6 +317,7 @@ class Input(object):
return self._do_read(size, use_readline=True)
def readlines(self, hint=None):
# pylint:disable=unused-argument
return list(self)
def __iter__(self):
......@@ -330,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):
......@@ -349,7 +355,7 @@ except ImportError:
def typeheader(self):
return self.get('content-type')
def headers_factory(fp, *args):
def headers_factory(fp, *args): # pylint:disable=unused-argument
try:
ret = client.parse_headers(fp, _class=OldMessage)
except client.LineTooLong:
......@@ -373,6 +379,8 @@ class WSGIHandler(object):
itself. The application and environment are obtained from the server.
"""
# pylint:disable=too-many-instance-attributes
protocol_version = 'HTTP/1.1'
if PY3:
# if we do like Py2, then headers_factory unconditionally
......@@ -412,17 +420,17 @@ class WSGIHandler(object):
command = None # str: 'GET'
path = None # str: '/'
def __init__(self, socket, address, server, rfile=None):
def __init__(self, sock, address, server, rfile=None):
# Deprecation: The rfile kwarg was introduced in 1.0a1 as part
# of a refactoring. It was never documented or used. It is
# considered DEPRECATED and may be removed in the future. Its
# use is not supported.
self.socket = socket
self.socket = sock
self.client_address = address
self.server = server
if rfile is None:
self.rfile = socket.makefile('rb', -1)
self.rfile = sock.makefile('rb', -1)
else:
self.rfile = rfile
......@@ -470,10 +478,10 @@ class WSGIHandler(object):
self.__dict__.pop('rfile', None)
def _check_http_version(self):
version = self.request_version
if not version.startswith("HTTP/"):
version_str = self.request_version
if not version_str.startswith("HTTP/"):
return False
version = tuple(int(x) for x in version[5:].split(".")) # "HTTP/"
version = tuple(int(x) for x in version_str[5:].split(".")) # "HTTP/"
if version[1] < 0 or version < (0, 9) or version >= (2, 0):
return False
return True
......@@ -500,6 +508,7 @@ class WSGIHandler(object):
Raise the previously documented :exc:`ValueError` in more cases instead of returning a
false value; this allows subclasses more opportunity to customize behaviour.
"""
# pylint:disable=too-many-branches
self.requestline = raw_requestline.rstrip()
words = self.requestline.split()
if len(words) == 3:
......@@ -539,10 +548,7 @@ class WSGIHandler(object):
if self.request_version == "HTTP/1.1":
conntype = self.headers.get("Connection", "").lower()
if conntype == "close":
self.close_connection = True
else:
self.close_connection = False
self.close_connection = (conntype == 'close')
else:
self.close_connection = True
......@@ -551,17 +557,17 @@ class WSGIHandler(object):
def log_error(self, msg, *args):
try:
message = msg % args
except Exception:
except Exception: # pylint:disable=broad-except
traceback.print_exc()
message = '%r %r' % (msg, args)
try:
message = '%s: %s' % (self.socket, message)
except Exception:
except Exception: # pylint:disable=broad-except
pass
try:
self.server.error_log.write(message + '\n')
except Exception:
except Exception: # pylint:disable=broad-except
traceback.print_exc()
def read_requestline(self):
......@@ -620,8 +626,10 @@ class WSGIHandler(object):
:meth:`_handle_client_error` to allow subclasses to customize. Note that
this is experimental and may change in the future.
"""
# pylint:disable=too-many-return-statements
if self.rfile.closed:
return
try:
self.requestline = self.read_requestline()
# Account for old subclasses that haven't done this
......@@ -645,7 +653,7 @@ class WSGIHandler(object):
# subclasses that return a False value instead.
if not self.read_request(self.requestline):
return ('400', _BAD_REQUEST_RESPONSE)
except Exception as ex:
except Exception as ex: # pylint:disable=broad-except
# Notice we don't use self.handle_error because it reports
# a 500 error to the client, and this is almost certainly
# a client error.
......@@ -748,6 +756,7 @@ class WSGIHandler(object):
and headers during this method. On Python 2, avoid some
extra encodings.
"""
# pylint:disable=too-many-branches
if exc_info:
try:
if self.headers_sent:
......@@ -909,7 +918,7 @@ class WSGIHandler(object):
self.close_connection = True
else:
self.handle_error(*sys.exc_info())
except:
except: # pylint:disable=bare-except
self.handle_error(*sys.exc_info())
finally:
self.time_finish = time.time()
......@@ -1014,11 +1023,12 @@ class WSGIHandler(object):
env[key] = value
if env.get('HTTP_EXPECT') == '100-continue':
socket = self.socket
sock = self.socket
else:
socket = None
sock = None
chunked = env.get('HTTP_TRANSFER_ENCODING', '').lower() == 'chunked'
self.wsgi_input = Input(self.rfile, self.content_length, socket=socket, chunked_input=chunked)
self.wsgi_input = Input(self.rfile, self.content_length, socket=sock, chunked_input=chunked)
env['wsgi.input'] = self.wsgi_input
return env
......@@ -1028,6 +1038,7 @@ class _NoopLog(object):
# to pass the WSGI validator
def write(self, *args, **kwargs):
# pylint:disable=unused-argument
return
def flush(self):
......@@ -1236,18 +1247,19 @@ 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:
self.environ.setdefault('SERVER_NAME', '')
self.environ.setdefault('SERVER_PORT', '')
def handle(self, socket, address):
def handle(self, sock, address):
"""
Create an instance of :attr:`handler_class` to handle the request.
This method blocks until the handler returns.
"""
handler = self.handler_class(socket, address, self)
# pylint:disable=method-hidden
handler = self.handler_class(sock, address, self)
handler.handle()
......@@ -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
......@@ -105,6 +105,8 @@ class Queue(object):
return type(self)(self.maxsize, self.queue)
def _init(self, maxsize, items=None):
# FIXME: Why is maxsize unused or even passed?
# pylint:disable=unused-argument
if items:
self.queue = collections.deque(items)
else:
......@@ -321,7 +323,7 @@ class Queue(object):
try:
putter = self.putters.popleft()
self._put(putter.item)
except:
except: # pylint:disable=bare-except
putter.throw(*sys.exc_info())
else:
putter.switch(putter)
......@@ -378,9 +380,11 @@ class PriorityQueue(Queue):
self.queue = []
def _put(self, item, heappush=heapq.heappush):
# pylint:disable=arguments-differ
heappush(self.queue, item)
def _get(self, heappop=heapq.heappop):
# pylint:disable=arguments-differ
return heappop(self.queue)
......@@ -593,3 +597,5 @@ class Channel(object):
if result is StopIteration:
raise result
return result
__next__ = next # py3
......@@ -8,7 +8,7 @@ import sys
from _socket import getservbyname, getaddrinfo, gaierror, error
from gevent.hub import Waiter, get_hub, string_types, text_type, integer_types, reraise, PY3
from gevent.socket import AF_UNSPEC, AF_INET, AF_INET6, SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, AI_NUMERICHOST, EAI_SERVICE, AI_PASSIVE
from gevent.ares import channel, InvalidIP
from gevent.ares import channel, InvalidIP # pylint:disable=import-error,no-name-in-module
__all__ = ['Resolver']
......@@ -101,6 +101,7 @@ class Resolver(object):
# "self.ares is not ares" means channel was destroyed (because we were forked)
def _lookup_port(self, port, socktype):
# pylint:disable=too-many-branches
socktypes = []
if isinstance(port, string_types):
try:
......@@ -146,6 +147,7 @@ class Resolver(object):
return port, socktypes
def _getaddrinfo(self, host, port, family=0, socktype=0, proto=0, flags=0):
# pylint:disable=too-many-locals,too-many-branches
if isinstance(host, text_type):
host = host.encode('idna')
elif not isinstance(host, str) or (flags & AI_NUMERICHOST):
......@@ -167,19 +169,19 @@ class Resolver(object):
ares = self.ares
if family == AF_UNSPEC:
values = Values(self.hub, 2)
ares.gethostbyname(values, host, AF_INET)
ares.gethostbyname(values, host, AF_INET6)
ares_values = Values(self.hub, 2)
ares.gethostbyname(ares_values, host, AF_INET)
ares.gethostbyname(ares_values, host, AF_INET6)
elif family == AF_INET:
values = Values(self.hub, 1)
ares.gethostbyname(values, host, AF_INET)
ares_values = Values(self.hub, 1)
ares.gethostbyname(ares_values, host, AF_INET)
elif family == AF_INET6:
values = Values(self.hub, 1)
ares.gethostbyname(values, host, AF_INET6)
ares_values = Values(self.hub, 1)
ares.gethostbyname(ares_values, host, AF_INET6)
else:
raise gaierror(5, 'ai_family not supported: %r' % (family, ))
values = values.get()
values = ares_values.get()
if len(values) == 2 and values[0] == values[1]:
values.pop()
......@@ -281,7 +283,7 @@ class Resolver(object):
reraise(*sys.exc_info())
elif len(result) != 1:
raise error('sockaddr resolved to multiple addresses')
family, socktype, proto, name, address = result[0]
family, _socktype, _proto, _name, address = result[0]
if family == AF_INET:
if len(sockaddr) != 2:
......@@ -331,7 +333,8 @@ class Values(object):
if self.values:
return self.values
else:
raise self.error
assert error is not None
raise self.error # pylint:disable=raising-bad-type
def _resolve_special(hostname, family):
......
......@@ -51,7 +51,7 @@ class SelectResult(object):
self.event.set()
def select(rlist, wlist, xlist, timeout=None):
def select(rlist, wlist, xlist, timeout=None): # pylint:disable=unused-argument
"""An implementation of :meth:`select.select` that blocks only the current greenlet.
Note: *xlist* is ignored.
......@@ -78,8 +78,8 @@ def select(rlist, wlist, xlist, timeout=None):
result.event.wait(timeout=timeout)
return result.read, result.write, []
finally:
for watcher in watchers:
watcher.stop()
for awatcher in watchers:
awatcher.stop()
if original_poll is not None:
class PollResult(object):
......@@ -122,13 +122,13 @@ 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)
finally:
for fd in self.fds:
self.fds[fd].stop()
for afd in self.fds:
self.fds[afd].stop()
def unregister(self, fd):
self.fds.pop(fd, None)
......@@ -77,6 +77,8 @@ class StreamServer(BaseServer):
def init_socket(self):
if not hasattr(self, 'socket'):
# FIXME: clean up the socket lifetime
# pylint:disable=attribute-defined-outside-init
self.socket = self.get_listener(self.address, self.backlog, self.family)
self.address = self.socket.getsockname()
if self.ssl_args:
......@@ -85,10 +87,10 @@ class StreamServer(BaseServer):
self._handle = self.handle
@classmethod
def get_listener(self, address, backlog=None, family=None):
def get_listener(cls, address, backlog=None, family=None):
if backlog is None:
backlog = self.backlog
return _tcp_listener(address, backlog=backlog, reuse_addr=self.reuse_addr, family=family)
backlog = cls.backlog
return _tcp_listener(address, backlog=backlog, reuse_addr=cls.reuse_addr, family=family)
if PY3:
......@@ -96,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
......@@ -118,8 +120,8 @@ class StreamServer(BaseServer):
client_socket._drop()
return sockobj, address
def do_close(self, socket, *args):
socket.close()
def do_close(self, sock, *args):
sock.close()
def wrap_socket_and_handle(self, client_socket, address):
# used in case of ssl sockets
......@@ -133,12 +135,16 @@ class DatagramServer(BaseServer):
reuse_addr = DEFAULT_REUSE_ADDR
def __init__(self, *args, **kwargs):
# The raw (non-gevent) socket, if possible
self._socket = None
BaseServer.__init__(self, *args, **kwargs)
from gevent.lock import Semaphore
self._writelock = Semaphore()
def init_socket(self):
if not hasattr(self, 'socket'):
# FIXME: clean up the socket lifetime
# pylint:disable=attribute-defined-outside-init
self.socket = self.get_listener(self.address, self.family)
self.address = self.socket.getsockname()
self._socket = self.socket
......@@ -148,8 +154,8 @@ class DatagramServer(BaseServer):
pass
@classmethod
def get_listener(self, address, family=None):
return _udp_socket(address, reuse_addr=self.reuse_addr, family=family)
def get_listener(cls, address, family=None):
return _udp_socket(address, reuse_addr=cls.reuse_addr, family=family)
def do_read(self):
try:
......@@ -186,6 +192,9 @@ def _tcp_listener(address, backlog=50, reuse_addr=None, family=_socket.AF_INET):
def _udp_socket(address, backlog=50, reuse_addr=None, family=_socket.AF_INET):
# backlog argument for compat with tcp_listener
# pylint:disable=unused-argument
# we want gevent.socket.socket here
sock = socket(family=family, type=_socket.SOCK_DGRAM)
if reuse_addr is not None:
......
......@@ -10,16 +10,30 @@ in this module only block the current greenlet and let the others run.
For convenience, exceptions (like :class:`error <socket.error>` and :class:`timeout <socket.timeout>`)
as well as the constants from the :mod:`socket` module are imported into this module.
"""
# Our import magic sadly makes this warning useless
# pylint: disable=undefined-variable
import sys
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
# define some things we're expecting to overwrite; each module
# needs to define these
__implements__ = __dns__ = __all__ = __extensions__ = __imports__ = ()
class error(Exception):
errno = None
def getfqdn(*args):
# pylint:disable=unused-argument
raise NotImplementedError()
for key in _source.__dict__:
if key.startswith('__') and key not in '__implements__ __dns__ __all__ __extensions__ __imports__ __socket__'.split():
......@@ -62,7 +76,7 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=N
host, port = address
err = None
for res in getaddrinfo(host, port, 0 if has_ipv6 else AF_INET, SOCK_STREAM):
af, socktype, proto, _canonname, sa = res
af, socktype, proto, _, sa = res
sock = None
try:
sock = socket(af, socktype, proto)
......@@ -78,12 +92,12 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=N
# that does not happen with regular sockets though, because _socket.socket.connect() is a built-in.
# this is similar to "getnameinfo loses a reference" failure in test_socket.py
if not PY3:
sys.exc_clear()
sys.exc_clear() # pylint:disable=no-member,useless-suppression
if sock is not None:
sock.close()
err = ex
if err is not None:
raise err
raise err # pylint:disable=raising-bad-type
else:
raise error("getaddrinfo returns an empty list")
......
......@@ -21,6 +21,15 @@ Cooperative ``subprocess`` module.
.. _is not defined: http://www.linuxprogrammingblog.com/all-about-linux-signals?page=11
"""
from __future__ import absolute_import, print_function
# Can we split this up to make it cleaner? See https://github.com/gevent/gevent/issues/748
# pylint: disable=too-many-lines
# Import magic
# pylint: disable=undefined-all-variable,undefined-variable
# Most of this we inherit from the standard lib
# pylint: disable=bare-except,too-many-locals,too-many-statements,bad-builtin,attribute-defined-outside-init
# pylint: disable=too-many-branches,too-many-instance-attributes
# Most of this is cross-platform
# pylint: disable=no-member,expression-not-assigned,unused-argument,unused-variable
import errno
import gc
import io
......@@ -49,6 +58,9 @@ if PY3 and not sys.platform.startswith('win32'):
__implements__.append("_posixsubprocess")
_posixsubprocess = None
# Some symbols we define that we expect to export;
# useful for static analysis
PIPE = "PIPE should be imported"
# Standard functions and classes that this module re-imports.
__imports__ = [
......@@ -155,7 +167,7 @@ __all__ = __implements__ + __imports__
mswindows = sys.platform == 'win32'
if mswindows:
import msvcrt
import msvcrt # pylint: disable=import-error
if PY3:
class Handle(int):
closed = False
......@@ -394,7 +406,7 @@ class Popen(object):
# POSIX
if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS:
# close_fds has different defaults on Py3/Py2
if PY3:
if PY3: # pylint: disable=simplifiable-if-statement
close_fds = True
else:
close_fds = False
......@@ -669,7 +681,7 @@ class Popen(object):
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
def __exit__(self, t, v, tb):
if self.stdout:
self.stdout.close()
if self.stderr:
......
......@@ -19,9 +19,9 @@ __implements__ = ['allocate_lock',
__imports__ = ['error']
if sys.version_info[0] <= 2:
import thread as __thread__
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',
......@@ -43,8 +43,11 @@ def get_ident(gr=None):
return id(gr)
def start_new_thread(function, args=(), kwargs={}):
greenlet = Greenlet.spawn(function, *args, **kwargs)
def start_new_thread(function, args=(), kwargs=None):
if kwargs is not None:
greenlet = Greenlet.spawn(function, *args, **kwargs)
else:
greenlet = Greenlet.spawn(function, *args)
return get_ident(greenlet)
......@@ -54,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
......
from __future__ import absolute_import
__implements__ = ['local',
'_start_new_thread',
'_allocate_lock',
'Lock',
'_get_ident',
'_sleep',
'_DummyThread']
__implements__ = [
'local',
'_start_new_thread',
'_allocate_lock',
'Lock',
'_get_ident',
'_sleep',
'_DummyThread',
]
import threading as __threading__
......@@ -15,6 +17,15 @@ _DummyThread_ = __threading__._DummyThread
from gevent.local import local
from gevent.thread import start_new_thread as _start_new_thread, allocate_lock as _allocate_lock, get_ident as _get_ident
from gevent.hub import sleep as _sleep, getcurrent, PYPY
# Exports, prevent unused import warnings
local = local
start_new_thread = _start_new_thread
allocate_lock = _allocate_lock
_get_ident = _get_ident
_sleep = _sleep
getcurrent = getcurrent
Lock = _allocate_lock
......@@ -61,7 +72,7 @@ class _DummyThread(_DummyThread_):
_tstate_lock = None
def __init__(self):
#_DummyThread_.__init__(self)
#_DummyThread_.__init__(self) # pylint:disable=super-init-not-called
# It'd be nice to use a pattern like "greenlet-%d", but maybe somebody out
# there is checking thread names...
......@@ -88,12 +99,12 @@ class _DummyThread(_DummyThread_):
# when gevent.threading is imported before monkey patching or not at all
# XXX: This assumes that the import is happening in the "main" greenlet
if _get_ident() not in __threading__._active and len(__threading__._active) == 1:
k, v = next(iter(__threading__._active.items()))
del __threading__._active[k]
v._Thread__ident = _get_ident()
__threading__._active[_get_ident()] = v
del k
del v
_k, _v = next(iter(__threading__._active.items()))
del __threading__._active[_k]
_v._Thread__ident = _get_ident()
__threading__._active[_get_ident()] = _v
del _k
del _v
# Avoid printing an error on shutdown trying to remove the thread entry
# we just replaced if we're not fully monkey patched in
......@@ -101,6 +112,7 @@ if _get_ident() not in __threading__._active and len(__threading__._active) == 1
# defines __delitem__, shutdown hangs. Maybe due to something with the GC?
# XXX: This may be fixed in 2.6.1+
if not PYPY:
# pylint:disable=no-member
_MAIN_THREAD = __threading__._get_ident() if hasattr(__threading__, '_get_ident') else __threading__.get_ident()
class _active(dict):
......
......@@ -189,6 +189,7 @@ class ThreadPool(GroupMappingMixin):
self._size -= 1
def _worker(self):
# pylint:disable=too-many-branches
need_decrease = True
try:
while True:
......@@ -205,7 +206,7 @@ class ThreadPool(GroupMappingMixin):
func, args, kwargs, thread_result = task
try:
value = func(*args, **kwargs)
except:
except: # pylint:disable=bare-except
exc_info = getattr(sys, 'exc_info', None)
if exc_info is None:
return
......@@ -219,7 +220,7 @@ class ThreadPool(GroupMappingMixin):
del func, args, kwargs, thread_result, task
finally:
if sys is None:
return
return # pylint:disable=lost-exception
task_queue.task_done()
finally:
if need_decrease:
......@@ -230,6 +231,7 @@ class ThreadPool(GroupMappingMixin):
.. deprecated:: 1.1a2
Identical to :meth:`apply`; the ``expected_errors`` argument is ignored.
"""
# pylint:disable=unused-argument
# Deprecated but never documented. In the past, before
# self.apply() allowed all errors to be raised to the caller,
# expected_errors allowed a caller to specify a set of errors
......
......@@ -29,6 +29,7 @@ class _FakeTimer(object):
active = False
def start(self, *args, **kwargs):
# pylint:disable=unused-argument
raise AssertionError("non-expiring timer cannot be started")
def stop(self):
......
......@@ -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):
"""
......
......@@ -9,7 +9,7 @@ pipelining, and not supporting SSL.
Use :mod:`gevent.pywsgi`
"""
from gevent.pywsgi import *
from gevent.pywsgi import * # pylint:disable=wildcard-import
import gevent.pywsgi as _pywsgi
__all__ = _pywsgi.__all__
del _pywsgi
......@@ -20,6 +20,8 @@
# THE SOFTWARE.
# package is named greentest, not test, so it won't be confused with test in stdlib
# pylint:disable=broad-except,unused-argument,no-member,too-many-branches,unused-variable
# pylint:disable=attribute-defined-outside-init,abstract-method
import sys
import types
import unittest
......@@ -83,7 +85,7 @@ if sys.version_info[0] == 2:
PY2 = True
NON_APPLICABLE_SUFFIXES.append('3')
if (sys.version_info[1] < 7
or (sys.version_info[1] == 7 and sys.version_info[2] < 9)):
or (sys.version_info[1] == 7 and sys.version_info[2] < 9)):
# Python 2, < 2.7.9
NON_APPLICABLE_SUFFIXES.append('279')
if sys.platform.startswith('win'):
......@@ -305,7 +307,11 @@ class TestCaseMetaClass(type):
# b) fatal error check
# c) restore the hub's error handler (see expect_one_error)
# d) totalrefcount check
def __new__(meta, classname, bases, classDict):
def __new__(cls, classname, bases, classDict):
# pylint and pep8 fight over what this should be called (mcs or cls).
# pylint gets it right, but we cant scope disable pep8, so we go with
# its convention.
# pylint: disable=bad-mcs-classmethod-argument
timeout = classDict.get('__timeout__', 'NONE')
if timeout == 'NONE':
timeout = getattr(bases[0], '__timeout__', None)
......@@ -327,7 +333,7 @@ class TestCaseMetaClass(type):
if check_totalrefcount:
value = wrap_refcount(value)
classDict[key] = value
return type.__new__(meta, classname, bases, classDict)
return type.__new__(cls, classname, bases, classDict)
class TestCase(TestCaseMetaClass("NewBase", (BaseTestCase,), {})):
......
# pylint:disable=missing-docstring,invalid-name
from __future__ import print_function
import sys
import os
......@@ -46,9 +47,9 @@ test_patched_threading.*
def make_re(tests):
tests = [x.strip().replace('\.', '\\.').replace('*', '.*?') for x in tests.split('\n') if x.strip()]
tests = re.compile('^%s$' % '|'.join(tests))
return tests
tests = [x.strip().replace(r'\.', r'\\.').replace('*', '.*?')
for x in tests.split('\n') if x.strip()]
return re.compile('^%s$' % '|'.join(tests))
no_switch_tests = make_re(no_switch_tests)
......@@ -66,6 +67,9 @@ def get_switch_expected(fullname):
>>> get_switch_expected("test_patched_httplib.BasicTest.test_bad_status_repr")
False
"""
# certain pylint versions mistype the globals as
# str, not re.
# pylint:disable=no-member
if ignore_switch_tests.match(fullname) is not None:
return None
if no_switch_tests.match(fullname) is not None:
......@@ -280,7 +284,7 @@ if hasattr(sys, 'pypy_version_info'):
# _execut_child)
]
import cffi
import cffi # pylint:disable=import-error,useless-suppression
if cffi.__version_info__ < (1, 2, 0):
disabled_tests += [
'test_signal.InterProcessSignalTests.test_main',
......
......@@ -254,6 +254,12 @@ class TestChannel(TestCase):
channel.task_done()
assert channel.unfinished_tasks == 0, channel.unfinished_tasks
def test_iterable(self):
channel = queue.Channel()
gevent.spawn(channel.put, StopIteration)
r = list(channel)
self.assertEqual(r, [])
class TestNoWait(TestCase):
......
......@@ -34,6 +34,7 @@ IGNORE_COVERAGE = [
def run_many(tests, expected=(), failfast=False):
# pylint:disable=too-many-locals
global NWORKERS
start = time.time()
total = 0
......@@ -71,7 +72,7 @@ def run_many(tests, expected=(), failfast=False):
while reap() > 0:
time.sleep(0.1)
def spawn(args, kwargs):
def spawn(args, kwargs): # pylint:disable=unused-argument
while True:
if reap() < NWORKERS:
r = pool.apply_async(run_one, (cmd, ), options or {})
......@@ -117,7 +118,7 @@ def run_many(tests, expected=(), failfast=False):
def discover(tests=None, ignore=(), coverage=False):
if isinstance(ignore, six.string_types):
ignore = load_list_from_file(ignore)
ignore = set(load_list_from_file(ignore))
ignore = set(ignore or ())
if coverage:
......@@ -194,6 +195,7 @@ def format_seconds(seconds):
def report(total, failed, passed, exit=True, took=None, expected=None):
# pylint:disable=redefined-builtin,too-many-branches
runtimelog = util.runtimelog
if runtimelog:
log('\nLongest-running tests:')
......@@ -253,7 +255,8 @@ def print_list(lst):
def main():
import optparse
# FIXME: transition to argparse
import optparse # pylint:disable=deprecated-module
parser = optparse.OptionParser()
parser.add_option('--ignore')
parser.add_option('--discover', action='store_true')
......
......@@ -7,6 +7,7 @@ import threading
import subprocess
import time
# pylint: disable=broad-except,attribute-defined-outside-init
runtimelog = []
MIN_RUNTIME = 1.0
......
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