diff --git a/newrelic/hooks/framework_bottle.py b/newrelic/hooks/framework_bottle.py index 99caa844fd..5635fa782c 100644 --- a/newrelic/hooks/framework_bottle.py +++ b/newrelic/hooks/framework_bottle.py @@ -18,14 +18,21 @@ import functools -from newrelic.api.function_trace import (FunctionTrace, FunctionTraceWrapper, - wrap_function_trace) +from newrelic.api.function_trace import ( + FunctionTrace, + FunctionTraceWrapper, + wrap_function_trace, +) from newrelic.api.transaction import current_transaction from newrelic.api.wsgi_application import wrap_wsgi_application from newrelic.common.object_names import callable_name -from newrelic.common.object_wrapper import (wrap_out_function, - function_wrapper, ObjectProxy, wrap_object_attribute, - wrap_function_wrapper) +from newrelic.common.object_wrapper import ( + ObjectProxy, + function_wrapper, + wrap_function_wrapper, + wrap_object_attribute, + wrap_out_function, +) module_bottle = None @@ -34,17 +41,17 @@ def status_code(exc, value, tb): # The HTTPError class derives from HTTPResponse and so we do not # need to check for it seperately as isinstance() will pick it up. - if isinstance(value, module_bottle.HTTPResponse): - if hasattr(value, 'status_code'): + if isinstance(value, module_bottle.HTTPResponse): # pragma: no cover + if hasattr(value, "status_code"): return value.status_code - elif hasattr(value, 'status'): + elif hasattr(value, "status"): return value.status - elif hasattr(value, 'http_status_code'): + elif hasattr(value, "http_status_code"): return value.http_status_code def should_ignore(exc, value, tb): - if hasattr(module_bottle, 'RouteReset'): + if hasattr(module_bottle, "RouteReset"): if isinstance(value, module_bottle.RouteReset): return True @@ -113,8 +120,7 @@ def get(self, status, default=None): transaction.set_transaction_name(name, priority=1) handler = FunctionTraceWrapper(handler, name=name) else: - transaction.set_transaction_name(str(status), - group='StatusCode', priority=1) + transaction.set_transaction_name(str(status), group="StatusCode", priority=1) return handler or default @@ -140,43 +146,39 @@ def instrument_bottle(module): global module_bottle module_bottle = module - framework_details = ('Bottle', getattr(module, '__version__')) - - if hasattr(module.Bottle, 'wsgi'): # version >= 0.9 - wrap_wsgi_application(module, 'Bottle.wsgi', - framework=framework_details) - elif hasattr(module.Bottle, '__call__'): # version < 0.9 - wrap_wsgi_application(module, 'Bottle.__call__', - framework=framework_details) - - if (hasattr(module, 'Route') and - hasattr(module.Route, '_make_callback')): # version >= 0.10 - wrap_out_function(module, 'Route._make_callback', - output_wrapper_Route_make_callback) - elif hasattr(module.Bottle, '_match'): # version >= 0.9 - wrap_out_function(module, 'Bottle._match', - output_wrapper_Bottle_match) - elif hasattr(module.Bottle, 'match_url'): # version < 0.9 - wrap_out_function(module, 'Bottle.match_url', - output_wrapper_Bottle_match) - - wrap_object_attribute(module, 'Bottle.error_handler', - proxy_Bottle_error_handler) - - if hasattr(module, 'auth_basic'): - wrap_function_wrapper(module, 'auth_basic', wrapper_auth_basic) - - if hasattr(module, 'SimpleTemplate'): - wrap_function_trace(module, 'SimpleTemplate.render') - - if hasattr(module, 'MakoTemplate'): - wrap_function_trace(module, 'MakoTemplate.render') - - if hasattr(module, 'CheetahTemplate'): - wrap_function_trace(module, 'CheetahTemplate.render') - - if hasattr(module, 'Jinja2Template'): - wrap_function_trace(module, 'Jinja2Template.render') - - if hasattr(module, 'SimpleTALTemplate'): - wrap_function_trace(module, 'SimpleTALTemplate.render') + framework_details = ("Bottle", getattr(module, "__version__")) + # version >= 0.9 + if hasattr(module.Bottle, "wsgi"): # pragma: no cover + wrap_wsgi_application(module, "Bottle.wsgi", framework=framework_details) + # version < 0.9 + elif hasattr(module.Bottle, "__call__"): # pragma: no cover + wrap_wsgi_application(module, "Bottle.__call__", framework=framework_details) + # version >= 0.10 + if hasattr(module, "Route") and hasattr(module.Route, "_make_callback"): # pragma: no cover + wrap_out_function(module, "Route._make_callback", output_wrapper_Route_make_callback) + # version >= 0.9 + elif hasattr(module.Bottle, "_match"): # pragma: no cover + wrap_out_function(module, "Bottle._match", output_wrapper_Bottle_match) + # version < 0.9 + elif hasattr(module.Bottle, "match_url"): # pragma: no cover + wrap_out_function(module, "Bottle.match_url", output_wrapper_Bottle_match) + + wrap_object_attribute(module, "Bottle.error_handler", proxy_Bottle_error_handler) + + if hasattr(module, "auth_basic"): + wrap_function_wrapper(module, "auth_basic", wrapper_auth_basic) + + if hasattr(module, "SimpleTemplate"): + wrap_function_trace(module, "SimpleTemplate.render") + + if hasattr(module, "MakoTemplate"): + wrap_function_trace(module, "MakoTemplate.render") + + if hasattr(module, "CheetahTemplate"): + wrap_function_trace(module, "CheetahTemplate.render") + + if hasattr(module, "Jinja2Template"): + wrap_function_trace(module, "Jinja2Template.render") + + if hasattr(module, "SimpleTALTemplate"): # pragma: no cover + wrap_function_trace(module, "SimpleTALTemplate.render") diff --git a/newrelic/hooks/framework_pyramid.py b/newrelic/hooks/framework_pyramid.py index efe3c4468e..996ebb372d 100644 --- a/newrelic/hooks/framework_pyramid.py +++ b/newrelic/hooks/framework_pyramid.py @@ -48,8 +48,11 @@ from newrelic.api.transaction import current_transaction from newrelic.api.wsgi_application import wrap_wsgi_application from newrelic.common.object_names import callable_name -from newrelic.common.object_wrapper import (FunctionWrapper, wrap_out_function, - wrap_function_wrapper) +from newrelic.common.object_wrapper import ( + FunctionWrapper, + wrap_function_wrapper, + wrap_out_function, +) def instrument_pyramid_router(module): @@ -57,16 +60,17 @@ def instrument_pyramid_router(module): try: import pkg_resources - pyramid_version = pkg_resources.get_distribution('pyramid').version + + pyramid_version = pkg_resources.get_distribution("pyramid").version except Exception: pass - wrap_wsgi_application( - module, 'Router.__call__', framework=('Pyramid', pyramid_version)) + wrap_wsgi_application(module, "Router.__call__", framework=("Pyramid", pyramid_version)) def status_code(exc, value, tb): from pyramid.httpexceptions import HTTPException + # Ignore certain exceptions based on HTTP status codes. if isinstance(value, HTTPException): @@ -75,6 +79,7 @@ def status_code(exc, value, tb): def should_ignore(exc, value, tb): from pyramid.exceptions import PredicateMismatch + # Always ignore PredicateMismatch as it is raised by views to force # subsequent views to be consulted when multi views are being used. # It isn't therefore strictly an error as such as a subsequent view @@ -100,9 +105,7 @@ def view_handler_wrapper(wrapped, instance, args, kwargs): # set exception views to priority=1 so they won't take precedence over # the original view callable - transaction.set_transaction_name( - name, - priority=1 if args and isinstance(args[0], Exception) else 2) + transaction.set_transaction_name(name, priority=1 if args and isinstance(args[0], Exception) else 2) with FunctionTrace(name, source=view_callable) as trace: try: @@ -114,7 +117,7 @@ def view_handler_wrapper(wrapped, instance, args, kwargs): def wrap_view_handler(mapped_view): - if hasattr(mapped_view, '_nr_wrapped'): + if hasattr(mapped_view, "_nr_wrapped"): # pragma: no cover return mapped_view else: wrapped = FunctionWrapper(mapped_view, view_handler_wrapper) @@ -157,7 +160,7 @@ def _wrapper(context, request): return wrapper(context, request) finally: attr = instance.attr - inst = getattr(request, '__view__', None) + inst = getattr(request, "__view__", None) if inst is not None: if attr: handler = getattr(inst, attr) @@ -166,7 +169,7 @@ def _wrapper(context, request): tracer.name = name tracer.add_code_level_metrics(handler) else: - method = getattr(inst, '__call__') + method = getattr(inst, "__call__") if method: name = callable_name(method) transaction.set_transaction_name(name, priority=2) @@ -180,22 +183,21 @@ def instrument_pyramid_config_views(module): # Location of the ViewDeriver class changed from pyramid.config to # pyramid.config.views so check if present before trying to update. - if hasattr(module, 'ViewDeriver'): - wrap_out_function(module, 'ViewDeriver.__call__', wrap_view_handler) - elif hasattr(module, 'Configurator'): - wrap_out_function(module, 'Configurator._derive_view', - wrap_view_handler) + if hasattr(module, "ViewDeriver"): # pragma: no cover + wrap_out_function(module, "ViewDeriver.__call__", wrap_view_handler) + elif hasattr(module, "Configurator"): + wrap_out_function(module, "Configurator._derive_view", wrap_view_handler) - if hasattr(module, 'DefaultViewMapper'): + if hasattr(module, "DefaultViewMapper"): module.DefaultViewMapper.map_class_requestonly = FunctionWrapper( - module.DefaultViewMapper.map_class_requestonly, - default_view_mapper_wrapper) + module.DefaultViewMapper.map_class_requestonly, default_view_mapper_wrapper + ) module.DefaultViewMapper.map_class_native = FunctionWrapper( - module.DefaultViewMapper.map_class_native, - default_view_mapper_wrapper) + module.DefaultViewMapper.map_class_native, default_view_mapper_wrapper + ) def instrument_pyramid_config_tweens(module): - wrap_function_wrapper(module, 'Tweens.add_explicit', wrap_add_tween) + wrap_function_wrapper(module, "Tweens.add_explicit", wrap_add_tween) - wrap_function_wrapper(module, 'Tweens.add_implicit', wrap_add_tween) + wrap_function_wrapper(module, "Tweens.add_implicit", wrap_add_tween) diff --git a/newrelic/hooks/logger_loguru.py b/newrelic/hooks/logger_loguru.py index 9e7ed3eaef..dc9843b204 100644 --- a/newrelic/hooks/logger_loguru.py +++ b/newrelic/hooks/logger_loguru.py @@ -134,7 +134,7 @@ def patch_loguru_logger(logger): if not hasattr(logger._core, "_nr_instrumented"): logger.add(_nr_log_forwarder, format="{message}") logger._core._nr_instrumented = True - elif not hasattr(logger, "_nr_instrumented"): + elif not hasattr(logger, "_nr_instrumented"): # pragma: no cover for _, handler in six.iteritems(logger._handlers): if handler._writer is _nr_log_forwarder: logger._nr_instrumented = True diff --git a/newrelic/hooks/messagebroker_pika.py b/newrelic/hooks/messagebroker_pika.py index cecc1b9343..d6120c10de 100644 --- a/newrelic/hooks/messagebroker_pika.py +++ b/newrelic/hooks/messagebroker_pika.py @@ -36,7 +36,6 @@ def _add_consume_rabbitmq_trace(transaction, method, properties, nr_start_time, queue_name=None): - routing_key = None if hasattr(method, "routing_key"): routing_key = method.routing_key @@ -197,7 +196,7 @@ def _wrap_basic_get_Channel(wrapper, queue, callback, *args, **kwargs): return queue, args, kwargs -def _wrap_basic_get_Channel_old(wrapper, callback=None, queue="", *args, **kwargs): +def _wrap_basic_get_Channel_old(wrapper, callback=None, queue="", *args, **kwargs): # pragma: no cover if callback is not None: callback = wrapper(callback) args = (callback, queue) + args @@ -368,7 +367,6 @@ def callback_wrapper(wrapped, instance, args, kwargs): correlation_id=correlation_id, source=wrapped, ) as mt: - # Improve transaction naming _new_txn_name = "RabbitMQ/Exchange/%s/%s" % (exchange, name) mt.set_transaction_name(_new_txn_name, group="Message") @@ -404,7 +402,7 @@ def instrument_pika_adapters(module): version = tuple(int(num) for num in pika.__version__.split(".", 1)[0]) - if version[0] < 1: + if version[0] < 1: # pragma: no cover wrap_consume = _wrap_basic_consume_BlockingChannel_old else: wrap_consume = _wrap_basic_consume_Channel @@ -426,7 +424,7 @@ def instrument_pika_channel(module): version = tuple(int(num) for num in pika.__version__.split(".", 1)[0]) - if version[0] < 1: + if version[0] < 1: # pragma: no cover wrap_consume = _wrap_basic_consume_Channel_old wrap_get = _wrap_basic_get_Channel_old else: diff --git a/tox.ini b/tox.ini index 6abb9c0a9a..76eba20c58 100644 --- a/tox.ini +++ b/tox.ini @@ -47,14 +47,11 @@ skip_missing_interpreters = false envlist = python-adapter_cheroot-{py27,py37,py38,py39,py310,py311}, python-adapter_daphne-{py37,py38,py39,py310,py311}-daphnelatest, - python-adapter_daphne-py38-daphne{0204,0205}, python-adapter_gevent-{py27,py37,py38,py310,py311}, python-adapter_gunicorn-{py37,py38,py39,py310,py311}-aiohttp3-gunicornlatest, python-adapter_hypercorn-{py37,py38,py39,py310,py311}-hypercornlatest, python-adapter_hypercorn-py38-hypercorn{0010,0011,0012,0013}, - python-adapter_uvicorn-py37-uvicorn03, - python-adapter_uvicorn-{py37,py38,py39,py310,py311}-uvicornlatest, - python-adapter_waitress-{py37,py38,py39}-waitress010404, + python-adapter_uvicorn-{py37,py38,py39,py310,py311}-uvicorn{014,latest}, python-adapter_waitress-{py37,py38,py39,py310}-waitress02, python-adapter_waitress-{py37,py38,py39,py310,py311}-waitresslatest, python-agent_features-{py27,py37,py38,py39,py310,py311}-{with,without}_extensions, @@ -113,10 +110,7 @@ envlist = python-framework_aiohttp-{py37,py38,py39,py310,py311,pypy38}-aiohttp03, python-framework_ariadne-{py37,py38,py39,py310,py311}-ariadnelatest, python-framework_ariadne-py37-ariadne{0011,0012,0013}, - python-framework_bottle-py27-bottle{0008,0009,0010}, - python-framework_bottle-{py27,py37,py38,py39,pypy38}-bottle{0011,0012}, - python-framework_bottle-{py310,py311}-bottle0012, - python-framework_bottle-pypy27-bottle{0008,0009,0010,0011,0012}, + python-framework_bottle-{py27,py37,py38,py39,py310,py311,pypy27,pypy38}-bottle0012, ; CherryPy still uses inspect.getargspec, deprecated in favor of inspect.getfullargspec. Not supported in 3.11 python-framework_cherrypy-{py37,py38,py39,py310,py311,pypy38}-CherryPylatest, python-framework_django-{pypy27,py27}-Django0103, @@ -136,10 +130,9 @@ envlist = python-framework_graphql-py37-graphql{0300,0301,0302}, grpc-framework_grpc-py27-grpc0125, grpc-framework_grpc-{py37,py38,py39,py310,py311}-grpclatest, - python-framework_pyramid-{pypy27,py27,py38}-Pyramid0104, python-framework_pyramid-{pypy27,py27,pypy38,py37,py38,py39,py310,py311}-Pyramid0110-cornice, python-framework_pyramid-{py37,py38,py39,py310,py311,pypy38}-Pyramidlatest, - python-framework_sanic-{py38,pypy38}-sanic{190301,1906,1912,200904,210300,2109,2112,2203,2290}, + python-framework_sanic-{py38,pypy38}-sanic{200904,210300,2109,2112,2203,2290}, python-framework_sanic-{py37,py38,py39,py310,py311,pypy38}-saniclatest, python-framework_starlette-{py310,pypy38}-starlette{0014,0015,0019,0028}, python-framework_starlette-{py37,py38}-starlette{002001}, @@ -147,18 +140,17 @@ envlist = python-framework_strawberry-{py37,py38,py39,py310,py311}-strawberrylatest, python-logger_logging-{py27,py37,py38,py39,py310,py311,pypy27,pypy38}, python-logger_loguru-{py37,py38,py39,py310,py311,pypy38}-logurulatest, - python-logger_loguru-py39-loguru{06,05,04,03}, + python-logger_loguru-py39-loguru{06,05}, python-logger_structlog-{py37,py38,py39,py310,py311,pypy38}-structloglatest, python-framework_tornado-{py38,py39,py310,py311}-tornadolatest, python-framework_tornado-{py38,py39,py310,py311}-tornadomaster, - rabbitmq-messagebroker_pika-{py27,py37,py38,py39,pypy27,pypy38}-pika0.13, rabbitmq-messagebroker_pika-{py37,py38,py39,py310,py311,pypy38}-pikalatest, kafka-messagebroker_confluentkafka-{py37,py38,py39,py310,py311}-confluentkafkalatest, kafka-messagebroker_confluentkafka-{py27,py39}-confluentkafka{0107,0106}, ; confluent-kafka had a bug in 1.8.2's setup.py file which was incompatible with 2.7. kafka-messagebroker_confluentkafka-{py39}-confluentkafka{0108}, kafka-messagebroker_kafkapython-{pypy27,py27,py37,py38,pypy38}-kafkapythonlatest, - kafka-messagebroker_kafkapython-{py27,py38}-kafkapython{020001,020000,0104}, + kafka-messagebroker_kafkapython-{py27,py38}-kafkapython{020001,020000}, python-template_genshi-{py27,py37,py311}-genshilatest python-template_jinja2-{py37,py311}-jinja2latest python-template_mako-{py27,py37,py310,py311} @@ -175,8 +167,6 @@ deps = # Test Suite Dependencies adapter_cheroot: cheroot adapter_daphne-daphnelatest: daphne - adapter_daphne-daphne0205: daphne<2.6 - adapter_daphne-daphne0204: daphne<2.5 adapter_gevent: WSGIProxy2 adapter_gevent: gevent adapter_gevent: urllib3 @@ -189,12 +179,10 @@ deps = adapter_hypercorn-hypercorn0012: hypercorn<0.13 adapter_hypercorn-hypercorn0011: hypercorn<0.12 adapter_hypercorn-hypercorn0010: hypercorn<0.11 - adapter_uvicorn-uvicorn03: uvicorn<0.4 adapter_uvicorn-uvicorn014: uvicorn<0.15 adapter_uvicorn-uvicornlatest: uvicorn adapter_uvicorn: typing-extensions adapter_waitress: WSGIProxy2 - adapter_waitress-waitress010404: waitress<1.4.5 adapter_waitress-waitress02: waitress<2.1 adapter_waitress-waitresslatest: waitress agent_features: beautifulsoup4 @@ -273,10 +261,6 @@ deps = framework_ariadne-ariadne0011: ariadne<0.12 framework_ariadne-ariadne0012: ariadne<0.13 framework_ariadne-ariadne0013: ariadne<0.14 - framework_bottle-bottle0008: bottle<0.9.0 - framework_bottle-bottle0009: bottle<0.10.0 - framework_bottle-bottle0010: bottle<0.11.0 - framework_bottle-bottle0011: bottle<0.12.0 framework_bottle-bottle0012: bottle<0.13.0 framework_bottle: jinja2<3.1 framework_bottle: markupsafe<2.1 @@ -320,13 +304,8 @@ deps = protobuf04: protobuf<5 framework_pyramid: routes framework_pyramid-cornice: cornice!=5.0.0 - framework_pyramid-Pyramid0104: Pyramid<1.5 framework_pyramid-Pyramid0110: Pyramid<1.11 framework_pyramid-Pyramidlatest: Pyramid - framework_sanic-sanic1812: sanic<18.13 - framework_sanic-sanic190301: sanic<19.3.2 - framework_sanic-sanic1906: sanic<19.7 - framework_sanic-sanic1912: sanic<19.13 framework_sanic-sanic200904: sanic<20.9.5 framework_sanic-sanic210300: sanic<21.3.1 framework_sanic-sanic2109: sanic<21.10 @@ -334,8 +313,7 @@ deps = framework_sanic-sanic2203: sanic<22.4 framework_sanic-sanic2290: sanic<22.9.1 framework_sanic-saniclatest: sanic - framework_sanic-sanic{1812,190301,1906}: aiohttp - framework_sanic-sanic{1812,190301,1906,1912,200904,210300,2109,2112,2203,2290}: websockets<11 + framework_sanic-sanic{200904,210300,2109,2112,2203,2290}: websockets<11 ; For test_exception_in_middleware test, anyio is used: ; https://github.com/encode/starlette/pull/1157 ; but anyiolatest creates breaking changes to our tests @@ -356,10 +334,7 @@ deps = logger_loguru-logurulatest: loguru logger_loguru-loguru06: loguru<0.7 logger_loguru-loguru05: loguru<0.6 - logger_loguru-loguru04: loguru<0.5 - logger_loguru-loguru03: loguru<0.4 logger_structlog-structloglatest: structlog - messagebroker_pika-pika0.13: pika<0.14 messagebroker_pika-pikalatest: pika messagebroker_pika: tornado<5 messagebroker_pika-{py27,pypy27}: enum34 @@ -370,7 +345,6 @@ deps = messagebroker_kafkapython-kafkapythonlatest: kafka-python messagebroker_kafkapython-kafkapython020001: kafka-python<2.0.2 messagebroker_kafkapython-kafkapython020000: kafka-python<2.0.1 - messagebroker_kafkapython-kafkapython0104: kafka-python<1.5 template_genshi-genshilatest: genshi template_jinja2-jinja2latest: Jinja2 template_mako: mako