Skip to content

Commit

Permalink
Prevent wild assignment in DEBUG mode only (#2860)
Browse files Browse the repository at this point in the history
For sake of performance
  • Loading branch information
asvetlov authored Mar 21, 2018
1 parent 037ccbc commit 3ee8a5e
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 28 deletions.
19 changes: 10 additions & 9 deletions aiohttp/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
9 changes: 9 additions & 0 deletions aiohttp/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {'(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']',
Expand All @@ -52,6 +59,8 @@

coroutines = asyncio.coroutines
old_debug = coroutines._DEBUG

# prevent "coroutine noop was never awaited" warning.
coroutines._DEBUG = False


Expand Down
17 changes: 9 additions & 8 deletions aiohttp/web_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
19 changes: 10 additions & 9 deletions aiohttp/web_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -632,14 +632,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,
Expand Down
4 changes: 3 additions & 1 deletion tests/test_client_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down
4 changes: 3 additions & 1 deletion tests/test_web_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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):
Expand Down
3 changes: 3 additions & 0 deletions tests/test_web_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down

0 comments on commit 3ee8a5e

Please sign in to comment.