Skip to content

Commit

Permalink
Remove Python 2 todos from base check (#18913)
Browse files Browse the repository at this point in the history
  • Loading branch information
iliakur authored Oct 25, 2024
1 parent 6dd1b14 commit 816bf76
Show file tree
Hide file tree
Showing 12 changed files with 33 additions and 69 deletions.
6 changes: 2 additions & 4 deletions datadog_checks_base/datadog_checks/base/checks/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -556,8 +556,7 @@ def load_configuration_models(self, package_path=None):
def load_configuration_model(import_path, model_name, config, context):
try:
package = importlib.import_module(import_path)
# TODO: remove the type ignore when we drop Python 2
except ModuleNotFoundError as e: # type: ignore
except ModuleNotFoundError as e:
# Don't fail if there are no models
if str(e).startswith('No module named '):
return
Expand All @@ -568,8 +567,7 @@ def load_configuration_model(import_path, model_name, config, context):
if model is not None:
try:
config_model = model.model_validate(config, context=context)
# TODO: remove the type ignore when we drop Python 2
except ValidationError as e: # type: ignore
except ValidationError as e:
errors = e.errors()
num_errors = len(errors)
message_lines = [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# (C) Datadog, Inc. 2020-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
# TODO: remove ignore when we stop invoking Mypy with --py2
# type: ignore
from collections import ChainMap
from contextlib import contextmanager

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# (C) Datadog, Inc. 2021-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
# TODO: when we stop invoking Mypy with --py2, remove ignore and use f-strings
# type: ignore
from collections import ChainMap
from contextlib import contextmanager, suppress

Expand Down Expand Up @@ -74,7 +72,7 @@ def _query_counters(self):
# https://mhammond.github.io/pywin32/win32pdh__CollectQueryData_meth.html
win32pdh.CollectQueryData(self._connection.query_handle)
except pywintypes.error as error:
message = 'Error querying performance counters: {}'.format(error.strerror)
message = f'Error querying performance counters: {error.strerror}'
self.submit_health_check(self.CRITICAL, message=message)
self.log.error(message)
return
Expand All @@ -93,19 +91,19 @@ def configure_perf_objects(self):
config = self.get_config_with_defaults()
server_tag = config.get('server_tag') or 'server'
use_localized_counters = is_affirmative(self.init_config.get('use_localized_counters', False))
tags = ['{}:{}'.format(server_tag, self._connection.server)]
tags = [f'{server_tag}:{self._connection.server}']
tags.extend(config.get('tags', []))
self._static_tags = tuple(tags)

for option_name in ('metrics', 'extra_metrics'):
metric_config = config.get(option_name, {})
if not isinstance(metric_config, dict):
raise ConfigTypeError('Setting `{}` must be a mapping'.format(option_name))
raise ConfigTypeError(f'Setting `{option_name}` must be a mapping')

for object_name, object_config in metric_config.items():
if not isinstance(object_config, dict):
raise ConfigTypeError(
'Performance object `{}` in setting `{}` must be a mapping'.format(object_name, option_name)
f'Performance object `{object_name}` in setting `{option_name}` must be a mapping'
)

perf_object = self.get_perf_object(
Expand Down Expand Up @@ -184,12 +182,12 @@ def get_config_with_defaults(self):
metrics_config = updated_config['metrics'] = {}
for object_name, config in default_config['metrics'].items():
new_config = config.copy()
new_config['name'] = '{}.{}'.format(self.__NAMESPACE__, new_config['name'])
new_config['name'] = f'{self.__NAMESPACE__}.{new_config["name"]}'
metrics_config[object_name] = new_config

# Ensure idempotency in case this method is called multiple times due to configuration errors
if self.namespace:
self.SERVICE_CHECK_HEALTH = '{}.{}'.format(self.__NAMESPACE__, self.SERVICE_CHECK_HEALTH)
self.SERVICE_CHECK_HEALTH = f'{self.__NAMESPACE__}.{self.SERVICE_CHECK_HEALTH}'

self.namespace = ''

Expand Down
5 changes: 1 addition & 4 deletions datadog_checks_base/datadog_checks/base/utils/db/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import time
from concurrent.futures.thread import ThreadPoolExecutor
from ipaddress import IPv4Address
from itertools import chain
from typing import Any, Callable, Dict, List, Tuple # noqa: F401

from cachetools import TTLCache
Expand Down Expand Up @@ -79,9 +78,7 @@ def transformer(_sources, *call_args, **kwargs):
# type: (Dict[str, Any], Tuple[str, Any], Dict[str, Any]) -> None
kwargs.update(modifiers)

# TODO: When Python 2 goes away simply do:
# submit_method(*creation_args, *call_args, **kwargs)
submit_method(*chain(creation_args, call_args), **kwargs)
submit_method(*creation_args, *call_args, **kwargs)

return transformer

Expand Down
32 changes: 11 additions & 21 deletions datadog_checks_base/datadog_checks/base/utils/headers.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,25 @@
# (C) Datadog, Inc. 2018-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
from collections import OrderedDict

from datadog_checks.base.agent import datadog_agent


def _get_common_headers():
return OrderedDict(
(
# Required by the HTTP spec. If missing, some websites may return junk (eg 404 responses).
('Accept', '*/*'),
# Allow websites to send compressed responses.
# (In theory, not including this header allows servers to send anything, but in practice servers are
# typically conservative and send plain text, i.e. uncompressed responses.)
('Accept-Encoding', 'gzip, deflate'),
# NOTE: we don't include a 'Connection' header. This is equivalent to using the spec-specific default
# behavior, i.e. 'keep-alive' for HTTP/1.1, and 'close' for HTTP/1.0.
)
)
return { # Required by the HTTP spec. If missing, some websites may return junk (eg 404 responses).
'Accept': '*/*',
# Allow websites to send compressed responses.
# (In theory, not including this header allows servers to send anything, but in practice servers are
# typically conservative and send plain text, i.e. uncompressed responses.)
'Accept-Encoding': 'gzip, deflate',
# NOTE: we don't include a 'Connection' header. This is equivalent to using the spec-specific default
# behavior, i.e. 'keep-alive' for HTTP/1.1, and 'close' for HTTP/1.0.
}


def get_default_headers():
# http://docs.python-requests.org/en/master/user/advanced/#header-ordering
# TODO: Use built-in when we drop Python 2 as dictionaries are guaranteed to be ordered in Python 3.6+ (and PyPy)
headers = OrderedDict(
(
# Default to `0.0.0` if no version is found
('User-Agent', 'Datadog Agent/{}'.format(datadog_agent.get_version() or '0.0.0')),
)
)
# Default to `0.0.0` if no version is found
headers = {'User-Agent': 'Datadog Agent/{}'.format(datadog_agent.get_version() or '0.0.0')}
headers.update(_get_common_headers())
return headers

Expand Down
5 changes: 1 addition & 4 deletions datadog_checks_base/datadog_checks/base/utils/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,9 @@ def get_timestamp(dt=None):
If `dt` is not specified or `None`, the current time in UTC is assumed.
"""
if dt is None:
# The precision is different between Python 2 and 3
return epoch_offset()

# TODO: when we drop support for Python 2 switch to:
# return ensure_aware_datetime(dt).timestamp()
return (ensure_aware_datetime(dt) - EPOCH).total_seconds()
return ensure_aware_datetime(dt).timestamp()


def get_current_datetime(tz=UTC):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
# (C) Datadog, Inc. 2024-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
from datadog_checks.base.checks.logs.crawler.base import LogCrawlerCheck
from datadog_checks.base.checks.logs.crawler.stream import LogRecord, LogStream


# TODO: Remove lazy imports and `.format` calls when we drop support for Python 2
def test_submission(dd_run_check, datadog_agent):
from datadog_checks.base.checks.logs.crawler.base import LogCrawlerCheck
from datadog_checks.base.checks.logs.crawler.stream import LogRecord, LogStream

class TestLogStream(LogStream):
def __init__(self, start, **kwargs):
Expand All @@ -17,11 +16,11 @@ def __init__(self, start, **kwargs):
def records(self, cursor=None):
start = cursor['counter'] + 1 if cursor is not None else self.start
for i in range(start, start + 2):
message = '{} {}'.format(self.name, i)
message = f'{self.name} {i}'
data = (
{'message': message}
if i % 2 == 0
else {'message': message, 'ddtags': self.construct_tags(['{}:tag{}'.format(self.name, i)])}
else {'message': message, 'ddtags': self.construct_tags([f'{self.name}:tag{i}'])}
)
yield LogRecord(data, cursor={'counter': i})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,12 @@
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
from datadog_checks.base import OpenMetricsBaseCheckV2
from datadog_checks.base.checks.openmetrics.v2.scraper import OpenMetricsCompatibilityScraper

# TODO: remove `try` when we drop Python 2
try:
from datadog_checks.base.checks.openmetrics.v2.scraper import OpenMetricsCompatibilityScraper

class LegacyCheck(OpenMetricsBaseCheckV2):
def create_scraper(self, config):
return OpenMetricsCompatibilityScraper(self, self.get_config_with_defaults(config))

except Exception:
pass
class LegacyCheck(OpenMetricsBaseCheckV2):
def create_scraper(self, config):
return OpenMetricsCompatibilityScraper(self, self.get_config_with_defaults(config))


def get_legacy_check(instance=None, init_config=None):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,6 @@ def test_refresh_after_connection_error(self):
write_file(token_file, '\nsecret1\n')
http.get('https://www.google.com')

# TODO: use nonlocal when we drop Python 2 support
counter = {'errors': 0}

def raise_error_once(*args, **kwargs):
Expand Down
2 changes: 0 additions & 2 deletions datadog_checks_base/tests/base/utils/http/test_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,6 @@ def test_no_proxy_uris_coverage():

http.no_proxy_uris.__iter__ = lambda self, *args, **kwargs: iter([])
http.no_proxy_uris.__bool__ = lambda self, *args, **kwargs: True
# TODO: Remove with Python 2
http.no_proxy_uris.__nonzero__ = lambda self, *args, **kwargs: True

http.get('https://www.google.com')

Expand Down
7 changes: 3 additions & 4 deletions datadog_checks_base/tests/models/test_types.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
# (C) Datadog, Inc. 2021-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
from types import MappingProxyType

from datadog_checks.base.utils.models.validation.utils import make_immutable

def test_make_immutable():
# TODO: move imports up top when we drop Python 2
from types import MappingProxyType

from datadog_checks.base.utils.models.validation.utils import make_immutable
def test_make_immutable():

obj = make_immutable(
{
Expand Down
6 changes: 1 addition & 5 deletions datadog_checks_base/tests/test_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
import logging
import sys
import warnings

import mock
Expand Down Expand Up @@ -36,10 +35,7 @@ def test_logging_capture_warnings():

warnings.warn("hello-world") # noqa: B028
assert log_warning.call_count == 1
# _showwarning provides only one parameter to Logger.warning on py3.11+ but two before
# See https://github.com/python/cpython/pull/30975
# TODO: remove when python 2 is dropped
warning_arg_index = 0 if sys.version_info >= (3, 11) else 1
warning_arg_index = 0
msg = log_warning.mock_calls[0].args[warning_arg_index]
assert "hello-world" in msg

Expand Down

0 comments on commit 816bf76

Please sign in to comment.