From d143203e741163972ce7c726b8e792ad3c0e8e7d Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Wed, 29 Jan 2020 16:27:23 +0100 Subject: [PATCH] chord(flake8,black): ignore W504 and E231 not respected by black black does not respect those error codes and therefore they should be ignored. It does support W503 so that one should be included. This patch therefore black-ifies the files that do not respect W503. --- ddtrace/contrib/django/middleware.py | 68 +++--- ddtrace/contrib/grpc/client_interceptor.py | 51 ++-- ddtrace/contrib/requests/connection.py | 51 ++-- pyproject.toml | 183 ++++++++++++++- tests/contrib/dogpile_cache/test_tracing.py | 76 +++--- tests/contrib/pyramid/utils.py | 247 ++++++++++---------- tests/internal/test_writer.py | 109 +++++---- tests/opentracer/test_tracer.py | 244 +++++++++---------- tests/propagation/test_http.py | 38 ++- tox.ini | 3 +- 10 files changed, 601 insertions(+), 469 deletions(-) diff --git a/ddtrace/contrib/django/middleware.py b/ddtrace/contrib/django/middleware.py index 6e71d200799..8a0539a75bb 100644 --- a/ddtrace/contrib/django/middleware.py +++ b/ddtrace/contrib/django/middleware.py @@ -17,33 +17,33 @@ try: from django.utils.deprecation import MiddlewareMixin + MiddlewareClass = MiddlewareMixin except ImportError: MiddlewareClass = object log = get_logger(__name__) -EXCEPTION_MIDDLEWARE = 'ddtrace.contrib.django.TraceExceptionMiddleware' -TRACE_MIDDLEWARE = 'ddtrace.contrib.django.TraceMiddleware' -MIDDLEWARE = 'MIDDLEWARE' -MIDDLEWARE_CLASSES = 'MIDDLEWARE_CLASSES' +EXCEPTION_MIDDLEWARE = "ddtrace.contrib.django.TraceExceptionMiddleware" +TRACE_MIDDLEWARE = "ddtrace.contrib.django.TraceMiddleware" +MIDDLEWARE = "MIDDLEWARE" +MIDDLEWARE_CLASSES = "MIDDLEWARE_CLASSES" # Default views list available from: # https://github.com/django/django/blob/38e2fdadfd9952e751deed662edf4c496d238f28/django/views/defaults.py # DEV: Django doesn't call `process_view` when falling back to one of these internal error handling views # DEV: We only use these names when `span.resource == 'unknown'` and we have one of these status codes _django_default_views = { - 400: 'django.views.defaults.bad_request', - 403: 'django.views.defaults.permission_denied', - 404: 'django.views.defaults.page_not_found', - 500: 'django.views.defaults.server_error', + 400: "django.views.defaults.bad_request", + 403: "django.views.defaults.permission_denied", + 404: "django.views.defaults.page_not_found", + 500: "django.views.defaults.server_error", } def _analytics_enabled(): return ( - (config.analytics_enabled and settings.ANALYTICS_ENABLED is not False) or - settings.ANALYTICS_ENABLED is True + (config.analytics_enabled and settings.ANALYTICS_ENABLED is not False) or settings.ANALYTICS_ENABLED is True ) and settings.ANALYTICS_SAMPLE_RATE is not None @@ -87,6 +87,7 @@ class InstrumentationMixin(MiddlewareClass): """ Useful mixin base class for tracing middlewares """ + def __init__(self, get_response=None): # disable the middleware if the tracer is not enabled # or if the auto instrumentation is disabled @@ -99,20 +100,22 @@ class TraceExceptionMiddleware(InstrumentationMixin): """ Middleware that traces exceptions raised """ + def process_exception(self, request, exception): try: span = _get_req_span(request) if span: - span.set_tag(http.STATUS_CODE, '500') + span.set_tag(http.STATUS_CODE, "500") span.set_traceback() # will set the exception info except Exception: - log.debug('error processing exception', exc_info=True) + log.debug("error processing exception", exc_info=True) class TraceMiddleware(InstrumentationMixin): """ Middleware that traces Django requests """ + def process_request(self, request): tracer = settings.TRACER if settings.DISTRIBUTED_TRACING: @@ -123,9 +126,9 @@ def process_request(self, request): tracer.context_provider.activate(context) try: span = tracer.trace( - 'django.request', + "django.request", service=settings.DEFAULT_SERVICE, - resource='unknown', # will be filled by process view + resource="unknown", # will be filled by process view span_type=SpanTypes.WEB, ) @@ -133,8 +136,7 @@ def process_request(self, request): # DEV: django is special case maintains separate configuration from config api if _analytics_enabled() and settings.ANALYTICS_SAMPLE_RATE is not None: span.set_tag( - ANALYTICS_SAMPLE_RATE_KEY, - settings.ANALYTICS_SAMPLE_RATE, + ANALYTICS_SAMPLE_RATE_KEY, settings.ANALYTICS_SAMPLE_RATE, ) # Set HTTP Request tags @@ -144,10 +146,10 @@ def process_request(self, request): if trace_query_string is None: trace_query_string = config.django.trace_query_string if trace_query_string: - span.set_tag(http.QUERY_STRING, request.META['QUERY_STRING']) + span.set_tag(http.QUERY_STRING, request.META["QUERY_STRING"]) _set_req_span(request, span) except Exception: - log.debug('error tracing request', exc_info=True) + log.debug("error tracing request", exc_info=True) def process_view(self, request, view_func, *args, **kwargs): span = _get_req_span(request) @@ -166,63 +168,63 @@ def process_response(self, request, response): # If `process_view` was not called, try to determine the correct `span.resource` to set # DEV: `process_view` won't get called if a middle `process_request` returns an HttpResponse # DEV: `process_view` won't get called when internal error handlers are used (e.g. for 404 responses) - if span.resource == 'unknown': + if span.resource == "unknown": try: # Attempt to lookup the view function from the url resolver # https://github.com/django/django/blob/38e2fdadfd9952e751deed662edf4c496d238f28/django/core/handlers/base.py#L104-L113 # noqa urlconf = None - if hasattr(request, 'urlconf'): + if hasattr(request, "urlconf"): urlconf = request.urlconf resolver = get_resolver(urlconf) # Try to resolve the Django view for handling this request - if getattr(request, 'request_match', None): + if getattr(request, "request_match", None): request_match = request.request_match else: # This may raise a `django.urls.exceptions.Resolver404` exception request_match = resolver.resolve(request.path_info) span.resource = func_name(request_match.func) except Exception: - log.debug('error determining request view function', exc_info=True) + log.debug("error determining request view function", exc_info=True) # If the view could not be found, try to set from a static list of # known internal error handler views - span.resource = _django_default_views.get(response.status_code, 'unknown') + span.resource = _django_default_views.get(response.status_code, "unknown") span.set_tag(http.STATUS_CODE, response.status_code) span = _set_auth_tags(span, request) span.finish() except Exception: - log.debug('error tracing request', exc_info=True) + log.debug("error tracing request", exc_info=True) finally: return response def _get_req_span(request): """ Return the datadog span from the given request. """ - return getattr(request, '_datadog_request_span', None) + return getattr(request, "_datadog_request_span", None) def _set_req_span(request, span): """ Set the datadog span on the given request. """ - return setattr(request, '_datadog_request_span', span) + return setattr(request, "_datadog_request_span", span) def _set_auth_tags(span, request): """ Patch any available auth tags from the request onto the span. """ - user = getattr(request, 'user', None) + user = getattr(request, "user", None) if not user: return span - if hasattr(user, 'is_authenticated'): - span.set_tag('django.user.is_authenticated', user_is_authenticated(user)) + if hasattr(user, "is_authenticated"): + span.set_tag("django.user.is_authenticated", user_is_authenticated(user)) - uid = getattr(user, 'pk', None) + uid = getattr(user, "pk", None) if uid: - span.set_tag('django.user.id', uid) + span.set_tag("django.user.id", uid) - uname = getattr(user, 'username', None) + uname = getattr(user, "username", None) if uname: - span.set_tag('django.user.name', uname) + span.set_tag("django.user.name", uname) return span diff --git a/ddtrace/contrib/grpc/client_interceptor.py b/ddtrace/contrib/grpc/client_interceptor.py index 5aa763dc0d8..be1e66efa91 100644 --- a/ddtrace/contrib/grpc/client_interceptor.py +++ b/ddtrace/contrib/grpc/client_interceptor.py @@ -28,9 +28,9 @@ def create_client_interceptor(pin, host, port): def intercept_channel(wrapped, instance, args, kwargs): channel = args[0] interceptors = args[1:] - if isinstance(getattr(channel, '_interceptor', None), _ClientInterceptor): + if isinstance(getattr(channel, "_interceptor", None), _ClientInterceptor): dd_interceptor = channel._interceptor - base_channel = getattr(channel, '_channel', None) + base_channel = getattr(channel, "_channel", None) if base_channel: new_channel = wrapped(channel._channel, *interceptors) return grpc.intercept_channel(new_channel, dd_interceptor) @@ -39,10 +39,9 @@ def intercept_channel(wrapped, instance, args, kwargs): class _ClientCallDetails( - collections.namedtuple( - '_ClientCallDetails', - ('method', 'timeout', 'metadata', 'credentials')), - grpc.ClientCallDetails): + collections.namedtuple("_ClientCallDetails", ("method", "timeout", "metadata", "credentials")), + grpc.ClientCallDetails, +): pass @@ -74,9 +73,9 @@ def _handle_error(span, response_error, status_code): # exception() and traceback() methods if a computation has resulted in an # exception being raised if ( - not callable(getattr(response_error, 'cancelled', None)) and - not callable(getattr(response_error, 'exception', None)) and - not callable(getattr(response_error, 'traceback', None)) + not callable(getattr(response_error, "cancelled", None)) + and not callable(getattr(response_error, "exception", None)) + and not callable(getattr(response_error, "traceback", None)) ): return @@ -129,7 +128,7 @@ def __next__(self): raise except Exception: # DEV: added for safety though should not be reached since wrapped response - log.debug('unexpected non-grpc exception raised, closing open span', exc_info=True) + log.debug("unexpected non-grpc exception raised, closing open span", exc_info=True) self._span.set_traceback() self._span.finish() raise @@ -139,9 +138,11 @@ def next(self): class _ClientInterceptor( - grpc.UnaryUnaryClientInterceptor, grpc.UnaryStreamClientInterceptor, - grpc.StreamUnaryClientInterceptor, grpc.StreamStreamClientInterceptor): - + grpc.UnaryUnaryClientInterceptor, + grpc.UnaryStreamClientInterceptor, + grpc.StreamUnaryClientInterceptor, + grpc.StreamStreamClientInterceptor, +): def __init__(self, pin, host, port): self._pin = pin self._host = host @@ -151,10 +152,7 @@ def _intercept_client_call(self, method_kind, client_call_details): tracer = self._pin.tracer span = tracer.trace( - 'grpc', - span_type=SpanTypes.GRPC, - service=self._pin.service, - resource=client_call_details.method, + "grpc", span_type=SpanTypes.GRPC, service=self._pin.service, resource=client_call_details.method, ) # tags for method details @@ -189,19 +187,13 @@ def _intercept_client_call(self, method_kind, client_call_details): metadata.extend(headers.items()) client_call_details = _ClientCallDetails( - client_call_details.method, - client_call_details.timeout, - metadata, - client_call_details.credentials, + client_call_details.method, client_call_details.timeout, metadata, client_call_details.credentials, ) return span, client_call_details def intercept_unary_unary(self, continuation, client_call_details, request): - span, client_call_details = self._intercept_client_call( - constants.GRPC_METHOD_KIND_UNARY, - client_call_details, - ) + span, client_call_details = self._intercept_client_call(constants.GRPC_METHOD_KIND_UNARY, client_call_details,) try: response = continuation(client_call_details, request) _handle_response(span, response) @@ -216,8 +208,7 @@ def intercept_unary_unary(self, continuation, client_call_details, request): def intercept_unary_stream(self, continuation, client_call_details, request): span, client_call_details = self._intercept_client_call( - constants.GRPC_METHOD_KIND_SERVER_STREAMING, - client_call_details, + constants.GRPC_METHOD_KIND_SERVER_STREAMING, client_call_details, ) response_iterator = continuation(client_call_details, request) response_iterator = _WrappedResponseCallFuture(response_iterator, span) @@ -225,8 +216,7 @@ def intercept_unary_stream(self, continuation, client_call_details, request): def intercept_stream_unary(self, continuation, client_call_details, request_iterator): span, client_call_details = self._intercept_client_call( - constants.GRPC_METHOD_KIND_CLIENT_STREAMING, - client_call_details, + constants.GRPC_METHOD_KIND_CLIENT_STREAMING, client_call_details, ) try: response = continuation(client_call_details, request_iterator) @@ -242,8 +232,7 @@ def intercept_stream_unary(self, continuation, client_call_details, request_iter def intercept_stream_stream(self, continuation, client_call_details, request_iterator): span, client_call_details = self._intercept_client_call( - constants.GRPC_METHOD_KIND_BIDI_STREAMING, - client_call_details, + constants.GRPC_METHOD_KIND_BIDI_STREAMING, client_call_details, ) response_iterator = continuation(client_call_details, request_iterator) response_iterator = _WrappedResponseCallFuture(response_iterator, span) diff --git a/ddtrace/contrib/requests/connection.py b/ddtrace/contrib/requests/connection.py index e1536599e80..503d4a56c27 100644 --- a/ddtrace/contrib/requests/connection.py +++ b/ddtrace/contrib/requests/connection.py @@ -26,13 +26,11 @@ def _extract_service_name(session, span, hostname=None): Updated service name > parent service name > default to `requests`. """ cfg = config.get_from(session) - if cfg['split_by_domain'] and hostname: + if cfg["split_by_domain"] and hostname: return hostname - service_name = cfg['service_name'] - if (service_name == DEFAULT_SERVICE and - span._parent is not None and - span._parent.service is not None): + service_name = cfg["service_name"] + if service_name == DEFAULT_SERVICE and span._parent is not None and span._parent.service is not None: service_name = span._parent.service return service_name @@ -43,13 +41,13 @@ def _wrap_send(func, instance, args, kwargs): # and is ddtrace.tracer; it's used only inside our tests and can # be easily changed by providing a TracingTestCase that sets common # tracing functionalities. - tracer = getattr(instance, 'datadog_tracer', ddtrace.tracer) + tracer = getattr(instance, "datadog_tracer", ddtrace.tracer) # skip if tracing is not enabled if not tracer.enabled: return func(*args, **kwargs) - request = kwargs.get('request') or args[0] + request = kwargs.get("request") or args[0] if not request: return func(*args, **kwargs) @@ -57,32 +55,31 @@ def _wrap_send(func, instance, args, kwargs): parsed_uri = parse.urlparse(request.url) hostname = parsed_uri.hostname if parsed_uri.port: - hostname = '{}:{}'.format(hostname, parsed_uri.port) - sanitized_url = parse.urlunparse(( - parsed_uri.scheme, - parsed_uri.netloc, - parsed_uri.path, - parsed_uri.params, - None, # drop parsed_uri.query - parsed_uri.fragment - )) - - with tracer.trace('requests.request', span_type=SpanTypes.HTTP) as span: + hostname = "{}:{}".format(hostname, parsed_uri.port) + sanitized_url = parse.urlunparse( + ( + parsed_uri.scheme, + parsed_uri.netloc, + parsed_uri.path, + parsed_uri.params, + None, # drop parsed_uri.query + parsed_uri.fragment, + ) + ) + + with tracer.trace("requests.request", span_type=SpanTypes.HTTP) as span: # update the span service name before doing any action span.service = _extract_service_name(instance, span, hostname=hostname) # Configure trace search sample rate # DEV: analytics enabled on per-session basis cfg = config.get_from(instance) - analytics_enabled = cfg.get('analytics_enabled') + analytics_enabled = cfg.get("analytics_enabled") if analytics_enabled: - span.set_tag( - ANALYTICS_SAMPLE_RATE_KEY, - cfg.get('analytics_sample_rate', True) - ) + span.set_tag(ANALYTICS_SAMPLE_RATE_KEY, cfg.get("analytics_sample_rate", True)) # propagate distributed tracing headers - if cfg.get('distributed_tracing'): + if cfg.get("distributed_tracing"): propagator = HTTPPropagator() propagator.inject(span.context, request.headers) @@ -95,7 +92,7 @@ def _wrap_send(func, instance, args, kwargs): # Storing response headers in the span. Note that response.headers is not a dict, but an iterable # requests custom structure, that we convert to a dict - if hasattr(response, 'headers'): + if hasattr(response, "headers"): store_response_headers(dict(response.headers), span, config.requests) return response finally: @@ -111,7 +108,7 @@ def _wrap_send(func, instance, args, kwargs): # Storing response headers in the span. # Note that response.headers is not a dict, but an iterable # requests custom structure, that we convert to a dict - response_headers = dict(getattr(response, 'headers', {})) + response_headers = dict(getattr(response, "headers", {})) store_response_headers(response_headers, span, config.requests) except Exception: - log.debug('requests: error adding tags', exc_info=True) + log.debug("requests: error adding tags", exc_info=True) diff --git a/pyproject.toml b/pyproject.toml index 707aa964b0e..eb5d49495c5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,6 +19,79 @@ exclude = ''' | bootstrap/ | commands/ | contrib/ + ( + aiobotocore + | aiohttp + | aiopg + | algoliasearch + | asyncio + | boto + | botocore + | bottle + | cassandra + | celery + | consul + | dbapi + | django/ + ( + __init__.py + | apps.py + | cache.py + | compat.py + | conf.py + | db.py + | patch.py + | restframework.py + | templates.py + | utils.py + ) + | dogpile_cache + | elasticsearch + | falcon + | flask + | flask_cache + | futures + | gevent + | grpc/ + ( + __init__.py + | constants.py + | patch.py + | server_interceptor.py + | utils.py + ) + | httplib + | jinja2 + | kombu + | logging + | mako + | molten + | mongoengine + | mysql + | mysqldb + | psycopg + | pylibmc + | pylons + | pymemcache + | pymongo + | pymysql + | pyramid + | redis + | rediscluster + | requests/ + ( + __init__.py + | constants.py + | legacy.py + | patch.py + | session.py + ) + | sqlalchemy + | sqlite3 + | tornado + | util.py + | vertica + ) | ext/ | http/ | internal/ @@ -29,5 +102,113 @@ exclude = ''' | vendor/ ) | tests/ + ( + base + | benchmark.py + | commands + | contrib/ + ( + aiobotocore + | aiohttp + | aiopg + | algoliasearch + | asyncio + | boto + | botocore + | bottle + | cassandra + | celery + | config.py + | consul + | dbapi + | django + | djangorestframework + | elasticsearch + | falcon + | flask + | flask_autopatch + | flask_cache + | futures + | gevent + | grpc + | httplib + | jinja2 + | kombu + | logging + | mako + | molten + | mongoengine + | mysql + | mysqldb + | patch.py + | psycopg + | pylibmc + | pylons + | pymemcache + | pymongo + | pymysql + | pyramid/ + ( + app/web.py + | __init__.py + | test_pyramid.py + | test_pyramid_autopatch.py + ) + | redis + | rediscluster + | requests + | requests_gevent + | sqlalchemy + | sqlite3 + | test_utils.py + | tornado + | vertica + ) + | ddtrace_run.py + | internal/ + ( + runtime/ + | test_context_manager.py + | test_hostname.py + | test_logger.py + | test_rate_limiter.py + ) + | memory.py + | opentracer/ + ( + conftest.py + | test_dd_compatibility.py + | test_span.py + | test_span_context.py + | test_tracer_asyncio.py + | test_tracer_gevent.py + | test_tracer_tornado.py + | test_utils.py + ) + | propagation/test_utils.py + | subprocesstest.py + | test_api.py + | test_compat.py + | test_context.py + | test_encoders.py + | test_filters.py + | test_global_config.py + | test_helpers.py + | test_hook.py + | test_instance_config.py + | test_integration.py + | test_payload.py + | test_pin.py + | test_sampler.py + | test_span.py + | test_tracer.py + | test_utils.py + | test_worker.py + | unit + | util.py + | utils + | vendor + | wait-for-services.py + ) ) -''' +''' \ No newline at end of file diff --git a/tests/contrib/dogpile_cache/test_tracing.py b/tests/contrib/dogpile_cache/test_tracing.py index 79e42592069..1548bf24e11 100644 --- a/tests/contrib/dogpile_cache/test_tracing.py +++ b/tests/contrib/dogpile_cache/test_tracing.py @@ -17,8 +17,8 @@ def region(tracer): patch() # Setup a simple dogpile cache region for testing. # The backend is trivial so we can use memory to simplify test setup. - test_region = dogpile.cache.make_region(name='TestRegion') - test_region.configure('dogpile.cache.memory') + test_region = dogpile.cache.make_region(name="TestRegion") + test_region.configure("dogpile.cache.memory") Pin.override(dogpile.cache, tracer=tracer) return test_region @@ -34,6 +34,7 @@ def single_cache(region): @region.cache_on_arguments() def fn(x): return x * 2 + return fn @@ -74,13 +75,13 @@ def test_traces_get_or_create(tracer, single_cache): spans = traces[0] assert len(spans) == 1 span = spans[0] - assert span.name == 'dogpile.cache' - assert span.resource == 'get_or_create' - assert span.meta['key'] == 'tests.contrib.dogpile_cache.test_tracing:fn|1' - assert span.meta['hit'] == 'False' - assert span.meta['expired'] == 'True' - assert span.meta['backend'] == 'MemoryBackend' - assert span.meta['region'] == 'TestRegion' + assert span.name == "dogpile.cache" + assert span.resource == "get_or_create" + assert span.meta["key"] == "tests.contrib.dogpile_cache.test_tracing:fn|1" + assert span.meta["hit"] == "False" + assert span.meta["expired"] == "True" + assert span.meta["backend"] == "MemoryBackend" + assert span.meta["region"] == "TestRegion" # Now the results should be cached. assert single_cache(1) == 2 @@ -89,13 +90,13 @@ def test_traces_get_or_create(tracer, single_cache): spans = traces[0] assert len(spans) == 1 span = spans[0] - assert span.name == 'dogpile.cache' - assert span.resource == 'get_or_create' - assert span.meta['key'] == 'tests.contrib.dogpile_cache.test_tracing:fn|1' - assert span.meta['hit'] == 'True' - assert span.meta['expired'] == 'False' - assert span.meta['backend'] == 'MemoryBackend' - assert span.meta['region'] == 'TestRegion' + assert span.name == "dogpile.cache" + assert span.resource == "get_or_create" + assert span.meta["key"] == "tests.contrib.dogpile_cache.test_tracing:fn|1" + assert span.meta["hit"] == "True" + assert span.meta["expired"] == "False" + assert span.meta["backend"] == "MemoryBackend" + assert span.meta["region"] == "TestRegion" def test_traces_get_or_create_multi(tracer, multi_cache): @@ -105,14 +106,13 @@ def test_traces_get_or_create_multi(tracer, multi_cache): spans = traces[0] assert len(spans) == 1 span = spans[0] - assert span.meta['keys'] == ( - "['tests.contrib.dogpile_cache.test_tracing:fn|2', " + - "'tests.contrib.dogpile_cache.test_tracing:fn|3']" + assert span.meta["keys"] == ( + "['tests.contrib.dogpile_cache.test_tracing:fn|2', " + "'tests.contrib.dogpile_cache.test_tracing:fn|3']" ) - assert span.meta['hit'] == 'False' - assert span.meta['expired'] == 'True' - assert span.meta['backend'] == 'MemoryBackend' - assert span.meta['region'] == 'TestRegion' + assert span.meta["hit"] == "False" + assert span.meta["expired"] == "True" + assert span.meta["backend"] == "MemoryBackend" + assert span.meta["region"] == "TestRegion" # Partial hit assert multi_cache(2, 4) == [4, 8] @@ -121,14 +121,13 @@ def test_traces_get_or_create_multi(tracer, multi_cache): spans = traces[0] assert len(spans) == 1 span = spans[0] - assert span.meta['keys'] == ( - "['tests.contrib.dogpile_cache.test_tracing:fn|2', " + - "'tests.contrib.dogpile_cache.test_tracing:fn|4']" + assert span.meta["keys"] == ( + "['tests.contrib.dogpile_cache.test_tracing:fn|2', " + "'tests.contrib.dogpile_cache.test_tracing:fn|4']" ) - assert span.meta['hit'] == 'False' - assert span.meta['expired'] == 'True' - assert span.meta['backend'] == 'MemoryBackend' - assert span.meta['region'] == 'TestRegion' + assert span.meta["hit"] == "False" + assert span.meta["expired"] == "True" + assert span.meta["backend"] == "MemoryBackend" + assert span.meta["region"] == "TestRegion" # Full hit assert multi_cache(2, 4) == [4, 8] @@ -137,14 +136,13 @@ def test_traces_get_or_create_multi(tracer, multi_cache): spans = traces[0] assert len(spans) == 1 span = spans[0] - assert span.meta['keys'] == ( - "['tests.contrib.dogpile_cache.test_tracing:fn|2', " + - "'tests.contrib.dogpile_cache.test_tracing:fn|4']" + assert span.meta["keys"] == ( + "['tests.contrib.dogpile_cache.test_tracing:fn|2', " + "'tests.contrib.dogpile_cache.test_tracing:fn|4']" ) - assert span.meta['hit'] == 'True' - assert span.meta['expired'] == 'False' - assert span.meta['backend'] == 'MemoryBackend' - assert span.meta['region'] == 'TestRegion' + assert span.meta["hit"] == "True" + assert span.meta["expired"] == "False" + assert span.meta["backend"] == "MemoryBackend" + assert span.meta["region"] == "TestRegion" class TestInnerFunctionCalls(object): @@ -156,8 +154,8 @@ def multi_cache(self, *x): def test_calls_inner_functions_correctly(self, region, mocker): """ This ensures the get_or_create behavior of dogpile is not altered. """ - spy_single_cache = mocker.spy(self, 'single_cache') - spy_multi_cache = mocker.spy(self, 'multi_cache') + spy_single_cache = mocker.spy(self, "single_cache") + spy_multi_cache = mocker.spy(self, "multi_cache") single_cache = region.cache_on_arguments()(self.single_cache) multi_cache = region.cache_multi_on_arguments()(self.multi_cache) diff --git a/tests/contrib/pyramid/utils.py b/tests/contrib/pyramid/utils.py index f3c97e1f546..3e9ee9dc81a 100644 --- a/tests/contrib/pyramid/utils.py +++ b/tests/contrib/pyramid/utils.py @@ -19,6 +19,7 @@ class PyramidBase(BaseTracerTestCase): """Base Pyramid test application""" + def setUp(self): super(PyramidBase, self).setUp() self.create_app() @@ -27,7 +28,7 @@ def create_app(self, settings=None): # get default settings or use what is provided settings = settings or self.get_settings() # always set the dummy tracer as a default tracer - settings.update({'datadog_tracer': self.tracer}) + settings.update({"datadog_tracer": self.tracer}) app, renderer = create_app(settings, self.instrument) self.app = webtest.TestApp(app) @@ -42,37 +43,38 @@ def override_settings(self, settings): class PyramidTestCase(PyramidBase): """Pyramid TestCase that includes tests for automatic instrumentation""" + instrument = True def get_settings(self): return { - 'datadog_trace_service': 'foobar', + "datadog_trace_service": "foobar", } - def test_200(self, query_string=''): + def test_200(self, query_string=""): if query_string: - fqs = '?' + query_string + fqs = "?" + query_string else: - fqs = '' - res = self.app.get('/' + fqs, status=200) - assert b'idx' in res.body + fqs = "" + res = self.app.get("/" + fqs, status=200) + assert b"idx" in res.body writer = self.tracer.writer spans = writer.pop() assert len(spans) == 1 s = spans[0] - assert s.service == 'foobar' - assert s.resource == 'GET index' + assert s.service == "foobar" + assert s.resource == "GET index" assert s.error == 0 - assert s.span_type == 'web' - assert s.meta.get('http.method') == 'GET' + assert s.span_type == "web" + assert s.meta.get("http.method") == "GET" assert_span_http_status_code(s, 200) - assert s.meta.get(http.URL) == 'http://localhost/' + assert s.meta.get(http.URL) == "http://localhost/" if config.pyramid.trace_query_string: assert s.meta.get(http.QUERY_STRING) == query_string else: assert http.QUERY_STRING not in s.meta - assert s.meta.get('pyramid.route.name') == 'index' + assert s.meta.get("pyramid.route.name") == "index" # ensure services are set correctly services = writer.pop_services() @@ -80,11 +82,11 @@ def test_200(self, query_string=''): assert services == expected def test_200_query_string(self): - return self.test_200('foo=bar') + return self.test_200("foo=bar") def test_200_query_string_trace(self): - with self.override_http_config('pyramid', dict(trace_query_string=True)): - return self.test_200('foo=bar') + with self.override_http_config("pyramid", dict(trace_query_string=True)): + return self.test_200("foo=bar") def test_analytics_global_on_integration_default(self): """ @@ -93,12 +95,10 @@ def test_analytics_global_on_integration_default(self): We expect the root span to have the appropriate tag """ with self.override_global_config(dict(analytics_enabled=True)): - res = self.app.get('/', status=200) - assert b'idx' in res.body + res = self.app.get("/", status=200) + assert b"idx" in res.body - self.assert_structure( - dict(name='pyramid.request', metrics={ANALYTICS_SAMPLE_RATE_KEY: 1.0}), - ) + self.assert_structure(dict(name="pyramid.request", metrics={ANALYTICS_SAMPLE_RATE_KEY: 1.0}),) def test_analytics_global_on_integration_on(self): """ @@ -108,12 +108,10 @@ def test_analytics_global_on_integration_on(self): """ with self.override_global_config(dict(analytics_enabled=True)): self.override_settings(dict(datadog_analytics_enabled=True, datadog_analytics_sample_rate=0.5)) - res = self.app.get('/', status=200) - assert b'idx' in res.body + res = self.app.get("/", status=200) + assert b"idx" in res.body - self.assert_structure( - dict(name='pyramid.request', metrics={ANALYTICS_SAMPLE_RATE_KEY: 0.5}), - ) + self.assert_structure(dict(name="pyramid.request", metrics={ANALYTICS_SAMPLE_RATE_KEY: 0.5}),) def test_analytics_global_off_integration_default(self): """ @@ -122,8 +120,8 @@ def test_analytics_global_off_integration_default(self): We expect the root span to not include tag """ with self.override_global_config(dict(analytics_enabled=False)): - res = self.app.get('/', status=200) - assert b'idx' in res.body + res = self.app.get("/", status=200) + assert b"idx" in res.body root = self.get_root_span() self.assertIsNone(root.get_metric(ANALYTICS_SAMPLE_RATE_KEY)) @@ -136,61 +134,59 @@ def test_analytics_global_off_integration_on(self): """ with self.override_global_config(dict(analytics_enabled=False)): self.override_settings(dict(datadog_analytics_enabled=True, datadog_analytics_sample_rate=0.5)) - res = self.app.get('/', status=200) - assert b'idx' in res.body + res = self.app.get("/", status=200) + assert b"idx" in res.body - self.assert_structure( - dict(name='pyramid.request', metrics={ANALYTICS_SAMPLE_RATE_KEY: 0.5}), - ) + self.assert_structure(dict(name="pyramid.request", metrics={ANALYTICS_SAMPLE_RATE_KEY: 0.5}),) def test_404(self): - self.app.get('/404', status=404) + self.app.get("/404", status=404) writer = self.tracer.writer spans = writer.pop() assert len(spans) == 1 s = spans[0] - assert s.service == 'foobar' - assert s.resource == '404' + assert s.service == "foobar" + assert s.resource == "404" assert s.error == 0 - assert s.span_type == 'web' - assert s.meta.get('http.method') == 'GET' + assert s.span_type == "web" + assert s.meta.get("http.method") == "GET" assert_span_http_status_code(s, 404) - assert s.meta.get(http.URL) == 'http://localhost/404' + assert s.meta.get(http.URL) == "http://localhost/404" def test_302(self): - self.app.get('/redirect', status=302) + self.app.get("/redirect", status=302) writer = self.tracer.writer spans = writer.pop() assert len(spans) == 1 s = spans[0] - assert s.service == 'foobar' - assert s.resource == 'GET raise_redirect' + assert s.service == "foobar" + assert s.resource == "GET raise_redirect" assert s.error == 0 - assert s.span_type == 'web' - assert s.meta.get('http.method') == 'GET' + assert s.span_type == "web" + assert s.meta.get("http.method") == "GET" assert_span_http_status_code(s, 302) - assert s.meta.get(http.URL) == 'http://localhost/redirect' + assert s.meta.get(http.URL) == "http://localhost/redirect" def test_204(self): - self.app.get('/nocontent', status=204) + self.app.get("/nocontent", status=204) writer = self.tracer.writer spans = writer.pop() assert len(spans) == 1 s = spans[0] - assert s.service == 'foobar' - assert s.resource == 'GET raise_no_content' + assert s.service == "foobar" + assert s.resource == "GET raise_no_content" assert s.error == 0 - assert s.span_type == 'web' - assert s.meta.get('http.method') == 'GET' + assert s.span_type == "web" + assert s.meta.get("http.method") == "GET" assert_span_http_status_code(s, 204) - assert s.meta.get(http.URL) == 'http://localhost/nocontent' + assert s.meta.get(http.URL) == "http://localhost/nocontent" def test_exception(self): try: - self.app.get('/exception', status=500) + self.app.get("/exception", status=500) except ZeroDivisionError: pass @@ -198,146 +194,145 @@ def test_exception(self): spans = writer.pop() assert len(spans) == 1 s = spans[0] - assert s.service == 'foobar' - assert s.resource == 'GET exception' + assert s.service == "foobar" + assert s.resource == "GET exception" assert s.error == 1 - assert s.span_type == 'web' - assert s.meta.get('http.method') == 'GET' + assert s.span_type == "web" + assert s.meta.get("http.method") == "GET" assert_span_http_status_code(s, 500) - assert s.meta.get(http.URL) == 'http://localhost/exception' - assert s.meta.get('pyramid.route.name') == 'exception' + assert s.meta.get(http.URL) == "http://localhost/exception" + assert s.meta.get("pyramid.route.name") == "exception" def test_500(self): - self.app.get('/error', status=500) + self.app.get("/error", status=500) writer = self.tracer.writer spans = writer.pop() assert len(spans) == 1 s = spans[0] - assert s.service == 'foobar' - assert s.resource == 'GET error' + assert s.service == "foobar" + assert s.resource == "GET error" assert s.error == 1 - assert s.span_type == 'web' - assert s.meta.get('http.method') == 'GET' + assert s.span_type == "web" + assert s.meta.get("http.method") == "GET" assert_span_http_status_code(s, 500) - assert s.meta.get(http.URL) == 'http://localhost/error' - assert s.meta.get('pyramid.route.name') == 'error' + assert s.meta.get(http.URL) == "http://localhost/error" + assert s.meta.get("pyramid.route.name") == "error" assert type(s.error) == int def test_json(self): - res = self.app.get('/json', status=200) + res = self.app.get("/json", status=200) parsed = json.loads(compat.to_unicode(res.body)) - assert parsed == {'a': 1} + assert parsed == {"a": 1} writer = self.tracer.writer spans = writer.pop() assert len(spans) == 2 spans_by_name = {s.name: s for s in spans} - s = spans_by_name['pyramid.request'] - assert s.service == 'foobar' - assert s.resource == 'GET json' + s = spans_by_name["pyramid.request"] + assert s.service == "foobar" + assert s.resource == "GET json" assert s.error == 0 - assert s.span_type == 'web' - assert s.meta.get('http.method') == 'GET' + assert s.span_type == "web" + assert s.meta.get("http.method") == "GET" assert_span_http_status_code(s, 200) - assert s.meta.get(http.URL) == 'http://localhost/json' - assert s.meta.get('pyramid.route.name') == 'json' + assert s.meta.get(http.URL) == "http://localhost/json" + assert s.meta.get("pyramid.route.name") == "json" - s = spans_by_name['pyramid.render'] - assert s.service == 'foobar' + s = spans_by_name["pyramid.render"] + assert s.service == "foobar" assert s.error == 0 - assert s.span_type == 'template' + assert s.span_type == "template" def test_renderer(self): - self.app.get('/renderer', status=200) - assert self.renderer._received['request'] is not None + self.app.get("/renderer", status=200) + assert self.renderer._received["request"] is not None - self.renderer.assert_(foo='bar') + self.renderer.assert_(foo="bar") writer = self.tracer.writer spans = writer.pop() assert len(spans) == 2 spans_by_name = {s.name: s for s in spans} - s = spans_by_name['pyramid.request'] - assert s.service == 'foobar' - assert s.resource == 'GET renderer' + s = spans_by_name["pyramid.request"] + assert s.service == "foobar" + assert s.resource == "GET renderer" assert s.error == 0 - assert s.span_type == 'web' - assert s.meta.get('http.method') == 'GET' + assert s.span_type == "web" + assert s.meta.get("http.method") == "GET" assert_span_http_status_code(s, 200) - assert s.meta.get(http.URL) == 'http://localhost/renderer' - assert s.meta.get('pyramid.route.name') == 'renderer' + assert s.meta.get(http.URL) == "http://localhost/renderer" + assert s.meta.get("pyramid.route.name") == "renderer" - s = spans_by_name['pyramid.render'] - assert s.service == 'foobar' + s = spans_by_name["pyramid.render"] + assert s.service == "foobar" assert s.error == 0 - assert s.span_type == 'template' + assert s.span_type == "template" def test_http_exception_response(self): with pytest.raises(HTTPException): - self.app.get('/404/raise_exception', status=404) + self.app.get("/404/raise_exception", status=404) writer = self.tracer.writer spans = writer.pop() assert len(spans) == 1 s = spans[0] - assert s.service == 'foobar' - assert s.resource == '404' + assert s.service == "foobar" + assert s.resource == "404" assert s.error == 1 - assert s.span_type == 'web' - assert s.meta.get('http.method') == 'GET' + assert s.span_type == "web" + assert s.meta.get("http.method") == "GET" assert_span_http_status_code(s, 404) - assert s.meta.get(http.URL) == 'http://localhost/404/raise_exception' + assert s.meta.get(http.URL) == "http://localhost/404/raise_exception" def test_insert_tween_if_needed_already_set(self): - settings = {'pyramid.tweens': 'ddtrace.contrib.pyramid:trace_tween_factory'} + settings = {"pyramid.tweens": "ddtrace.contrib.pyramid:trace_tween_factory"} insert_tween_if_needed(settings) - assert settings['pyramid.tweens'] == 'ddtrace.contrib.pyramid:trace_tween_factory' + assert settings["pyramid.tweens"] == "ddtrace.contrib.pyramid:trace_tween_factory" def test_insert_tween_if_needed_none(self): - settings = {'pyramid.tweens': ''} + settings = {"pyramid.tweens": ""} insert_tween_if_needed(settings) - assert settings['pyramid.tweens'] == '' + assert settings["pyramid.tweens"] == "" def test_insert_tween_if_needed_excview(self): - settings = {'pyramid.tweens': 'pyramid.tweens.excview_tween_factory'} + settings = {"pyramid.tweens": "pyramid.tweens.excview_tween_factory"} insert_tween_if_needed(settings) assert ( - settings['pyramid.tweens'] == - 'ddtrace.contrib.pyramid:trace_tween_factory\npyramid.tweens.excview_tween_factory' + settings["pyramid.tweens"] + == "ddtrace.contrib.pyramid:trace_tween_factory\npyramid.tweens.excview_tween_factory" ) def test_insert_tween_if_needed_excview_and_other(self): - settings = {'pyramid.tweens': 'a.first.tween\npyramid.tweens.excview_tween_factory\na.last.tween\n'} + settings = {"pyramid.tweens": "a.first.tween\npyramid.tweens.excview_tween_factory\na.last.tween\n"} insert_tween_if_needed(settings) assert ( - settings['pyramid.tweens'] == - 'a.first.tween\n' - 'ddtrace.contrib.pyramid:trace_tween_factory\n' - 'pyramid.tweens.excview_tween_factory\n' - 'a.last.tween\n') + settings["pyramid.tweens"] == "a.first.tween\n" + "ddtrace.contrib.pyramid:trace_tween_factory\n" + "pyramid.tweens.excview_tween_factory\n" + "a.last.tween\n" + ) def test_insert_tween_if_needed_others(self): - settings = {'pyramid.tweens': 'a.random.tween\nand.another.one'} + settings = {"pyramid.tweens": "a.random.tween\nand.another.one"} insert_tween_if_needed(settings) assert ( - settings['pyramid.tweens'] == - 'a.random.tween\nand.another.one\nddtrace.contrib.pyramid:trace_tween_factory' + settings["pyramid.tweens"] == "a.random.tween\nand.another.one\nddtrace.contrib.pyramid:trace_tween_factory" ) def test_include_conflicts(self): # test that includes do not create conflicts - self.override_settings({'pyramid.includes': 'tests.contrib.pyramid.test_pyramid'}) - self.app.get('/404', status=404) + self.override_settings({"pyramid.includes": "tests.contrib.pyramid.test_pyramid"}) + self.app.get("/404", status=404) spans = self.tracer.writer.pop() assert len(spans) == 1 def test_200_ot(self): """OpenTracing version of test_200.""" - ot_tracer = init_tracer('pyramid_svc', self.tracer) + ot_tracer = init_tracer("pyramid_svc", self.tracer) - with ot_tracer.start_active_span('pyramid_get'): - res = self.app.get('/', status=200) - assert b'idx' in res.body + with ot_tracer.start_active_span("pyramid_get"): + res = self.app.get("/", status=200) + assert b"idx" in res.body writer = self.tracer.writer spans = writer.pop() @@ -349,14 +344,14 @@ def test_200_ot(self): assert ot_span.parent_id is None assert dd_span.parent_id == ot_span.span_id - assert ot_span.name == 'pyramid_get' - assert ot_span.service == 'pyramid_svc' + assert ot_span.name == "pyramid_get" + assert ot_span.service == "pyramid_svc" - assert dd_span.service == 'foobar' - assert dd_span.resource == 'GET index' + assert dd_span.service == "foobar" + assert dd_span.resource == "GET index" assert dd_span.error == 0 - assert dd_span.span_type == 'web' - assert dd_span.meta.get('http.method') == 'GET' + assert dd_span.span_type == "web" + assert dd_span.meta.get("http.method") == "GET" assert_span_http_status_code(dd_span, 200) - assert dd_span.meta.get(http.URL) == 'http://localhost/' - assert dd_span.meta.get('pyramid.route.name') == 'index' + assert dd_span.meta.get(http.URL) == "http://localhost/" + assert dd_span.meta.get("pyramid.route.name") == "index" diff --git a/tests/internal/test_writer.py b/tests/internal/test_writer.py index 3f28dae1ec3..4ee0087dfc4 100644 --- a/tests/internal/test_writer.py +++ b/tests/internal/test_writer.py @@ -10,7 +10,7 @@ from ..base import BaseTestCase -class RemoveAllFilter(): +class RemoveAllFilter: def __init__(self): self.filtered_traces = 0 @@ -19,7 +19,7 @@ def process_trace(self, trace): return None -class KeepAllFilter(): +class KeepAllFilter: def __init__(self): self.filtered_traces = 0 @@ -28,7 +28,7 @@ def process_trace(self, trace): return trace -class AddTagFilter(): +class AddTagFilter: def __init__(self, tag_name): self.tag_name = tag_name self.filtered_traces = 0 @@ -36,14 +36,14 @@ def __init__(self, tag_name): def process_trace(self, trace): self.filtered_traces += 1 for span in trace: - span.set_tag(self.tag_name, 'A value') + span.set_tag(self.tag_name, "A value") return trace class DummyAPI(API): def __init__(self): # Call API.__init__ to setup required properties - super(DummyAPI, self).__init__(hostname='localhost', port=8126) + super(DummyAPI, self).__init__(hostname="localhost", port=8126) self.traces = [] @@ -58,10 +58,9 @@ def send_traces(self, traces): class FailingAPI(object): - @staticmethod def send_traces(traces): - return [Exception('oops')] + return [Exception("oops")] class AgentWriterTests(BaseTestCase): @@ -75,10 +74,9 @@ def create_worker(self, filters=None, api_class=DummyAPI, enable_stats=False): self.api = api_class() worker.api = self.api for i in range(self.N_TRACES): - worker.write([ - Span(tracer=None, name='name', trace_id=i, span_id=j, parent_id=j - 1 or None) - for j in range(7) - ]) + worker.write( + [Span(tracer=None, name="name", trace_id=i, span_id=j, parent_id=j - 1 or None) for j in range(7)] + ) worker.stop() worker.join() return worker @@ -108,7 +106,7 @@ def test_filters_remove_all(self): self.assertEqual(filtr.filtered_traces, self.N_TRACES) def test_filters_add_tag(self): - tag_name = 'Tag' + tag_name = "Tag" filtr = AddTagFilter(tag_name) self.create_worker([filtr]) self.assertEqual(len(self.api.traces), self.N_TRACES) @@ -127,72 +125,71 @@ def test_filters_short_circuit(self): def test_no_dogstats(self): worker = self.create_worker() assert worker._send_stats is False - assert [ - ] == self.dogstatsd.gauge.mock_calls + assert [] == self.dogstatsd.gauge.mock_calls def test_dogstatsd(self): self.create_worker(enable_stats=True) assert [ - mock.call('datadog.tracer.heartbeat', 1), - mock.call('datadog.tracer.queue.max_length', 1000), + mock.call("datadog.tracer.heartbeat", 1), + mock.call("datadog.tracer.queue.max_length", 1000), ] == self.dogstatsd.gauge.mock_calls assert [ - mock.call('datadog.tracer.flushes'), - mock.call('datadog.tracer.flush.traces.total', 11, tags=None), - mock.call('datadog.tracer.flush.spans.total', 77, tags=None), - mock.call('datadog.tracer.flush.traces_filtered.total', 0, tags=None), - mock.call('datadog.tracer.api.requests.total', 11, tags=None), - mock.call('datadog.tracer.api.errors.total', 0, tags=None), - mock.call('datadog.tracer.api.responses.total', 11, tags=['status:200']), - mock.call('datadog.tracer.queue.dropped.traces', 0), - mock.call('datadog.tracer.queue.enqueued.traces', 11), - mock.call('datadog.tracer.queue.enqueued.spans', 77), - mock.call('datadog.tracer.shutdown'), + mock.call("datadog.tracer.flushes"), + mock.call("datadog.tracer.flush.traces.total", 11, tags=None), + mock.call("datadog.tracer.flush.spans.total", 77, tags=None), + mock.call("datadog.tracer.flush.traces_filtered.total", 0, tags=None), + mock.call("datadog.tracer.api.requests.total", 11, tags=None), + mock.call("datadog.tracer.api.errors.total", 0, tags=None), + mock.call("datadog.tracer.api.responses.total", 11, tags=["status:200"]), + mock.call("datadog.tracer.queue.dropped.traces", 0), + mock.call("datadog.tracer.queue.enqueued.traces", 11), + mock.call("datadog.tracer.queue.enqueued.spans", 77), + mock.call("datadog.tracer.shutdown"), ] == self.dogstatsd.increment.mock_calls histogram_calls = [ - mock.call('datadog.tracer.flush.traces', 11, tags=None), - mock.call('datadog.tracer.flush.spans', 77, tags=None), - mock.call('datadog.tracer.flush.traces_filtered', 0, tags=None), - mock.call('datadog.tracer.api.requests', 11, tags=None), - mock.call('datadog.tracer.api.errors', 0, tags=None), - mock.call('datadog.tracer.api.responses', 11, tags=['status:200']), + mock.call("datadog.tracer.flush.traces", 11, tags=None), + mock.call("datadog.tracer.flush.spans", 77, tags=None), + mock.call("datadog.tracer.flush.traces_filtered", 0, tags=None), + mock.call("datadog.tracer.api.requests", 11, tags=None), + mock.call("datadog.tracer.api.errors", 0, tags=None), + mock.call("datadog.tracer.api.responses", 11, tags=["status:200"]), ] - if hasattr(time, 'thread_time'): - histogram_calls.append(mock.call('datadog.tracer.writer.cpu_time', mock.ANY)) + if hasattr(time, "thread_time"): + histogram_calls.append(mock.call("datadog.tracer.writer.cpu_time", mock.ANY)) assert histogram_calls == self.dogstatsd.histogram.mock_calls def test_dogstatsd_failing_api(self): self.create_worker(api_class=FailingAPI, enable_stats=True) assert [ - mock.call('datadog.tracer.heartbeat', 1), - mock.call('datadog.tracer.queue.max_length', 1000), + mock.call("datadog.tracer.heartbeat", 1), + mock.call("datadog.tracer.queue.max_length", 1000), ] == self.dogstatsd.gauge.mock_calls assert [ - mock.call('datadog.tracer.flushes'), - mock.call('datadog.tracer.flush.traces.total', 11, tags=None), - mock.call('datadog.tracer.flush.spans.total', 77, tags=None), - mock.call('datadog.tracer.flush.traces_filtered.total', 0, tags=None), - mock.call('datadog.tracer.api.requests.total', 1, tags=None), - mock.call('datadog.tracer.api.errors.total', 1, tags=None), - mock.call('datadog.tracer.queue.dropped.traces', 0), - mock.call('datadog.tracer.queue.enqueued.traces', 11), - mock.call('datadog.tracer.queue.enqueued.spans', 77), - mock.call('datadog.tracer.shutdown'), + mock.call("datadog.tracer.flushes"), + mock.call("datadog.tracer.flush.traces.total", 11, tags=None), + mock.call("datadog.tracer.flush.spans.total", 77, tags=None), + mock.call("datadog.tracer.flush.traces_filtered.total", 0, tags=None), + mock.call("datadog.tracer.api.requests.total", 1, tags=None), + mock.call("datadog.tracer.api.errors.total", 1, tags=None), + mock.call("datadog.tracer.queue.dropped.traces", 0), + mock.call("datadog.tracer.queue.enqueued.traces", 11), + mock.call("datadog.tracer.queue.enqueued.spans", 77), + mock.call("datadog.tracer.shutdown"), ] == self.dogstatsd.increment.mock_calls histogram_calls = [ - mock.call('datadog.tracer.flush.traces', 11, tags=None), - mock.call('datadog.tracer.flush.spans', 77, tags=None), - mock.call('datadog.tracer.flush.traces_filtered', 0, tags=None), - mock.call('datadog.tracer.api.requests', 1, tags=None), - mock.call('datadog.tracer.api.errors', 1, tags=None), + mock.call("datadog.tracer.flush.traces", 11, tags=None), + mock.call("datadog.tracer.flush.spans", 77, tags=None), + mock.call("datadog.tracer.flush.traces_filtered", 0, tags=None), + mock.call("datadog.tracer.api.requests", 1, tags=None), + mock.call("datadog.tracer.api.errors", 1, tags=None), ] - if hasattr(time, 'thread_time'): - histogram_calls.append(mock.call('datadog.tracer.writer.cpu_time', mock.ANY)) + if hasattr(time, "thread_time"): + histogram_calls.append(mock.call("datadog.tracer.writer.cpu_time", mock.ANY)) assert histogram_calls == self.dogstatsd.histogram.mock_calls @@ -203,9 +200,7 @@ def test_queue_full(): q.put(2) q.put([3]) q.put([4, 4]) - assert (list(q.queue) == [[1], 2, [4, 4]] or - list(q.queue) == [[1], [4, 4], [3]] or - list(q.queue) == [[4, 4], 2, [3]]) + assert list(q.queue) == [[1], 2, [4, 4]] or list(q.queue) == [[1], [4, 4], [3]] or list(q.queue) == [[4, 4], 2, [3]] assert q.dropped == 1 assert q.accepted == 4 assert q.accepted_lengths == 5 diff --git a/tests/opentracer/test_tracer.py b/tests/opentracer/test_tracer.py index 5ca46eb30c4..7888e5973f9 100644 --- a/tests/opentracer/test_tracer.py +++ b/tests/opentracer/test_tracer.py @@ -23,80 +23,77 @@ class TestTracerConfig(object): def test_config(self): """Test the configuration of the tracer""" - config = {'enabled': True} - tracer = Tracer(service_name='myservice', config=config) + config = {"enabled": True} + tracer = Tracer(service_name="myservice", config=config) - assert tracer._service_name == 'myservice' + assert tracer._service_name == "myservice" assert tracer._enabled is True def test_no_service_name(self): """A service_name should be generated if one is not provided.""" tracer = Tracer() - assert tracer._service_name == 'pytest' + assert tracer._service_name == "pytest" def test_multiple_tracer_configs(self): """Ensure that a tracer config is a copy of the passed config.""" - config = {'enabled': True} + config = {"enabled": True} - tracer1 = Tracer(service_name='serv1', config=config) - assert tracer1._service_name == 'serv1' + tracer1 = Tracer(service_name="serv1", config=config) + assert tracer1._service_name == "serv1" - config['enabled'] = False - tracer2 = Tracer(service_name='serv2', config=config) + config["enabled"] = False + tracer2 = Tracer(service_name="serv2", config=config) # Ensure tracer1's config was not mutated - assert tracer1._service_name == 'serv1' + assert tracer1._service_name == "serv1" assert tracer1._enabled is True - assert tracer2._service_name == 'serv2' + assert tracer2._service_name == "serv2" assert tracer2._enabled is False def test_invalid_config_key(self): """A config with an invalid key should raise a ConfigException.""" - config = {'enabeld': False} + config = {"enabeld": False} # No debug flag should not raise an error - tracer = Tracer(service_name='mysvc', config=config) + tracer = Tracer(service_name="mysvc", config=config) # With debug flag should raise an error - config['debug'] = True + config["debug"] = True with pytest.raises(ConfigException) as ce_info: tracer = Tracer(config=config) - assert 'enabeld' in str(ce_info) + assert "enabeld" in str(ce_info) assert tracer is not None # Test with multiple incorrect keys - config['setttings'] = {} + config["setttings"] = {} with pytest.raises(ConfigException) as ce_info: - tracer = Tracer(service_name='mysvc', config=config) - assert ['enabeld', 'setttings'] in str(ce_info) + tracer = Tracer(service_name="mysvc", config=config) + assert ["enabeld", "setttings"] in str(ce_info) assert tracer is not None def test_global_tags(self): """Global tags should be passed from the opentracer to the tracer.""" config = { - 'global_tags': { - 'tag1': 'value1', - 'tag2': 2, - }, + "global_tags": {"tag1": "value1", "tag2": 2,}, } - tracer = Tracer(service_name='mysvc', config=config) - with tracer.start_span('myop') as span: + tracer = Tracer(service_name="mysvc", config=config) + with tracer.start_span("myop") as span: # global tags should be attached to generated all datadog spans - assert span._dd_span.get_tag('tag1') == 'value1' - assert span._dd_span.get_metric('tag2') == 2 + assert span._dd_span.get_tag("tag1") == "value1" + assert span._dd_span.get_metric("tag2") == 2 - with tracer.start_span('myop2') as span2: - assert span2._dd_span.get_tag('tag1') == 'value1' - assert span2._dd_span.get_metric('tag2') == 2 + with tracer.start_span("myop2") as span2: + assert span2._dd_span.get_tag("tag1") == "value1" + assert span2._dd_span.get_metric("tag2") == 2 class TestTracer(object): def test_start_span(self, ot_tracer, writer): """Start and finish a span.""" - with ot_tracer.start_span('myop') as span: + with ot_tracer.start_span("myop") as span: pass # span should be finished when the context manager exits @@ -108,16 +105,16 @@ def test_start_span(self, ot_tracer, writer): def test_start_span_references(self, ot_tracer, writer): """Start a span using references.""" - with ot_tracer.start_span('one', references=[child_of()]): + with ot_tracer.start_span("one", references=[child_of()]): pass spans = writer.pop() assert spans[0].parent_id is None - root = ot_tracer.start_active_span('root') + root = ot_tracer.start_active_span("root") # create a child using a parent reference that is not the context parent - with ot_tracer.start_active_span('one'): - with ot_tracer.start_active_span('two', references=[child_of(root.span)]): + with ot_tracer.start_active_span("one"): + with ot_tracer.start_active_span("two", references=[child_of(root.span)]): pass root.close() @@ -127,9 +124,9 @@ def test_start_span_references(self, ot_tracer, writer): def test_start_span_custom_start_time(self, ot_tracer): """Start a span with a custom start time.""" t = 100 - with mock.patch('ddtrace.span.time_ns') as time: + with mock.patch("ddtrace.span.time_ns") as time: time.return_value = 102 * 1e9 - with ot_tracer.start_span('myop', start_time=t) as span: + with ot_tracer.start_span("myop", start_time=t) as span: pass assert span._dd_span.start == t @@ -139,8 +136,8 @@ def test_start_span_with_spancontext(self, ot_tracer, writer): """Start and finish a span using a span context as the child_of reference. """ - with ot_tracer.start_span('myop') as span: - with ot_tracer.start_span('myop', child_of=span.context) as span2: + with ot_tracer.start_span("myop") as span: + with ot_tracer.start_span("myop", child_of=span.context) as span2: pass # span should be finished when the context manager exits @@ -155,36 +152,36 @@ def test_start_span_with_spancontext(self, ot_tracer, writer): def test_start_span_with_tags(self, ot_tracer): """Create a span with initial tags.""" - tags = {'key': 'value', 'key2': 'value2'} - with ot_tracer.start_span('myop', tags=tags) as span: + tags = {"key": "value", "key2": "value2"} + with ot_tracer.start_span("myop", tags=tags) as span: pass - assert span._dd_span.get_tag('key') == 'value' - assert span._dd_span.get_tag('key2') == 'value2' + assert span._dd_span.get_tag("key") == "value" + assert span._dd_span.get_tag("key2") == "value2" def test_start_span_with_resource_name_tag(self, ot_tracer): """Create a span with the tag to set the resource name""" - tags = {'resource.name': 'value', 'key2': 'value2'} - with ot_tracer.start_span('myop', tags=tags) as span: + tags = {"resource.name": "value", "key2": "value2"} + with ot_tracer.start_span("myop", tags=tags) as span: pass # Span resource name should be set to tag value, and should not get set as # a tag on the underlying span. - assert span._dd_span.resource == 'value' - assert span._dd_span.get_tag('resource.name') is None + assert span._dd_span.resource == "value" + assert span._dd_span.get_tag("resource.name") is None # Other tags are set as normal - assert span._dd_span.get_tag('key2') == 'value2' + assert span._dd_span.get_tag("key2") == "value2" def test_start_active_span_multi_child(self, ot_tracer, writer): """Start and finish multiple child spans. This should ensure that child spans can be created 2 levels deep. """ - with ot_tracer.start_active_span('myfirstop') as scope1: + with ot_tracer.start_active_span("myfirstop") as scope1: time.sleep(0.009) - with ot_tracer.start_active_span('mysecondop') as scope2: + with ot_tracer.start_active_span("mysecondop") as scope2: time.sleep(0.007) - with ot_tracer.start_active_span('mythirdop') as scope3: + with ot_tracer.start_active_span("mythirdop") as scope3: time.sleep(0.005) # spans should be finished when the context manager exits @@ -213,11 +210,11 @@ def test_start_active_span_multi_child_siblings(self, ot_tracer, writer): This should test to ensure a parent can have multiple child spans at the same level. """ - with ot_tracer.start_active_span('myfirstop') as scope1: + with ot_tracer.start_active_span("myfirstop") as scope1: time.sleep(0.009) - with ot_tracer.start_active_span('mysecondop') as scope2: + with ot_tracer.start_active_span("mysecondop") as scope2: time.sleep(0.007) - with ot_tracer.start_active_span('mythirdop') as scope3: + with ot_tracer.start_active_span("mythirdop") as scope3: time.sleep(0.005) # spans should be finished when the context manager exits @@ -246,11 +243,11 @@ def test_start_span_manual_child_of(self, ot_tracer, writer): Spans should be created without parents since there will be no call for the active span. """ - root = ot_tracer.start_span('zero') + root = ot_tracer.start_span("zero") - with ot_tracer.start_span('one', child_of=root): - with ot_tracer.start_span('two', child_of=root): - with ot_tracer.start_span('three', child_of=root): + with ot_tracer.start_span("one", child_of=root): + with ot_tracer.start_span("two", child_of=root): + with ot_tracer.start_span("three", child_of=root): pass root.finish() @@ -261,20 +258,17 @@ def test_start_span_manual_child_of(self, ot_tracer, writer): assert spans[1].parent_id is root._dd_span.span_id assert spans[2].parent_id is root._dd_span.span_id assert spans[3].parent_id is root._dd_span.span_id - assert ( - spans[0].trace_id == spans[1].trace_id and - spans[1].trace_id == spans[2].trace_id - ) + assert spans[0].trace_id == spans[1].trace_id and spans[1].trace_id == spans[2].trace_id def test_start_span_no_active_span(self, ot_tracer, writer): """Start spans without using a scope manager. Spans should be created without parents since there will be no call for the active span. """ - with ot_tracer.start_span('one', ignore_active_span=True): - with ot_tracer.start_span('two', ignore_active_span=True): + with ot_tracer.start_span("one", ignore_active_span=True): + with ot_tracer.start_span("two", ignore_active_span=True): pass - with ot_tracer.start_span('three', ignore_active_span=True): + with ot_tracer.start_span("three", ignore_active_span=True): pass spans = writer.pop() @@ -285,15 +279,15 @@ def test_start_span_no_active_span(self, ot_tracer, writer): assert spans[2].parent_id is None # and that each span is a new trace assert ( - spans[0].trace_id != spans[1].trace_id and - spans[1].trace_id != spans[2].trace_id and - spans[0].trace_id != spans[2].trace_id + spans[0].trace_id != spans[1].trace_id + and spans[1].trace_id != spans[2].trace_id + and spans[0].trace_id != spans[2].trace_id ) def test_start_active_span_child_finish_after_parent(self, ot_tracer, writer): """Start a child span and finish it after its parent.""" - span1 = ot_tracer.start_active_span('one').span - span2 = ot_tracer.start_active_span('two').span + span1 = ot_tracer.start_active_span("one").span + span2 = ot_tracer.start_active_span("two").span span1.finish() time.sleep(0.005) span2.finish() @@ -314,7 +308,7 @@ def test_start_span_multi_intertwined(self, ot_tracer, writer): event = threading.Event() def trace_one(): - id = 11 # noqa: A001 + id = 11 # noqa: A001 with ot_tracer.start_active_span(str(id)): id += 1 with ot_tracer.start_active_span(str(id)): @@ -323,7 +317,7 @@ def trace_one(): event.set() def trace_two(): - id = 21 # noqa: A001 + id = 21 # noqa: A001 event.wait() with ot_tracer.start_active_span(str(id)): id += 1 @@ -347,12 +341,12 @@ def trace_two(): # trace_one will finish before trace_two so its spans should be written # before the spans from trace_two, let's confirm this - assert spans[0].name == '11' - assert spans[1].name == '12' - assert spans[2].name == '13' - assert spans[3].name == '21' - assert spans[4].name == '22' - assert spans[5].name == '23' + assert spans[0].name == "11" + assert spans[1].name == "12" + assert spans[2].name == "13" + assert spans[3].name == "21" + assert spans[4].name == "22" + assert spans[5].name == "23" # next let's ensure that each span has the correct parent: # trace_one @@ -366,61 +360,53 @@ def trace_two(): # finally we should ensure that the trace_ids are reasonable # trace_one - assert ( - spans[0].trace_id == spans[1].trace_id and - spans[1].trace_id == spans[2].trace_id - ) + assert spans[0].trace_id == spans[1].trace_id and spans[1].trace_id == spans[2].trace_id # traces should be independent assert spans[2].trace_id != spans[3].trace_id # trace_two - assert ( - spans[3].trace_id == spans[4].trace_id and - spans[4].trace_id == spans[5].trace_id - ) + assert spans[3].trace_id == spans[4].trace_id and spans[4].trace_id == spans[5].trace_id def test_start_active_span(self, ot_tracer, writer): - with ot_tracer.start_active_span('one') as scope: + with ot_tracer.start_active_span("one") as scope: pass - assert scope.span._dd_span.name == 'one' + assert scope.span._dd_span.name == "one" assert scope.span.finished spans = writer.pop() assert spans def test_start_active_span_finish_on_close(self, ot_tracer, writer): - with ot_tracer.start_active_span('one', finish_on_close=False) as scope: + with ot_tracer.start_active_span("one", finish_on_close=False) as scope: pass - assert scope.span._dd_span.name == 'one' + assert scope.span._dd_span.name == "one" assert not scope.span.finished spans = writer.pop() assert not spans def test_start_active_span_nested(self, ot_tracer): """Test the active span of multiple nested calls of start_active_span.""" - with ot_tracer.start_active_span('one') as outer_scope: + with ot_tracer.start_active_span("one") as outer_scope: assert ot_tracer.active_span == outer_scope.span - with ot_tracer.start_active_span('two') as inner_scope: + with ot_tracer.start_active_span("two") as inner_scope: assert ot_tracer.active_span == inner_scope.span - with ot_tracer.start_active_span( - 'three' - ) as innest_scope: # why isn't it innest? innermost so verbose + with ot_tracer.start_active_span("three") as innest_scope: # why isn't it innest? innermost so verbose assert ot_tracer.active_span == innest_scope.span - with ot_tracer.start_active_span('two') as inner_scope: + with ot_tracer.start_active_span("two") as inner_scope: assert ot_tracer.active_span == inner_scope.span assert ot_tracer.active_span == outer_scope.span assert ot_tracer.active_span is None def test_start_active_span_trace(self, ot_tracer, writer): """Test the active span of multiple nested calls of start_active_span.""" - with ot_tracer.start_active_span('one') as outer_scope: - outer_scope.span.set_tag('outer', 2) - with ot_tracer.start_active_span('two') as inner_scope: - inner_scope.span.set_tag('inner', 3) - with ot_tracer.start_active_span('two') as inner_scope: - inner_scope.span.set_tag('inner', 3) - with ot_tracer.start_active_span('three') as innest_scope: - innest_scope.span.set_tag('innerest', 4) + with ot_tracer.start_active_span("one") as outer_scope: + outer_scope.span.set_tag("outer", 2) + with ot_tracer.start_active_span("two") as inner_scope: + inner_scope.span.set_tag("inner", 3) + with ot_tracer.start_active_span("two") as inner_scope: + inner_scope.span.set_tag("inner", 3) + with ot_tracer.start_active_span("three") as innest_scope: + innest_scope.span.set_tag("innerest", 4) spans = writer.pop() @@ -474,9 +460,7 @@ def test_http_headers_base(self, ot_tracer): def test_http_headers_baggage(self, ot_tracer): """extract should undo inject for http headers.""" - span_ctx = SpanContext( - trace_id=123, span_id=456, baggage={'test': 4, 'test2': 'string'} - ) + span_ctx = SpanContext(trace_id=123, span_id=456, baggage={"test": 4, "test2": "string"}) carrier = {} ot_tracer.inject(span_ctx, Format.HTTP_HEADERS, carrier) @@ -497,9 +481,7 @@ def test_empty_propagated_context(self, ot_tracer): def test_text(self, ot_tracer): """extract should undo inject for http headers""" - span_ctx = SpanContext( - trace_id=123, span_id=456, baggage={'test': 4, 'test2': 'string'} - ) + span_ctx = SpanContext(trace_id=123, span_id=456, baggage={"test": 4, "test2": "string"}) carrier = {} ot_tracer.inject(span_ctx, Format.TEXT_MAP, carrier) @@ -512,9 +494,7 @@ def test_text(self, ot_tracer): def test_corrupted_propagated_context(self, ot_tracer): """Corrupted context should raise a SpanContextCorruptedException.""" - span_ctx = SpanContext( - trace_id=123, span_id=456, baggage={'test': 4, 'test2': 'string'} - ) + span_ctx = SpanContext(trace_id=123, span_id=456, baggage={"test": 4, "test2": "string"}) carrier = {} ot_tracer.inject(span_ctx, Format.TEXT_MAP, carrier) @@ -530,12 +510,12 @@ def test_corrupted_propagated_context(self, ot_tracer): def test_immutable_span_context(self, ot_tracer): """Span contexts should be immutable.""" - with ot_tracer.start_span('root') as root: + with ot_tracer.start_span("root") as root: ctx_before = root.context - root.set_baggage_item('test', 2) + root.set_baggage_item("test", 2) assert ctx_before is not root.context - with ot_tracer.start_span('child') as level1: - with ot_tracer.start_span('child') as level2: + with ot_tracer.start_span("child") as level1: + with ot_tracer.start_span("child") as level2: pass assert root.context is not level1.context assert level2.context is not level1.context @@ -543,27 +523,27 @@ def test_immutable_span_context(self, ot_tracer): def test_inherited_baggage(self, ot_tracer): """Baggage should be inherited by child spans.""" - with ot_tracer.start_active_span('root') as root: + with ot_tracer.start_active_span("root") as root: # this should be passed down to the child - root.span.set_baggage_item('root', 1) - root.span.set_baggage_item('root2', 1) - with ot_tracer.start_active_span('child') as level1: - level1.span.set_baggage_item('level1', 1) - with ot_tracer.start_active_span('child') as level2: - level2.span.set_baggage_item('level2', 1) + root.span.set_baggage_item("root", 1) + root.span.set_baggage_item("root2", 1) + with ot_tracer.start_active_span("child") as level1: + level1.span.set_baggage_item("level1", 1) + with ot_tracer.start_active_span("child") as level2: + level2.span.set_baggage_item("level2", 1) # ensure immutability assert level1.span.context is not root.span.context assert level2.span.context is not level1.span.context # level1 should have inherited the baggage of root - assert level1.span.get_baggage_item('root') - assert level1.span.get_baggage_item('root2') + assert level1.span.get_baggage_item("root") + assert level1.span.get_baggage_item("root2") # level2 should have inherited the baggage of both level1 and level2 - assert level2.span.get_baggage_item('root') - assert level2.span.get_baggage_item('root2') - assert level2.span.get_baggage_item('level1') - assert level2.span.get_baggage_item('level2') + assert level2.span.get_baggage_item("root") + assert level2.span.get_baggage_item("root2") + assert level2.span.get_baggage_item("level1") + assert level2.span.get_baggage_item("level2") class TestTracerCompatibility(object): @@ -574,14 +554,14 @@ def test_required_dd_fields(self): by the underlying datadog tracer. """ # a service name is required - tracer = Tracer('service') - with tracer.start_span('my_span') as span: + tracer = Tracer("service") + with tracer.start_span("my_span") as span: assert span._dd_span.service def test_set_global_tracer(): """Sanity check for set_global_tracer""" - my_tracer = Tracer('service') + my_tracer = Tracer("service") set_global_tracer(my_tracer) assert opentracing.tracer is my_tracer diff --git a/tests/propagation/test_http.py b/tests/propagation/test_http.py index 6249c037a4a..267954fd088 100644 --- a/tests/propagation/test_http.py +++ b/tests/propagation/test_http.py @@ -19,61 +19,55 @@ class TestHttpPropagation(TestCase): def test_inject(self): tracer = get_dummy_tracer() - with tracer.trace('global_root_span') as span: + with tracer.trace("global_root_span") as span: span.context.sampling_priority = 2 - span.context._dd_origin = 'synthetics' + span.context._dd_origin = "synthetics" headers = {} propagator = HTTPPropagator() propagator.inject(span.context, headers) assert int(headers[HTTP_HEADER_TRACE_ID]) == span.trace_id assert int(headers[HTTP_HEADER_PARENT_ID]) == span.span_id - assert ( - int(headers[HTTP_HEADER_SAMPLING_PRIORITY]) == - span.context.sampling_priority - ) - assert ( - headers[HTTP_HEADER_ORIGIN] == - span.context._dd_origin - ) + assert int(headers[HTTP_HEADER_SAMPLING_PRIORITY]) == span.context.sampling_priority + assert headers[HTTP_HEADER_ORIGIN] == span.context._dd_origin def test_extract(self): tracer = get_dummy_tracer() headers = { - 'x-datadog-trace-id': '1234', - 'x-datadog-parent-id': '5678', - 'x-datadog-sampling-priority': '1', - 'x-datadog-origin': 'synthetics', + "x-datadog-trace-id": "1234", + "x-datadog-parent-id": "5678", + "x-datadog-sampling-priority": "1", + "x-datadog-origin": "synthetics", } propagator = HTTPPropagator() context = propagator.extract(headers) tracer.context_provider.activate(context) - with tracer.trace('local_root_span') as span: + with tracer.trace("local_root_span") as span: assert span.trace_id == 1234 assert span.parent_id == 5678 assert span.context.sampling_priority == 1 - assert span.context._dd_origin == 'synthetics' + assert span.context._dd_origin == "synthetics" def test_WSGI_extract(self): """Ensure we support the WSGI formatted headers as well.""" tracer = get_dummy_tracer() headers = { - 'HTTP_X_DATADOG_TRACE_ID': '1234', - 'HTTP_X_DATADOG_PARENT_ID': '5678', - 'HTTP_X_DATADOG_SAMPLING_PRIORITY': '1', - 'HTTP_X_DATADOG_ORIGIN': 'synthetics', + "HTTP_X_DATADOG_TRACE_ID": "1234", + "HTTP_X_DATADOG_PARENT_ID": "5678", + "HTTP_X_DATADOG_SAMPLING_PRIORITY": "1", + "HTTP_X_DATADOG_ORIGIN": "synthetics", } propagator = HTTPPropagator() context = propagator.extract(headers) tracer.context_provider.activate(context) - with tracer.trace('local_root_span') as span: + with tracer.trace("local_root_span") as span: assert span.trace_id == 1234 assert span.parent_id == 5678 assert span.context.sampling_priority == 1 - assert span.context._dd_origin == 'synthetics' + assert span.context._dd_origin == "synthetics" diff --git a/tox.ini b/tox.ini index 6ce88549dda..d34fffd83d4 100644 --- a/tox.ini +++ b/tox.ini @@ -843,8 +843,9 @@ exclude= # Ignore: # A003: XXX is a python builtin, consider renaming the class attribute # G201 Logging: .exception(...) should be used instead of .error(..., exc_info=True) +# E231,W503: not respected by black # We ignore most of the D errors because there are too many; the goal is to fix them eventually -ignore = W504,A003,G201,D100,D101,D102,D103,D104,D105,D106,D107,D200,D202,D204,D205,D208,D210,D300,D400,D401,D403,D413 +ignore = W503,E231,A003,G201,D100,D101,D102,D103,D104,D105,D106,D107,D200,D202,D204,D205,D208,D210,D300,D400,D401,D403,D413 enable-extensions=G rst-roles = class,meth,obj,ref rst-directives = py:data