Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent wild assignment in DEBUG mode only #2860

Merged
merged 1 commit into from
Mar 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -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,
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