diff --git a/aiohttp/client.py b/aiohttp/client.py index be8486af7ab..4f6c6e78a01 100644 --- a/aiohttp/client.py +++ b/aiohttp/client.py @@ -25,8 +25,8 @@ from .connector import * # noqa from .connector import TCPConnector from .cookiejar import CookieJar -from .helpers import (PY_36, CeilTimeout, TimeoutHandle, proxies_from_env, - sentinel, strip_auth_from_url) +from .helpers import (DEBUG, PY_36, CeilTimeout, TimeoutHandle, + proxies_from_env, sentinel, strip_auth_from_url) from .http import WS_KEY, WebSocketReader, WebSocketWriter from .http_websocket import WSHandshakeError, ws_ext_gen, ws_ext_parse from .streams import FlowControlDataQueue @@ -149,13 +149,14 @@ def __init_subclass__(cls): DeprecationWarning, stacklevel=2) - def __setattr__(self, name, val): - if name not in self.ATTRS: - warnings.warn("Setting custom ClientSession.{} attribute " - "is discouraged".format(name), - DeprecationWarning, - stacklevel=2) - super().__setattr__(name, val) + if DEBUG: + def __setattr__(self, name, val): + if name not in self.ATTRS: + warnings.warn("Setting custom ClientSession.{} attribute " + "is discouraged".format(name), + DeprecationWarning, + stacklevel=2) + super().__setattr__(name, val) def __del__(self, _warnings=warnings): if not self.closed: diff --git a/aiohttp/helpers.py b/aiohttp/helpers.py index 0dbce4a9362..ff43b7823ab 100644 --- a/aiohttp/helpers.py +++ b/aiohttp/helpers.py @@ -43,6 +43,13 @@ sentinel = object() NO_EXTENSIONS = bool(os.environ.get('AIOHTTP_NO_EXTENSIONS')) +# N.B. sys.flags.dev_mode is available on Python 3.7+, use getattr +# for compatibility with older versions +DEBUG = (getattr(sys.flags, 'dev_mode', False) or + (not sys.flags.ignore_environment and + bool(os.environ.get('PYTHONASYNCIODEBUG')))) + + CHAR = set(chr(i) for i in range(0, 128)) CTL = set(chr(i) for i in range(0, 32)) | {chr(127), } SEPARATORS = {'(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', @@ -52,6 +59,8 @@ coroutines = asyncio.coroutines old_debug = coroutines._DEBUG + +# prevent "coroutine noop was never awaited" warning. coroutines._DEBUG = False diff --git a/aiohttp/web_app.py b/aiohttp/web_app.py index 20f52eb5254..5bd01639e47 100644 --- a/aiohttp/web_app.py +++ b/aiohttp/web_app.py @@ -6,7 +6,7 @@ from . import hdrs from .abc import AbstractAccessLogger, AbstractMatchInfo, AbstractRouter from .frozenlist import FrozenList -from .helpers import AccessLogger +from .helpers import DEBUG, AccessLogger from .log import web_logger from .signals import Signal from .web_middlewares import _fix_request_current_app @@ -71,13 +71,14 @@ def __init_subclass__(cls): DeprecationWarning, stacklevel=2) - def __setattr__(self, name, val): - if name not in self.ATTRS: - warnings.warn("Setting custom web.Application.{} attribute " - "is discouraged".format(name), - DeprecationWarning, - stacklevel=2) - super().__setattr__(name, val) + if DEBUG: + def __setattr__(self, name, val): + if name not in self.ATTRS: + warnings.warn("Setting custom web.Application.{} attribute " + "is discouraged".format(name), + DeprecationWarning, + stacklevel=2) + super().__setattr__(name, val) # MutableMapping API diff --git a/aiohttp/web_request.py b/aiohttp/web_request.py index 9ca2b4247fe..6e9d27827b0 100644 --- a/aiohttp/web_request.py +++ b/aiohttp/web_request.py @@ -19,7 +19,7 @@ from yarl import URL from . import hdrs, multipart -from .helpers import HeadersMixin, reify, sentinel +from .helpers import DEBUG, HeadersMixin, reify, sentinel from .streams import EmptyStreamReader from .web_exceptions import HTTPRequestEntityTooLarge @@ -610,14 +610,15 @@ def __init__(self, *args, **kwargs): # or information about traversal lookup self._match_info = None # initialized after route resolving - def __setattr__(self, name, val): - if name not in self.ATTRS: - warnings.warn("Setting custom {}.{} attribute " - "is discouraged".format(self.__class__.__name__, - name), - DeprecationWarning, - stacklevel=2) - super().__setattr__(name, val) + if DEBUG: + def __setattr__(self, name, val): + if name not in self.ATTRS: + warnings.warn("Setting custom {}.{} attribute " + "is discouraged".format(self.__class__.__name__, + name), + DeprecationWarning, + stacklevel=2) + super().__setattr__(name, val) def clone(self, *, method=sentinel, rel_url=sentinel, headers=sentinel, scheme=sentinel, host=sentinel, diff --git a/tests/test_client_session.py b/tests/test_client_session.py index a6bde916fed..ab4512c3521 100644 --- a/tests/test_client_session.py +++ b/tests/test_client_session.py @@ -16,7 +16,7 @@ from aiohttp.client import ClientSession from aiohttp.client_reqrep import ClientRequest from aiohttp.connector import BaseConnector, TCPConnector -from aiohttp.helpers import PY_36 +from aiohttp.helpers import DEBUG, PY_36 @pytest.fixture @@ -640,6 +640,8 @@ class A(ClientSession): pass +@pytest.mark.skipif(not DEBUG, + reason="The check is applied in DEBUG mode only") def test_client_session_custom_attr(loop): session = ClientSession(loop=loop) with pytest.warns(DeprecationWarning): diff --git a/tests/test_web_app.py b/tests/test_web_app.py index 3d807d5b576..5fbbcb81bdd 100644 --- a/tests/test_web_app.py +++ b/tests/test_web_app.py @@ -6,7 +6,7 @@ from aiohttp import log, web from aiohttp.abc import AbstractAccessLogger, AbstractRouter -from aiohttp.helpers import PY_36 +from aiohttp.helpers import DEBUG, PY_36 from aiohttp.test_utils import make_mocked_coro @@ -256,6 +256,8 @@ class A(web.Application): pass +@pytest.mark.skipif(not DEBUG, + reason="The check is applied in DEBUG mode only") def test_app_custom_attr(): app = web.Application() with pytest.warns(DeprecationWarning): diff --git a/tests/test_web_request.py b/tests/test_web_request.py index 4122d2e17e0..56a02cc46c1 100644 --- a/tests/test_web_request.py +++ b/tests/test_web_request.py @@ -7,6 +7,7 @@ from yarl import URL from aiohttp import HttpVersion +from aiohttp.helpers import DEBUG from aiohttp.streams import StreamReader from aiohttp.test_utils import make_mocked_request from aiohttp.web import HTTPRequestEntityTooLarge @@ -601,6 +602,8 @@ def test_clone_remote(): assert req2.remote == '11.11.11.11' +@pytest.mark.skipif(not DEBUG, + reason="The check is applied in DEBUG mode only") def test_request_custom_attr(): req = make_mocked_request('GET', '/') with pytest.warns(DeprecationWarning):