diff --git a/LICENSE-3rdparty.csv b/LICENSE-3rdparty.csv index 5b179aba8d955..64f52d5c0f1ed 100644 --- a/LICENSE-3rdparty.csv +++ b/LICENSE-3rdparty.csv @@ -37,7 +37,6 @@ flup-py3,Vendor,BSD-3-Clause,"Copyright (c) 2005, 2006 Allan Saddi '3.0' futures==3.4.0; python_version < '3.0' gearman==2.0.2; sys_platform != 'win32' and python_version < '3.0' -immutables==0.19; python_version > '3.0' importlib-metadata==2.1.3; python_version < '3.8' in-toto==1.0.1; python_version > '3.0' ipaddress==1.0.23; python_version < '3.0' @@ -59,7 +58,7 @@ psutil==5.9.0 psycopg2-binary==2.8.6; sys_platform != 'darwin' or platform_machine != 'arm64' pyasn1==0.4.6 pycryptodomex==3.10.1 -pydantic==1.10.8; python_version > '3.0' +pydantic==2.0; python_version > '3.0' pyjwt==1.7.1; python_version < '3.0' pyjwt==2.7.0; python_version > '3.0' pymongo[srv]==4.3.3; python_version >= '3.8' diff --git a/datadog_checks_base/datadog_checks/base/utils/models/types.py b/datadog_checks_base/datadog_checks/base/utils/models/types.py deleted file mode 100644 index 2e183d205c4ab..0000000000000 --- a/datadog_checks_base/datadog_checks/base/utils/models/types.py +++ /dev/null @@ -1,16 +0,0 @@ -# (C) Datadog, Inc. 2021-present -# All rights reserved -# Licensed under a 3-clause BSD style license (see LICENSE) -from collections.abc import Mapping, Sequence - -from immutables import Map - - -def make_immutable_check_config(obj): - if isinstance(obj, Sequence) and not isinstance(obj, str): - return tuple(make_immutable_check_config(item) for item in obj) - elif isinstance(obj, Mapping): - # There are no ordering guarantees, see https://github.com/MagicStack/immutables/issues/57 - return Map((k, make_immutable_check_config(v)) for k, v in obj.items()) - - return obj diff --git a/datadog_checks_base/datadog_checks/base/utils/models/validation/utils.py b/datadog_checks_base/datadog_checks/base/utils/models/validation/utils.py index 6690b172ede4c..d5b5c11fe1aae 100644 --- a/datadog_checks_base/datadog_checks/base/utils/models/validation/utils.py +++ b/datadog_checks_base/datadog_checks/base/utils/models/validation/utils.py @@ -1,11 +1,16 @@ # (C) Datadog, Inc. 2021-present # All rights reserved # Licensed under a 3-clause BSD style license (see LICENSE) -from ..types import make_immutable_check_config +from types import MappingProxyType -def make_immutable(value): - return make_immutable_check_config(value) +def make_immutable(obj): + if isinstance(obj, list): + return tuple(make_immutable(item) for item in obj) + elif isinstance(obj, dict): + return MappingProxyType({k: make_immutable(v) for k, v in obj.items()}) + + return obj def handle_deprecations(config_section, deprecations, fields, context): diff --git a/datadog_checks_base/pyproject.toml b/datadog_checks_base/pyproject.toml index 14b21fd082f19..a01e0f7adeebf 100644 --- a/datadog_checks_base/pyproject.toml +++ b/datadog_checks_base/pyproject.toml @@ -47,7 +47,6 @@ deps = [ "ddtrace==0.32.2; sys_platform == 'win32' and python_version < '3.0'", "ddtrace==0.53.2; (sys_platform != 'win32' and (sys_platform != 'darwin' or platform_machine != 'arm64' and python_version > '3.0')) or python_version > '3.0'", "enum34==1.1.10; python_version < '3.0'", - "immutables==0.19; python_version > '3.0'", "importlib-metadata==2.1.3; python_version < '3.8'", "ipaddress==1.0.23; python_version < '3.0'", "jellyfish==1.0.0; python_version > '3.0'", diff --git a/datadog_checks_base/tests/models/config_models/instance.py b/datadog_checks_base/tests/models/config_models/instance.py index d879e003da783..17114e6bd9f2d 100644 --- a/datadog_checks_base/tests/models/config_models/instance.py +++ b/datadog_checks_base/tests/models/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,22 +22,24 @@ class Obj(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - bar: Optional[Sequence[str]] = None + bar: Optional[tuple[str, ...]] = None foo: bool class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - array: Optional[Sequence[str]] = None + array: Optional[tuple[str, ...]] = None deprecated: Optional[str] = None flag: Optional[bool] = None hyphenated_name: Optional[str] = Field(None, alias='hyphenated-name') - mapping: Optional[Mapping[str, Any]] = None + mapping: Optional[MappingProxyType[str, Any]] = None obj: Optional[Obj] = None pass_: Optional[str] = Field(None, alias='pass') pid: Optional[int] = None @@ -62,6 +65,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_base/tests/models/config_models/shared.py b/datadog_checks_base/tests/models/config_models/shared.py index 6c63a9244322b..ac153729ced5d 100644 --- a/datadog_checks_base/tests/models/config_models/shared.py +++ b/datadog_checks_base/tests/models/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) deprecated: Optional[str] = None @@ -37,6 +38,10 @@ def _handle_deprecations(cls, values, info): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_base/tests/models/test_types.py b/datadog_checks_base/tests/models/test_types.py index e783d30916ce4..502c665817d07 100644 --- a/datadog_checks_base/tests/models/test_types.py +++ b/datadog_checks_base/tests/models/test_types.py @@ -6,13 +6,13 @@ pytestmark = [requires_py3] -def test_make_immutable_check_config(): +def test_make_immutable(): # TODO: move imports up top when we drop Python 2 - from immutables import Map + from types import MappingProxyType - from datadog_checks.base.utils.models.types import make_immutable_check_config + from datadog_checks.base.utils.models.validation import make_immutable - obj = make_immutable_check_config( + obj = make_immutable( { 'string': 'foo', 'integer': 9000, @@ -23,7 +23,7 @@ def test_make_immutable_check_config(): } ) - assert isinstance(obj, Map) + assert isinstance(obj, MappingProxyType) assert len(obj) == 6 assert isinstance(obj['string'], str) assert obj['string'] == 'foo' @@ -35,10 +35,10 @@ def test_make_immutable_check_config(): assert obj['boolean'] is True assert isinstance(obj['array'], tuple) assert len(obj['array']) == 2 - assert isinstance(obj['array'][0], Map) + assert isinstance(obj['array'][0], MappingProxyType) assert obj['array'][0]['key'] == 'foo' - assert isinstance(obj['array'][1], Map) + assert isinstance(obj['array'][1], MappingProxyType) assert obj['array'][1]['key'] == 'bar' - assert isinstance(obj['mapping'], Map) + assert isinstance(obj['mapping'], MappingProxyType) assert len(obj['mapping']) == 1 assert obj['mapping']['foo'] == 'bar' diff --git a/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/models.py b/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/models.py index 2ff8cde58eb25..1180cf477afea 100644 --- a/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/models.py +++ b/datadog_checks_dev/datadog_checks/dev/tooling/commands/validate/models.py @@ -127,7 +127,7 @@ def models(ctx, check, sync, verbose): models_location = get_models_location(check) # TODO: Remove when all integrations have models - if not sync and not dir_exists(models_location): + if not dir_exists(models_location): continue model_consumer = ModelConsumer(spec.data, code_formatter) diff --git a/datadog_checks_dev/datadog_checks/dev/tooling/configuration/consumers/model/model_consumer.py b/datadog_checks_dev/datadog_checks/dev/tooling/configuration/consumers/model/model_consumer.py index 3b9948dada87b..77863dab97b23 100644 --- a/datadog_checks_dev/datadog_checks/dev/tooling/configuration/consumers/model/model_consumer.py +++ b/datadog_checks_dev/datadog_checks/dev/tooling/configuration/consumers/model/model_consumer.py @@ -110,10 +110,8 @@ def _process_section(self, section) -> (List[Tuple[str, str]], dict, ModelInfo): dump_resolve_reference_action=model_types.dump_resolve_reference_action, enum_field_as_literal=LiteralType.All, encoding='utf-8', - use_generic_container_types=True, enable_faux_immutability=True, - # TODO: uncomment when the Agent upgrades Python to 3.9 - # use_standard_collections=True, + use_standard_collections=True, strip_default_none=True, # https://github.com/koxudaxi/datamodel-code-generator/pull/173 field_constraints=True, diff --git a/datadog_checks_dev/datadog_checks/dev/tooling/configuration/consumers/model/model_file.py b/datadog_checks_dev/datadog_checks/dev/tooling/configuration/consumers/model/model_file.py index 2c010611fd99b..53cddb68e5699 100644 --- a/datadog_checks_dev/datadog_checks/dev/tooling/configuration/consumers/model/model_file.py +++ b/datadog_checks_dev/datadog_checks/dev/tooling/configuration/consumers/model/model_file.py @@ -24,6 +24,7 @@ def build_model_file( options_with_defaults = len(model_info.defaults_file_lines) > 0 model_file_lines = parsed_document.splitlines() _add_imports(model_file_lines, options_with_defaults, len(model_info.deprecation_data)) + _fix_types(model_file_lines) if model_id in model_info.deprecation_data: model_file_lines += _define_deprecation_functions(model_id, section_name) @@ -35,8 +36,14 @@ def build_model_file( if line.startswith(' model_config = ConfigDict('): config_lines.append(i) - final_config_line = config_lines[-1] - model_file_lines.insert(final_config_line + 1, ' validate_default=True,') + extra_config_lines = [' arbitrary_types_allowed=True,'] + for i, line_number in enumerate(config_lines): + index = line_number + (len(extra_config_lines) * i) + 1 + for line in extra_config_lines: + model_file_lines.insert(index, line) + + if i == len(config_lines) - 1: + model_file_lines.insert(index, ' validate_default=True,') model_file_lines.append('') model_file_contents = '\n'.join(model_file_lines) @@ -47,10 +54,16 @@ def build_model_file( def _add_imports(model_file_lines, need_defaults, need_deprecations): import_lines = [] + mapping_found = False + typing_location = -1 for i, line in enumerate(model_file_lines): if line.startswith('from '): import_lines.append(i) + if line.startswith('from typing '): + typing_location = i + elif 'dict[' in line: + mapping_found = True # pydantic imports final_import_line = import_lines[-1] @@ -60,14 +73,22 @@ def _add_imports(model_file_lines, need_defaults, need_deprecations): model_file_lines[index] += ', field_validator, model_validator' break + if mapping_found: + if typing_location == -1: + insertion_index = import_lines[0] + 1 + model_file_lines.insert(insertion_index, 'from types import MappingProxyType') + model_file_lines.insert(insertion_index, '') + final_import_line += 2 + else: + model_file_lines.insert(typing_location, 'from types import MappingProxyType') + final_import_line += 1 + local_imports = ['validators'] if need_defaults: local_imports.append('defaults') if need_deprecations: local_imports.append('deprecations') - local_imports_part = ', '.join(sorted(local_imports)) - local_import_start_location = final_import_line + 1 for line in reversed( ( @@ -75,12 +96,36 @@ def _add_imports(model_file_lines, need_defaults, need_deprecations): 'from datadog_checks.base.utils.functions import identity', 'from datadog_checks.base.utils.models import validation', '', - f'from . import {local_imports_part}', + f'from . import {", ".join(sorted(local_imports))}', ) ): model_file_lines.insert(local_import_start_location, line) +def _fix_types(model_file_lines): + for i, line in enumerate(model_file_lines): + line = model_file_lines[i] = line.replace('dict[', 'MappingProxyType[') + if 'list[' not in line: + continue + + buffer = bytearray() + containers = [] + + for char in line: + if char == '[': + if buffer[-4:] == b'list': + containers.append(True) + buffer[-4:] = b'tuple' + else: + containers.append(False) + elif char == ']' and containers.pop(): + buffer.extend(b', ...') + + buffer.append(ord(char)) + + model_file_lines[i] = buffer.decode('utf-8') + + def _define_deprecation_functions(model_id, section_name): model_file_lines = [''] model_file_lines.append(" @model_validator(mode='before')") @@ -114,6 +159,11 @@ def _define_validator_functions(model_id, validator_data, need_defaults): model_file_lines.append('') model_file_lines.append(f" return getattr(defaults, f'{model_id}_{{info.field_name}}', lambda: value)()") + model_file_lines.append('') + model_file_lines.append(" @field_validator('*', mode='before')") + model_file_lines.append(' def _correct_initial_types(cls, value):') + model_file_lines.append(' return validation.utils.make_immutable(value)') + model_file_lines.append('') model_file_lines.append(" @field_validator('*')") model_file_lines.append(' def _run_validations(cls, value, info):') diff --git a/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/check/{check_name}/datadog_checks/{check_name}/config_models/instance.py b/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/check/{check_name}/datadog_checks/{check_name}/config_models/instance.py index cf2c08158a52f..9d26def89ae0f 100644 --- a/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/check/{check_name}/datadog_checks/{check_name}/config_models/instance.py +++ b/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/check/{check_name}/datadog_checks/{check_name}/config_models/instance.py @@ -4,7 +4,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -17,12 +17,13 @@ class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) empty_default_hostname: Optional[bool] = None min_collection_interval: Optional[float] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -37,6 +38,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{{info.field_name}}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/check/{check_name}/datadog_checks/{check_name}/config_models/shared.py b/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/check/{check_name}/datadog_checks/{check_name}/config_models/shared.py index 9ff64c128faae..f162aaffeb5cf 100644 --- a/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/check/{check_name}/datadog_checks/{check_name}/config_models/shared.py +++ b/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/check/{check_name}/datadog_checks/{check_name}/config_models/shared.py @@ -17,6 +17,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -34,6 +35,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{{info.field_name}}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/jmx/{check_name}/datadog_checks/{check_name}/config_models/instance.py b/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/jmx/{check_name}/datadog_checks/{check_name}/config_models/instance.py index 48711372c14ac..fb056ddc4adae 100644 --- a/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/jmx/{check_name}/datadog_checks/{check_name}/config_models/instance.py +++ b/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/jmx/{check_name}/datadog_checks/{check_name}/config_models/instance.py @@ -4,7 +4,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -17,6 +17,7 @@ class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_jvm_metrics: Optional[bool] = None @@ -36,7 +37,7 @@ class InstanceConfig(BaseModel): rmi_connection_timeout: Optional[float] = None rmi_registry_ssl: Optional[bool] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tools_jar_path: Optional[str] = None trust_store_password: Optional[str] = None trust_store_path: Optional[str] = None @@ -55,6 +56,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{{info.field_name}}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/jmx/{check_name}/datadog_checks/{check_name}/config_models/shared.py b/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/jmx/{check_name}/datadog_checks/{check_name}/config_models/shared.py index 3b34891a38ca7..e4f3a7744865a 100644 --- a/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/jmx/{check_name}/datadog_checks/{check_name}/config_models/shared.py +++ b/datadog_checks_dev/datadog_checks/dev/tooling/templates/integration/jmx/{check_name}/datadog_checks/{check_name}/config_models/shared.py @@ -4,7 +4,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -17,10 +18,11 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_metrics: bool - conf: Optional[Sequence[Mapping[str, Any]]] = None + conf: Optional[tuple[MappingProxyType[str, Any], ...]] = None is_jmx: bool new_gc_metrics: Optional[bool] = None service: Optional[str] = None @@ -39,6 +41,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{{info.field_name}}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_all_required.py b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_all_required.py index d33c17c579d73..d351a599d2f46 100644 --- a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_all_required.py +++ b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_all_required.py @@ -67,6 +67,7 @@ def config(self) -> InstanceConfig: class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) foo: str @@ -75,6 +76,10 @@ class InstanceConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_instance', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_array.py b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_array.py index 2b9087df0d2f2..dde0a3bac1e5a 100644 --- a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_array.py +++ b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_array.py @@ -62,7 +62,7 @@ def config(self) -> InstanceConfig: """ from __future__ import annotations - from typing import Optional, Sequence + from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -75,15 +75,20 @@ def config(self) -> InstanceConfig: class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) foo: str - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_instance', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_both_models_basic.py b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_both_models_basic.py index b7482f3e637c8..454d0dc18ea2d 100644 --- a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_both_models_basic.py +++ b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_both_models_basic.py @@ -80,6 +80,7 @@ def shared_config(self) -> SharedConfig: class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) foo: Optional[str] = None @@ -88,6 +89,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] @@ -126,6 +131,7 @@ def _final_validation(cls, model): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) foo: Optional[str] = None @@ -134,6 +140,10 @@ class InstanceConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_instance', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_common_validators.py b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_common_validators.py index 8a6f8831336be..e82daedc1eac4 100644 --- a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_common_validators.py +++ b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_common_validators.py @@ -68,7 +68,7 @@ def config(self) -> InstanceConfig: """ from __future__ import annotations - from typing import Optional, Sequence + from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -81,15 +81,20 @@ def config(self) -> InstanceConfig: class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) foo: str - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_instance', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_defaults.py b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_defaults.py index c48c676ea2a77..94424da9ff13b 100644 --- a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_defaults.py +++ b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_defaults.py @@ -119,7 +119,8 @@ def instance_long_default_formatted(): """ from __future__ import annotations - from typing import Any, Mapping, Optional, Sequence + from types import MappingProxyType + from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -132,14 +133,15 @@ def instance_long_default_formatted(): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) default_precedence: Optional[str] = None example: Optional[str] = None - example_ignored_array: Optional[Sequence[str]] = None - example_ignored_object: Optional[Mapping[str, Any]] = None + example_ignored_array: Optional[tuple[str, ...]] = None + example_ignored_object: Optional[MappingProxyType[str, Any]] = None foo: str - long_default_formatted: Optional[Sequence[Sequence[str]]] = None + long_default_formatted: Optional[tuple[tuple[str, ...], ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -154,6 +156,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_duplicate_hidden.py b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_duplicate_hidden.py index ffdc50f10cf53..f785ef4bcf99a 100644 --- a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_duplicate_hidden.py +++ b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_duplicate_hidden.py @@ -88,6 +88,7 @@ def instance_password(): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) foo: str @@ -106,6 +107,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_enum.py b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_enum.py index 614e165f06324..1ff68f46421f0 100644 --- a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_enum.py +++ b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_enum.py @@ -83,6 +83,7 @@ def instance_my_str(): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) my_str: Optional[Literal['a', 'b', 'c']] = None @@ -100,6 +101,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] @@ -198,6 +203,7 @@ def instance_my_int(): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) my_int: Optional[Literal[1, 2, 3]] = None @@ -215,6 +221,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_merge_instances.py b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_merge_instances.py index eb4b23dfe65f5..87c4370866600 100644 --- a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_merge_instances.py +++ b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_merge_instances.py @@ -87,6 +87,7 @@ def config(self) -> InstanceConfig: class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) bar: str @@ -96,6 +97,10 @@ class InstanceConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_instance', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_nested_option.py b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_nested_option.py index 25693e22ba180..afd69b869133a 100644 --- a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_nested_option.py +++ b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_nested_option.py @@ -76,7 +76,7 @@ def config(self) -> InstanceConfig: """ from __future__ import annotations - from typing import Optional, Sequence + from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -88,14 +88,16 @@ def config(self) -> InstanceConfig: class Setting2(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) bar: str - baz: Optional[Sequence[str]] = None + baz: Optional[tuple[str, ...]] = None class Settings(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) setting1: Optional[str] = None @@ -105,6 +107,7 @@ class Settings(BaseModel): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) foo: str @@ -114,6 +117,10 @@ class InstanceConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_instance', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_object_arbitrary_values.py b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_object_arbitrary_values.py index 1b762b7dbfa0e..ac850f3efc68e 100644 --- a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_object_arbitrary_values.py +++ b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_object_arbitrary_values.py @@ -61,7 +61,8 @@ def config(self) -> InstanceConfig: """ from __future__ import annotations - from typing import Any, Mapping, Optional + from types import MappingProxyType + from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -74,15 +75,20 @@ def config(self) -> InstanceConfig: class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) foo: str - obj: Optional[Mapping[str, Any]] = None + obj: Optional[MappingProxyType[str, Any]] = None @model_validator(mode='before') def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_instance', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_object_model.py b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_object_model.py index fe025ed3f19e5..807a9ed876126 100644 --- a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_object_model.py +++ b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_object_model.py @@ -69,7 +69,7 @@ def config(self) -> InstanceConfig: """ from __future__ import annotations - from typing import Optional, Sequence + from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -81,15 +81,17 @@ def config(self) -> InstanceConfig: class Obj(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) bar: str - baz: Optional[Sequence[str]] = None + baz: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) foo: str @@ -99,6 +101,10 @@ class InstanceConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_instance', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_object_typed_values.py b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_object_typed_values.py index e307459352992..4c65230670aa8 100644 --- a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_object_typed_values.py +++ b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_object_typed_values.py @@ -64,7 +64,8 @@ def config(self) -> InstanceConfig: """ from __future__ import annotations - from typing import Mapping, Optional, Sequence + from types import MappingProxyType + from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -77,15 +78,20 @@ def config(self) -> InstanceConfig: class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) foo: str - obj: Optional[Mapping[str, Sequence[float]]] = None + obj: Optional[MappingProxyType[str, tuple[float, ...]]] = None @model_validator(mode='before') def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_instance', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_only_shared.py b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_only_shared.py index 3ba607df3d9c0..51675a9d46115 100644 --- a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_only_shared.py +++ b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_only_shared.py @@ -68,6 +68,7 @@ def shared_config(self) -> SharedConfig: class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) foo: Optional[str] = None @@ -76,6 +77,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_option_name_normalization.py b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_option_name_normalization.py index 5b2869035c79b..84dbbc2195b0b 100644 --- a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_option_name_normalization.py +++ b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_option_name_normalization.py @@ -73,6 +73,7 @@ def config(self) -> InstanceConfig: class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) bar_baz: Optional[str] = Field(None, alias='bar-baz') @@ -82,6 +83,10 @@ class InstanceConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_instance', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_union_types.py b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_union_types.py index 6c075f31408d8..04663f9be8e69 100644 --- a/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_union_types.py +++ b/datadog_checks_dev/tests/tooling/configuration/consumers/model/test_union_types.py @@ -64,7 +64,7 @@ def config(self) -> InstanceConfig: """ from __future__ import annotations - from typing import Optional, Sequence, Union + from typing import Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -77,15 +77,20 @@ def config(self) -> InstanceConfig: class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) foo: str - obj: Optional[Union[str, Sequence[str]]] = None + obj: Optional[Union[str, tuple[str, ...]]] = None @model_validator(mode='before') def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_instance', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_cluster_agent/datadog_checks/datadog_cluster_agent/config_models/instance.py b/datadog_cluster_agent/datadog_checks/datadog_cluster_agent/config_models/instance.py index 5ded4c1b97033..33f5b0b39adbf 100644 --- a/datadog_cluster_agent/datadog_checks/datadog_cluster_agent/config_models/instance.py +++ b/datadog_cluster_agent/datadog_checks/datadog_cluster_agent/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,30 +22,34 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -52,24 +57,27 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -84,14 +92,14 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -101,10 +109,10 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, str]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, str]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = None ntlm_domain: Optional[str] = None @@ -123,16 +131,16 @@ class InstanceConfig(BaseModel): send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_legacy_auth_encoding: Optional[bool] = None use_process_start_time: Optional[bool] = None username: Optional[str] = None @@ -150,6 +158,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/datadog_cluster_agent/datadog_checks/datadog_cluster_agent/config_models/shared.py b/datadog_cluster_agent/datadog_checks/datadog_cluster_agent/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/datadog_cluster_agent/datadog_checks/datadog_cluster_agent/config_models/shared.py +++ b/datadog_cluster_agent/datadog_checks/datadog_cluster_agent/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/dcgm/datadog_checks/dcgm/config_models/instance.py b/dcgm/datadog_checks/dcgm/config_models/instance.py index 364568d359afa..b6a897cec5b0e 100644 --- a/dcgm/datadog_checks/dcgm/config_models/instance.py +++ b/dcgm/datadog_checks/dcgm/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,14 +41,16 @@ class ExtraMetric(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -55,24 +60,27 @@ class Metric(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -89,18 +97,18 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -110,7 +118,7 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') non_cumulative_histogram_buckets: Optional[bool] = None @@ -119,23 +127,23 @@ class InstanceConfig(BaseModel): password: Optional[str] = None persist_connections: Optional[bool] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None service: Optional[str] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None tag_by_endpoint: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_latest_spec: Optional[bool] = None @@ -156,6 +164,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/dcgm/datadog_checks/dcgm/config_models/shared.py b/dcgm/datadog_checks/dcgm/config_models/shared.py index 59c534d071001..6e5763403db19 100644 --- a/dcgm/datadog_checks/dcgm/config_models/shared.py +++ b/dcgm/datadog_checks/dcgm/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/directory/datadog_checks/directory/config_models/instance.py b/directory/datadog_checks/directory/config_models/instance.py index 071490eb1e54b..c124ee88be76b 100644 --- a/directory/datadog_checks/directory/config_models/instance.py +++ b/directory/datadog_checks/directory/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) countonly: Optional[bool] = None @@ -38,7 +40,7 @@ class InstanceConfig(BaseModel): dirtagname: Optional[str] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - exclude_dirs: Optional[Sequence[str]] = None + exclude_dirs: Optional[tuple[str, ...]] = None filegauges: Optional[bool] = None filetagname: Optional[str] = None follow_symlinks: Optional[bool] = None @@ -51,7 +53,7 @@ class InstanceConfig(BaseModel): service: Optional[str] = None stat_follow_symlinks: Optional[bool] = None submit_histograms: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -66,6 +68,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/directory/datadog_checks/directory/config_models/shared.py b/directory/datadog_checks/directory/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/directory/datadog_checks/directory/config_models/shared.py +++ b/directory/datadog_checks/directory/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/disk/datadog_checks/disk/config_models/instance.py b/disk/datadog_checks/disk/config_models/instance.py index d2190c7145100..cab38c491d3d1 100644 --- a/disk/datadog_checks/disk/config_models/instance.py +++ b/disk/datadog_checks/disk/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,6 +22,7 @@ class CreateMount(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) host: Optional[str] = None @@ -33,38 +35,40 @@ class CreateMount(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) all_partitions: Optional[bool] = None blkid_cache_file: Optional[str] = None - create_mounts: Optional[Sequence[CreateMount]] = None - device_exclude: Optional[Sequence[str]] = None - device_include: Optional[Sequence[str]] = None - device_tag_re: Optional[Mapping[str, Any]] = None + create_mounts: Optional[tuple[CreateMount, ...]] = None + device_exclude: Optional[tuple[str, ...]] = None + device_include: Optional[tuple[str, ...]] = None + device_tag_re: Optional[MappingProxyType[str, Any]] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - file_system_exclude: Optional[Sequence[str]] = None - file_system_include: Optional[Sequence[str]] = None + file_system_exclude: Optional[tuple[str, ...]] = None + file_system_include: Optional[tuple[str, ...]] = None include_all_devices: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None min_disk_size: Optional[float] = None - mount_point_exclude: Optional[Sequence[str]] = None - mount_point_include: Optional[Sequence[str]] = None + mount_point_exclude: Optional[tuple[str, ...]] = None + mount_point_include: Optional[tuple[str, ...]] = None service: Optional[str] = None service_check_rw: Optional[bool] = None tag_by_filesystem: Optional[bool] = None tag_by_label: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[int] = None use_lsblk: Optional[bool] = None use_mount: Optional[bool] = None @@ -82,6 +86,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/disk/datadog_checks/disk/config_models/shared.py b/disk/datadog_checks/disk/config_models/shared.py index f26e88b208fdf..7d45c36389230 100644 --- a/disk/datadog_checks/disk/config_models/shared.py +++ b/disk/datadog_checks/disk/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,17 +22,22 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - device_global_exclude: Optional[Sequence[str]] = None - file_system_global_exclude: Optional[Sequence[str]] = None - mount_point_global_exclude: Optional[Sequence[str]] = None + device_global_exclude: Optional[tuple[str, ...]] = None + file_system_global_exclude: Optional[tuple[str, ...]] = None + mount_point_global_exclude: Optional[tuple[str, ...]] = None service: Optional[str] = None @model_validator(mode='before') def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/dns_check/datadog_checks/dns_check/config_models/instance.py b/dns_check/datadog_checks/dns_check/config_models/instance.py index 28bf117ac104f..402004cfd0cc7 100644 --- a/dns_check/datadog_checks/dns_check/config_models/instance.py +++ b/dns_check/datadog_checks/dns_check/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None @@ -43,7 +45,7 @@ class InstanceConfig(BaseModel): record_type: Optional[str] = None resolves_as: Optional[str] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[int] = None @model_validator(mode='before') @@ -59,6 +61,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/dns_check/datadog_checks/dns_check/config_models/shared.py b/dns_check/datadog_checks/dns_check/config_models/shared.py index 76b4effac7b5f..cb48af7cd0455 100644 --- a/dns_check/datadog_checks/dns_check/config_models/shared.py +++ b/dns_check/datadog_checks/dns_check/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) default_timeout: Optional[int] = None @@ -40,6 +41,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/dotnetclr/datadog_checks/dotnetclr/config_models/instance.py b/dotnetclr/datadog_checks/dotnetclr/config_models/instance.py index 5edb57d89d89e..655420d32b3d5 100644 --- a/dotnetclr/datadog_checks/dotnetclr/config_models/instance.py +++ b/dotnetclr/datadog_checks/dotnetclr/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator from typing_extensions import Literal @@ -22,6 +23,7 @@ class Counter(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -34,6 +36,7 @@ class Counter(BaseModel): class InstanceCounts(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) monitored: Optional[str] = None @@ -43,11 +46,12 @@ class InstanceCounts(BaseModel): class ExtraMetrics(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - counters: Sequence[Mapping[str, Union[str, Counter]]] - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + counters: tuple[MappingProxyType[str, Union[str, Counter]], ...] + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None instance_counts: Optional[InstanceCounts] = None name: str tag_name: Optional[str] = None @@ -56,19 +60,21 @@ class ExtraMetrics(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metrics(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - counters: Sequence[Mapping[str, Union[str, Counter]]] - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + counters: tuple[MappingProxyType[str, Union[str, Counter]], ...] + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None instance_counts: Optional[InstanceCounts] = None name: str tag_name: Optional[str] = None @@ -78,24 +84,25 @@ class Metrics(BaseModel): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - additional_metrics: Optional[Sequence[Sequence[str]]] = None - counter_data_types: Optional[Sequence[str]] = None + additional_metrics: Optional[tuple[tuple[str, ...], ...]] = None + counter_data_types: Optional[tuple[str, ...]] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - extra_metrics: Optional[Mapping[str, ExtraMetrics]] = None + extra_metrics: Optional[MappingProxyType[str, ExtraMetrics]] = None host: Optional[str] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Mapping[str, Metrics]] = None + metrics: Optional[MappingProxyType[str, Metrics]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') password: Optional[str] = None server: Optional[str] = None server_tag: Optional[str] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None use_legacy_check_version: Optional[bool] = None username: Optional[str] = None @@ -112,6 +119,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/dotnetclr/datadog_checks/dotnetclr/config_models/shared.py b/dotnetclr/datadog_checks/dotnetclr/config_models/shared.py index aa58639466c05..f7b81f614312a 100644 --- a/dotnetclr/datadog_checks/dotnetclr/config_models/shared.py +++ b/dotnetclr/datadog_checks/dotnetclr/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -40,6 +41,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/druid/datadog_checks/druid/config_models/instance.py b/druid/datadog_checks/druid/config_models/instance.py index b0c9dd6112c5c..2707f8f1d2979 100644 --- a/druid/datadog_checks/druid/config_models/instance.py +++ b/druid/datadog_checks/druid/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,8 +63,8 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -78,13 +83,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None url: str @@ -104,6 +109,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/druid/datadog_checks/druid/config_models/shared.py b/druid/datadog_checks/druid/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/druid/datadog_checks/druid/config_models/shared.py +++ b/druid/datadog_checks/druid/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ecs_fargate/datadog_checks/ecs_fargate/config_models/instance.py b/ecs_fargate/datadog_checks/ecs_fargate/config_models/instance.py index f15b81079e318..e35f9167e0b3a 100644 --- a/ecs_fargate/datadog_checks/ecs_fargate/config_models/instance.py +++ b/ecs_fargate/datadog_checks/ecs_fargate/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,8 +63,8 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -78,13 +83,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -103,6 +108,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ecs_fargate/datadog_checks/ecs_fargate/config_models/shared.py b/ecs_fargate/datadog_checks/ecs_fargate/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/ecs_fargate/datadog_checks/ecs_fargate/config_models/shared.py +++ b/ecs_fargate/datadog_checks/ecs_fargate/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/eks_fargate/datadog_checks/eks_fargate/config_models/instance.py b/eks_fargate/datadog_checks/eks_fargate/config_models/instance.py index f15b81079e318..e35f9167e0b3a 100644 --- a/eks_fargate/datadog_checks/eks_fargate/config_models/instance.py +++ b/eks_fargate/datadog_checks/eks_fargate/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,8 +63,8 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -78,13 +83,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -103,6 +108,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/eks_fargate/datadog_checks/eks_fargate/config_models/shared.py b/eks_fargate/datadog_checks/eks_fargate/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/eks_fargate/datadog_checks/eks_fargate/config_models/shared.py +++ b/eks_fargate/datadog_checks/eks_fargate/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/elastic/datadog_checks/elastic/config_models/instance.py b/elastic/datadog_checks/elastic/config_models/instance.py index 4ac11de5cb817..6ca82f5f56d56 100644 --- a/elastic/datadog_checks/elastic/config_models/instance.py +++ b/elastic/datadog_checks/elastic/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class Column(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) name: Optional[str] = None @@ -38,35 +41,39 @@ class Column(BaseModel): class CustomQuery(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - columns: Optional[Sequence[Column]] = None + columns: Optional[tuple[Column, ...]] = None data_path: Optional[str] = None endpoint: Optional[str] = None - payload: Optional[Mapping[str, Any]] = None - tags: Optional[Sequence[str]] = None + payload: Optional[MappingProxyType[str, Any]] = None + tags: Optional[tuple[str, ...]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) admin_forwarder: Optional[bool] = None @@ -79,14 +86,14 @@ class InstanceConfig(BaseModel): cat_allocation_stats: Optional[bool] = None cluster_stats: Optional[bool] = None connect_timeout: Optional[float] = None - custom_queries: Optional[Sequence[CustomQuery]] = None + custom_queries: Optional[tuple[CustomQuery, ...]] = None detailed_index_stats: Optional[bool] = None disable_generic_tags: Optional[bool] = None disable_legacy_cluster_tag: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None gc_collectors_as_rate: Optional[bool] = None - headers: Optional[Mapping[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None index_stats: Optional[bool] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None @@ -112,13 +119,13 @@ class InstanceConfig(BaseModel): skip_proxy: Optional[bool] = None slm_stats: Optional[bool] = None submit_events: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None url: str @@ -138,6 +145,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/elastic/datadog_checks/elastic/config_models/shared.py b/elastic/datadog_checks/elastic/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/elastic/datadog_checks/elastic/config_models/shared.py +++ b/elastic/datadog_checks/elastic/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/envoy/datadog_checks/envoy/config_models/instance.py b/envoy/datadog_checks/envoy/config_models/instance.py index bb67674f09245..a8b3e2adf980e 100644 --- a/envoy/datadog_checks/envoy/config_models/instance.py +++ b/envoy/datadog_checks/envoy/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,14 +41,16 @@ class ExtraMetric(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -55,24 +60,27 @@ class Metric(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -92,20 +100,20 @@ class InstanceConfig(BaseModel): disable_legacy_cluster_tag: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - excluded_metrics: Optional[Sequence[str]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + excluded_metrics: Optional[tuple[str, ...]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None - included_metrics: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None + included_metrics: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -115,7 +123,7 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') non_cumulative_histogram_buckets: Optional[bool] = None @@ -125,24 +133,24 @@ class InstanceConfig(BaseModel): password: Optional[str] = None persist_connections: Optional[bool] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None service: Optional[str] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None stats_url: Optional[str] = None tag_by_endpoint: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_latest_spec: Optional[bool] = None @@ -163,6 +171,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/envoy/datadog_checks/envoy/config_models/shared.py b/envoy/datadog_checks/envoy/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/envoy/datadog_checks/envoy/config_models/shared.py +++ b/envoy/datadog_checks/envoy/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/etcd/datadog_checks/etcd/config_models/instance.py b/etcd/datadog_checks/etcd/config_models/instance.py index 4e5ce72d0b2aa..7b5005151df7e 100644 --- a/etcd/datadog_checks/etcd/config_models/instance.py +++ b/etcd/datadog_checks/etcd/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,30 +22,34 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -52,24 +57,27 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -84,14 +92,14 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -101,11 +109,11 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None leader_tag: Optional[bool] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, str]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, str]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = None ntlm_domain: Optional[str] = None @@ -124,16 +132,16 @@ class InstanceConfig(BaseModel): send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_legacy_auth_encoding: Optional[bool] = None use_preview: Optional[bool] = None use_process_start_time: Optional[bool] = None @@ -152,6 +160,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/etcd/datadog_checks/etcd/config_models/shared.py b/etcd/datadog_checks/etcd/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/etcd/datadog_checks/etcd/config_models/shared.py +++ b/etcd/datadog_checks/etcd/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/exchange_server/datadog_checks/exchange_server/config_models/instance.py b/exchange_server/datadog_checks/exchange_server/config_models/instance.py index 5edb57d89d89e..655420d32b3d5 100644 --- a/exchange_server/datadog_checks/exchange_server/config_models/instance.py +++ b/exchange_server/datadog_checks/exchange_server/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator from typing_extensions import Literal @@ -22,6 +23,7 @@ class Counter(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -34,6 +36,7 @@ class Counter(BaseModel): class InstanceCounts(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) monitored: Optional[str] = None @@ -43,11 +46,12 @@ class InstanceCounts(BaseModel): class ExtraMetrics(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - counters: Sequence[Mapping[str, Union[str, Counter]]] - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + counters: tuple[MappingProxyType[str, Union[str, Counter]], ...] + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None instance_counts: Optional[InstanceCounts] = None name: str tag_name: Optional[str] = None @@ -56,19 +60,21 @@ class ExtraMetrics(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metrics(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - counters: Sequence[Mapping[str, Union[str, Counter]]] - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + counters: tuple[MappingProxyType[str, Union[str, Counter]], ...] + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None instance_counts: Optional[InstanceCounts] = None name: str tag_name: Optional[str] = None @@ -78,24 +84,25 @@ class Metrics(BaseModel): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - additional_metrics: Optional[Sequence[Sequence[str]]] = None - counter_data_types: Optional[Sequence[str]] = None + additional_metrics: Optional[tuple[tuple[str, ...], ...]] = None + counter_data_types: Optional[tuple[str, ...]] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - extra_metrics: Optional[Mapping[str, ExtraMetrics]] = None + extra_metrics: Optional[MappingProxyType[str, ExtraMetrics]] = None host: Optional[str] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Mapping[str, Metrics]] = None + metrics: Optional[MappingProxyType[str, Metrics]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') password: Optional[str] = None server: Optional[str] = None server_tag: Optional[str] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None use_legacy_check_version: Optional[bool] = None username: Optional[str] = None @@ -112,6 +119,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/exchange_server/datadog_checks/exchange_server/config_models/shared.py b/exchange_server/datadog_checks/exchange_server/config_models/shared.py index aa58639466c05..f7b81f614312a 100644 --- a/exchange_server/datadog_checks/exchange_server/config_models/shared.py +++ b/exchange_server/datadog_checks/exchange_server/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -40,6 +41,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/external_dns/datadog_checks/external_dns/config_models/instance.py b/external_dns/datadog_checks/external_dns/config_models/instance.py index 5ded4c1b97033..33f5b0b39adbf 100644 --- a/external_dns/datadog_checks/external_dns/config_models/instance.py +++ b/external_dns/datadog_checks/external_dns/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,30 +22,34 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -52,24 +57,27 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -84,14 +92,14 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -101,10 +109,10 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, str]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, str]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = None ntlm_domain: Optional[str] = None @@ -123,16 +131,16 @@ class InstanceConfig(BaseModel): send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_legacy_auth_encoding: Optional[bool] = None use_process_start_time: Optional[bool] = None username: Optional[str] = None @@ -150,6 +158,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/external_dns/datadog_checks/external_dns/config_models/shared.py b/external_dns/datadog_checks/external_dns/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/external_dns/datadog_checks/external_dns/config_models/shared.py +++ b/external_dns/datadog_checks/external_dns/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/fluentd/datadog_checks/fluentd/config_models/instance.py b/fluentd/datadog_checks/fluentd/config_models/instance.py index 4ab45d86111ff..a445793674410 100644 --- a/fluentd/datadog_checks/fluentd/config_models/instance.py +++ b/fluentd/datadog_checks/fluentd/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,9 +63,9 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None fluentd: Optional[str] = None - headers: Optional[Mapping[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -75,20 +80,20 @@ class InstanceConfig(BaseModel): ntlm_domain: Optional[str] = None password: Optional[str] = None persist_connections: Optional[bool] = None - plugin_ids: Optional[Sequence[str]] = None + plugin_ids: Optional[tuple[str, ...]] = None proxy: Optional[Proxy] = None read_timeout: Optional[float] = None request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None tag_by: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -107,6 +112,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/fluentd/datadog_checks/fluentd/config_models/shared.py b/fluentd/datadog_checks/fluentd/config_models/shared.py index abe63595382ba..d325fdc66d82c 100644 --- a/fluentd/datadog_checks/fluentd/config_models/shared.py +++ b/fluentd/datadog_checks/fluentd/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) fluentd: Optional[str] = None @@ -52,6 +54,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/foundationdb/datadog_checks/foundationdb/config_models/instance.py b/foundationdb/datadog_checks/foundationdb/config_models/instance.py index b9b9b6da6a5a4..3bc42bb26ce37 100644 --- a/foundationdb/datadog_checks/foundationdb/config_models/instance.py +++ b/foundationdb/datadog_checks/foundationdb/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,25 +22,27 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) cluster_file: Optional[str] = None - custom_queries: Optional[Sequence[Mapping[str, Any]]] = None + custom_queries: Optional[tuple[MappingProxyType[str, Any], ...]] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tls_ca_file: Optional[str] = None tls_certificate_file: Optional[str] = None tls_key_file: Optional[str] = None @@ -59,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/foundationdb/datadog_checks/foundationdb/config_models/shared.py b/foundationdb/datadog_checks/foundationdb/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/foundationdb/datadog_checks/foundationdb/config_models/shared.py +++ b/foundationdb/datadog_checks/foundationdb/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/gearmand/datadog_checks/gearmand/config_models/instance.py b/gearmand/datadog_checks/gearmand/config_models/instance.py index c9099a4117ffa..255c7695140f5 100644 --- a/gearmand/datadog_checks/gearmand/config_models/instance.py +++ b/gearmand/datadog_checks/gearmand/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None @@ -39,8 +41,8 @@ class InstanceConfig(BaseModel): port: Optional[int] = None server: Optional[str] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None - tasks: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None + tasks: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -55,6 +57,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/gearmand/datadog_checks/gearmand/config_models/shared.py b/gearmand/datadog_checks/gearmand/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/gearmand/datadog_checks/gearmand/config_models/shared.py +++ b/gearmand/datadog_checks/gearmand/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/gitlab/datadog_checks/gitlab/config_models/instance.py b/gitlab/datadog_checks/gitlab/config_models/instance.py index e5f617f9fcac8..77447f6b00983 100644 --- a/gitlab/datadog_checks/gitlab/config_models/instance.py +++ b/gitlab/datadog_checks/gitlab/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,22 +41,25 @@ class ExtraMetric(BaseModel): class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -61,14 +67,16 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -78,24 +86,27 @@ class Metric(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -116,23 +127,23 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None gitaly_server_endpoint: Optional[str] = None gitlab_url: Optional[str] = None - headers: Optional[Mapping[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -142,10 +153,10 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') non_cumulative_histogram_buckets: Optional[bool] = None @@ -157,10 +168,10 @@ class InstanceConfig(BaseModel): prometheus_metrics_prefix: Optional[str] = None prometheus_url: Optional[str] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None send_distribution_buckets: Optional[bool] = None send_distribution_counts_as_monotonic: Optional[bool] = None @@ -169,20 +180,20 @@ class InstanceConfig(BaseModel): send_monotonic_counter: Optional[bool] = None send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None tag_by_endpoint: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_latest_spec: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None use_process_start_time: Optional[bool] = None @@ -201,6 +212,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/gitlab/datadog_checks/gitlab/config_models/shared.py b/gitlab/datadog_checks/gitlab/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/gitlab/datadog_checks/gitlab/config_models/shared.py +++ b/gitlab/datadog_checks/gitlab/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/gitlab_runner/datadog_checks/gitlab_runner/config_models/instance.py b/gitlab_runner/datadog_checks/gitlab_runner/config_models/instance.py index 241f30e5c5214..d530e93614849 100644 --- a/gitlab_runner/datadog_checks/gitlab_runner/config_models/instance.py +++ b/gitlab_runner/datadog_checks/gitlab_runner/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,30 +22,34 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -52,24 +57,27 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -84,15 +92,15 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - extra_headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None gitlab_url: str - headers: Optional[Mapping[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -102,10 +110,10 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, str]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, str]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = None ntlm_domain: Optional[str] = None @@ -125,16 +133,16 @@ class InstanceConfig(BaseModel): send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_legacy_auth_encoding: Optional[bool] = None use_process_start_time: Optional[bool] = None username: Optional[str] = None @@ -152,6 +160,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/gitlab_runner/datadog_checks/gitlab_runner/config_models/shared.py b/gitlab_runner/datadog_checks/gitlab_runner/config_models/shared.py index 70855079e3ede..1439bc2ccc04d 100644 --- a/gitlab_runner/datadog_checks/gitlab_runner/config_models/shared.py +++ b/gitlab_runner/datadog_checks/gitlab_runner/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,19 +21,21 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - allowed_metrics: Sequence[str] + allowed_metrics: tuple[str, ...] proxy: Optional[Proxy] = None service: Optional[str] = None skip_proxy: Optional[bool] = None @@ -52,6 +54,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/glusterfs/datadog_checks/glusterfs/config_models/instance.py b/glusterfs/datadog_checks/glusterfs/config_models/instance.py index 0ac5b0739126b..3d98d2be5a9f4 100644 --- a/glusterfs/datadog_checks/glusterfs/config_models/instance.py +++ b/glusterfs/datadog_checks/glusterfs/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None @@ -37,7 +39,7 @@ class InstanceConfig(BaseModel): metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None use_sudo: Optional[bool] = None @model_validator(mode='before') @@ -53,6 +55,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/glusterfs/datadog_checks/glusterfs/config_models/shared.py b/glusterfs/datadog_checks/glusterfs/config_models/shared.py index a802847d143fb..c01a9a8383ed3 100644 --- a/glusterfs/datadog_checks/glusterfs/config_models/shared.py +++ b/glusterfs/datadog_checks/glusterfs/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) gstatus_path: Optional[str] = None @@ -40,6 +41,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/go_expvar/datadog_checks/go_expvar/config_models/instance.py b/go_expvar/datadog_checks/go_expvar/config_models/instance.py index aa877478dbc9e..a3390b321a65c 100644 --- a/go_expvar/datadog_checks/go_expvar/config_models/instance.py +++ b/go_expvar/datadog_checks/go_expvar/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,42 +22,47 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) alias: Optional[str] = None path: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None type: Optional[str] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -69,8 +75,8 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None expvar_url: str - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -80,7 +86,7 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Metric]] = None + metrics: Optional[tuple[Metric, ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = None ntlm_domain: Optional[str] = None @@ -91,13 +97,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -116,6 +122,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/go_expvar/datadog_checks/go_expvar/config_models/shared.py b/go_expvar/datadog_checks/go_expvar/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/go_expvar/datadog_checks/go_expvar/config_models/shared.py +++ b/go_expvar/datadog_checks/go_expvar/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/gunicorn/datadog_checks/gunicorn/config_models/instance.py b/gunicorn/datadog_checks/gunicorn/config_models/instance.py index 01d7e3ef54960..97c4852973c30 100644 --- a/gunicorn/datadog_checks/gunicorn/config_models/instance.py +++ b/gunicorn/datadog_checks/gunicorn/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None @@ -39,7 +41,7 @@ class InstanceConfig(BaseModel): min_collection_interval: Optional[float] = None proc_name: str service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -54,6 +56,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/gunicorn/datadog_checks/gunicorn/config_models/shared.py b/gunicorn/datadog_checks/gunicorn/config_models/shared.py index 94a7316157dfc..772bb8f698b8e 100644 --- a/gunicorn/datadog_checks/gunicorn/config_models/shared.py +++ b/gunicorn/datadog_checks/gunicorn/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) gunicorn: Optional[str] = None @@ -40,6 +41,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/haproxy/datadog_checks/haproxy/config_models/instance.py b/haproxy/datadog_checks/haproxy/config_models/instance.py index ea3a92f4cc67c..10c51dea22db7 100644 --- a/haproxy/datadog_checks/haproxy/config_models/instance.py +++ b/haproxy/datadog_checks/haproxy/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,22 +41,25 @@ class ExtraMetric(BaseModel): class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -61,14 +67,16 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -78,24 +86,27 @@ class Metric(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) active_tag: Optional[bool] = None @@ -123,21 +134,21 @@ class InstanceConfig(BaseModel): empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None enable_service_check: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -147,10 +158,10 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') non_cumulative_histogram_buckets: Optional[bool] = None @@ -161,10 +172,10 @@ class InstanceConfig(BaseModel): prometheus_metrics_prefix: Optional[str] = None prometheus_url: Optional[str] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None send_distribution_buckets: Optional[bool] = None send_distribution_counts_as_monotonic: Optional[bool] = None @@ -173,15 +184,15 @@ class InstanceConfig(BaseModel): send_monotonic_counter: Optional[bool] = None send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None - services_exclude: Optional[Sequence[str]] = None - services_include: Optional[Sequence[str]] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + services_exclude: Optional[tuple[str, ...]] = None + services_include: Optional[tuple[str, ...]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None startup_grace_seconds: Optional[float] = None status_check: Optional[bool] = None tag_by_endpoint: Optional[bool] = None tag_service_check_by_host: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tags_regex: Optional[str] = None telemetry: Optional[bool] = None timeout: Optional[float] = None @@ -189,10 +200,10 @@ class InstanceConfig(BaseModel): tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None url: Optional[str] = None use_latest_spec: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -214,6 +225,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/haproxy/datadog_checks/haproxy/config_models/shared.py b/haproxy/datadog_checks/haproxy/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/haproxy/datadog_checks/haproxy/config_models/shared.py +++ b/haproxy/datadog_checks/haproxy/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/harbor/datadog_checks/harbor/config_models/instance.py b/harbor/datadog_checks/harbor/config_models/instance.py index 1afa826fcdf02..911200f1e3981 100644 --- a/harbor/datadog_checks/harbor/config_models/instance.py +++ b/harbor/datadog_checks/harbor/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,8 +63,8 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -78,13 +83,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None url: str @@ -104,6 +109,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/harbor/datadog_checks/harbor/config_models/shared.py b/harbor/datadog_checks/harbor/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/harbor/datadog_checks/harbor/config_models/shared.py +++ b/harbor/datadog_checks/harbor/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/hazelcast/datadog_checks/hazelcast/config_models/instance.py b/hazelcast/datadog_checks/hazelcast/config_models/instance.py index 6c38cc1e77b7f..f0305b2d55891 100644 --- a/hazelcast/datadog_checks/hazelcast/config_models/instance.py +++ b/hazelcast/datadog_checks/hazelcast/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,24 +22,27 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -50,8 +54,8 @@ class InstanceConfig(BaseModel): collect_default_jvm_metrics: Optional[bool] = None connect_timeout: Optional[float] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None host: Optional[str] = None is_jmx: Optional[bool] = None java_bin_path: Optional[str] = None @@ -67,7 +71,7 @@ class InstanceConfig(BaseModel): key_store_password: Optional[str] = None key_store_path: Optional[str] = None log_requests: Optional[bool] = None - mc_cluster_states: Optional[Mapping[str, Any]] = None + mc_cluster_states: Optional[MappingProxyType[str, Any]] = None mc_health_check_endpoint: Optional[str] = None min_collection_interval: Optional[float] = None name: Optional[str] = None @@ -84,13 +88,13 @@ class InstanceConfig(BaseModel): rmi_registry_ssl: Optional[bool] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None tools_jar_path: Optional[str] = None @@ -113,6 +117,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/hazelcast/datadog_checks/hazelcast/config_models/shared.py b/hazelcast/datadog_checks/hazelcast/config_models/shared.py index 83534741d4019..8e35eb51f1c45 100644 --- a/hazelcast/datadog_checks/hazelcast/config_models/shared.py +++ b/hazelcast/datadog_checks/hazelcast/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,20 +22,22 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_metrics: Optional[bool] = None - conf: Optional[Sequence[Mapping[str, Any]]] = None + conf: Optional[tuple[MappingProxyType[str, Any], ...]] = None is_jmx: Optional[bool] = None new_gc_metrics: Optional[bool] = None proxy: Optional[Proxy] = None @@ -56,6 +59,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/hdfs_datanode/datadog_checks/hdfs_datanode/config_models/instance.py b/hdfs_datanode/datadog_checks/hdfs_datanode/config_models/instance.py index 977815744f163..1e753d39f373b 100644 --- a/hdfs_datanode/datadog_checks/hdfs_datanode/config_models/instance.py +++ b/hdfs_datanode/datadog_checks/hdfs_datanode/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,9 +63,9 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None hdfs_datanode_jmx_uri: str - headers: Optional[Mapping[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -79,13 +84,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -104,6 +109,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/hdfs_datanode/datadog_checks/hdfs_datanode/config_models/shared.py b/hdfs_datanode/datadog_checks/hdfs_datanode/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/hdfs_datanode/datadog_checks/hdfs_datanode/config_models/shared.py +++ b/hdfs_datanode/datadog_checks/hdfs_datanode/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/hdfs_namenode/datadog_checks/hdfs_namenode/config_models/instance.py b/hdfs_namenode/datadog_checks/hdfs_namenode/config_models/instance.py index 7a11a8ba7b92e..9c03d7410d1db 100644 --- a/hdfs_namenode/datadog_checks/hdfs_namenode/config_models/instance.py +++ b/hdfs_namenode/datadog_checks/hdfs_namenode/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,9 +63,9 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None hdfs_namenode_jmx_uri: str - headers: Optional[Mapping[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -79,13 +84,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -104,6 +109,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/hdfs_namenode/datadog_checks/hdfs_namenode/config_models/shared.py b/hdfs_namenode/datadog_checks/hdfs_namenode/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/hdfs_namenode/datadog_checks/hdfs_namenode/config_models/shared.py +++ b/hdfs_namenode/datadog_checks/hdfs_namenode/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/hive/datadog_checks/hive/config_models/instance.py b/hive/datadog_checks/hive/config_models/instance.py index 631a321dda3bb..7f94ed9d0769f 100644 --- a/hive/datadog_checks/hive/config_models/instance.py +++ b/hive/datadog_checks/hive/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,6 +22,7 @@ class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_jvm_metrics: Optional[bool] = None @@ -42,7 +43,7 @@ class InstanceConfig(BaseModel): rmi_connection_timeout: Optional[float] = None rmi_registry_ssl: Optional[bool] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tools_jar_path: Optional[str] = None trust_store_password: Optional[str] = None trust_store_path: Optional[str] = None @@ -61,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/hive/datadog_checks/hive/config_models/shared.py b/hive/datadog_checks/hive/config_models/shared.py index 0db55a6d064d5..2e8fd64cd388e 100644 --- a/hive/datadog_checks/hive/config_models/shared.py +++ b/hive/datadog_checks/hive/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,10 +23,11 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_metrics: Optional[bool] = None - conf: Optional[Sequence[Mapping[str, Any]]] = None + conf: Optional[tuple[MappingProxyType[str, Any], ...]] = None is_jmx: bool new_gc_metrics: Optional[bool] = None service: Optional[str] = None @@ -44,6 +46,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/hivemq/datadog_checks/hivemq/config_models/instance.py b/hivemq/datadog_checks/hivemq/config_models/instance.py index 631a321dda3bb..7f94ed9d0769f 100644 --- a/hivemq/datadog_checks/hivemq/config_models/instance.py +++ b/hivemq/datadog_checks/hivemq/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,6 +22,7 @@ class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_jvm_metrics: Optional[bool] = None @@ -42,7 +43,7 @@ class InstanceConfig(BaseModel): rmi_connection_timeout: Optional[float] = None rmi_registry_ssl: Optional[bool] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tools_jar_path: Optional[str] = None trust_store_password: Optional[str] = None trust_store_path: Optional[str] = None @@ -61,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/hivemq/datadog_checks/hivemq/config_models/shared.py b/hivemq/datadog_checks/hivemq/config_models/shared.py index 0db55a6d064d5..2e8fd64cd388e 100644 --- a/hivemq/datadog_checks/hivemq/config_models/shared.py +++ b/hivemq/datadog_checks/hivemq/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,10 +23,11 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_metrics: Optional[bool] = None - conf: Optional[Sequence[Mapping[str, Any]]] = None + conf: Optional[tuple[MappingProxyType[str, Any], ...]] = None is_jmx: bool new_gc_metrics: Optional[bool] = None service: Optional[str] = None @@ -44,6 +46,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/http_check/datadog_checks/http_check/config_models/instance.py b/http_check/datadog_checks/http_check/config_models/instance.py index d9d7ff6479833..75594bfa6e87e 100644 --- a/http_check/datadog_checks/http_check/config_models/instance.py +++ b/http_check/datadog_checks/http_check/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -59,13 +64,13 @@ class InstanceConfig(BaseModel): collect_response_time: Optional[bool] = None connect_timeout: Optional[float] = None content_match: Optional[str] = None - data: Optional[Union[Mapping[str, Any], str]] = None + data: Optional[Union[MappingProxyType[str, Any], str]] = None days_critical: Optional[int] = None days_warning: Optional[int] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None http_response_status_code: Optional[str] = None include_content: Optional[bool] = None include_default_headers: Optional[bool] = None @@ -94,14 +99,14 @@ class InstanceConfig(BaseModel): skip_proxy: Optional[bool] = None ssl_server_name: Optional[str] = None stream: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None tls_private_key_password: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_retrieve_non_validated_cert: Optional[bool] = None tls_use_host_header: Optional[bool] = None tls_validate_hostname: Optional[bool] = None @@ -123,6 +128,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/http_check/datadog_checks/http_check/config_models/shared.py b/http_check/datadog_checks/http_check/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/http_check/datadog_checks/http_check/config_models/shared.py +++ b/http_check/datadog_checks/http_check/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/hudi/datadog_checks/hudi/config_models/instance.py b/hudi/datadog_checks/hudi/config_models/instance.py index 631a321dda3bb..7f94ed9d0769f 100644 --- a/hudi/datadog_checks/hudi/config_models/instance.py +++ b/hudi/datadog_checks/hudi/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,6 +22,7 @@ class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_jvm_metrics: Optional[bool] = None @@ -42,7 +43,7 @@ class InstanceConfig(BaseModel): rmi_connection_timeout: Optional[float] = None rmi_registry_ssl: Optional[bool] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tools_jar_path: Optional[str] = None trust_store_password: Optional[str] = None trust_store_path: Optional[str] = None @@ -61,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/hudi/datadog_checks/hudi/config_models/shared.py b/hudi/datadog_checks/hudi/config_models/shared.py index 0db55a6d064d5..2e8fd64cd388e 100644 --- a/hudi/datadog_checks/hudi/config_models/shared.py +++ b/hudi/datadog_checks/hudi/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,10 +23,11 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_metrics: Optional[bool] = None - conf: Optional[Sequence[Mapping[str, Any]]] = None + conf: Optional[tuple[MappingProxyType[str, Any], ...]] = None is_jmx: bool new_gc_metrics: Optional[bool] = None service: Optional[str] = None @@ -44,6 +46,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/hyperv/datadog_checks/hyperv/config_models/instance.py b/hyperv/datadog_checks/hyperv/config_models/instance.py index 5edb57d89d89e..655420d32b3d5 100644 --- a/hyperv/datadog_checks/hyperv/config_models/instance.py +++ b/hyperv/datadog_checks/hyperv/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator from typing_extensions import Literal @@ -22,6 +23,7 @@ class Counter(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -34,6 +36,7 @@ class Counter(BaseModel): class InstanceCounts(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) monitored: Optional[str] = None @@ -43,11 +46,12 @@ class InstanceCounts(BaseModel): class ExtraMetrics(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - counters: Sequence[Mapping[str, Union[str, Counter]]] - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + counters: tuple[MappingProxyType[str, Union[str, Counter]], ...] + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None instance_counts: Optional[InstanceCounts] = None name: str tag_name: Optional[str] = None @@ -56,19 +60,21 @@ class ExtraMetrics(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metrics(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - counters: Sequence[Mapping[str, Union[str, Counter]]] - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + counters: tuple[MappingProxyType[str, Union[str, Counter]], ...] + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None instance_counts: Optional[InstanceCounts] = None name: str tag_name: Optional[str] = None @@ -78,24 +84,25 @@ class Metrics(BaseModel): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - additional_metrics: Optional[Sequence[Sequence[str]]] = None - counter_data_types: Optional[Sequence[str]] = None + additional_metrics: Optional[tuple[tuple[str, ...], ...]] = None + counter_data_types: Optional[tuple[str, ...]] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - extra_metrics: Optional[Mapping[str, ExtraMetrics]] = None + extra_metrics: Optional[MappingProxyType[str, ExtraMetrics]] = None host: Optional[str] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Mapping[str, Metrics]] = None + metrics: Optional[MappingProxyType[str, Metrics]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') password: Optional[str] = None server: Optional[str] = None server_tag: Optional[str] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None use_legacy_check_version: Optional[bool] = None username: Optional[str] = None @@ -112,6 +119,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/hyperv/datadog_checks/hyperv/config_models/shared.py b/hyperv/datadog_checks/hyperv/config_models/shared.py index aa58639466c05..f7b81f614312a 100644 --- a/hyperv/datadog_checks/hyperv/config_models/shared.py +++ b/hyperv/datadog_checks/hyperv/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -40,6 +41,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ibm_ace/datadog_checks/ibm_ace/config_models/instance.py b/ibm_ace/datadog_checks/ibm_ace/config_models/instance.py index 374c33c3127ac..eaa8e54270199 100644 --- a/ibm_ace/datadog_checks/ibm_ace/config_models/instance.py +++ b/ibm_ace/datadog_checks/ibm_ace/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator from typing_extensions import Literal @@ -22,15 +22,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) channel: str = Field(..., min_length=1) @@ -48,7 +50,7 @@ class InstanceConfig(BaseModel): queue_manager: str = Field(..., min_length=1) resource_statistics: Optional[bool] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tls_auth: Optional[bool] = None tls_certificate_label: Optional[str] = None tls_cipher_spec: Optional[str] = None @@ -67,6 +69,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ibm_ace/datadog_checks/ibm_ace/config_models/shared.py b/ibm_ace/datadog_checks/ibm_ace/config_models/shared.py index d7f4dd28de478..4b2eecdc07b8b 100644 --- a/ibm_ace/datadog_checks/ibm_ace/config_models/shared.py +++ b/ibm_ace/datadog_checks/ibm_ace/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ibm_db2/datadog_checks/ibm_db2/config_models/instance.py b/ibm_db2/datadog_checks/ibm_db2/config_models/instance.py index 2fe2a731edf9a..1f4154872bd08 100644 --- a/ibm_db2/datadog_checks/ibm_db2/config_models/instance.py +++ b/ibm_db2/datadog_checks/ibm_db2/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator from typing_extensions import Literal @@ -22,28 +23,31 @@ class CustomQuery(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - columns: Optional[Sequence[Mapping[str, Any]]] = None + columns: Optional[tuple[MappingProxyType[str, Any], ...]] = None metric_prefix: Optional[str] = None query: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - custom_queries: Optional[Sequence[CustomQuery]] = None + custom_queries: Optional[tuple[CustomQuery, ...]] = None db: str disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None @@ -55,7 +59,7 @@ class InstanceConfig(BaseModel): port: Optional[int] = None security: Optional[Literal['none', 'ssl']] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tls_cert: Optional[str] = None use_global_custom_queries: Optional[str] = None username: str @@ -73,6 +77,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ibm_db2/datadog_checks/ibm_db2/config_models/shared.py b/ibm_db2/datadog_checks/ibm_db2/config_models/shared.py index 45d1293f12b20..888ffc02ce622 100644 --- a/ibm_db2/datadog_checks/ibm_db2/config_models/shared.py +++ b/ibm_db2/datadog_checks/ibm_db2/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,15 +23,20 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - global_custom_queries: Optional[Sequence[Mapping[str, Any]]] = None + global_custom_queries: Optional[tuple[MappingProxyType[str, Any], ...]] = None service: Optional[str] = None @model_validator(mode='before') def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ibm_i/datadog_checks/ibm_i/config_models/instance.py b/ibm_i/datadog_checks/ibm_i/config_models/instance.py index f246be0ce38d9..d36358e1c3c16 100644 --- a/ibm_i/datadog_checks/ibm_i/config_models/instance.py +++ b/ibm_i/datadog_checks/ibm_i/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,21 +21,24 @@ class MessageQueueInfo(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - selected_message_queues: Optional[Sequence[str]] = None + selected_message_queues: Optional[tuple[str, ...]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Query(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) name: str @@ -44,6 +47,7 @@ class Query(BaseModel): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) connection_string: Optional[str] = None @@ -56,13 +60,13 @@ class InstanceConfig(BaseModel): metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None password: Optional[str] = None - queries: Optional[Sequence[Query]] = None + queries: Optional[tuple[Query, ...]] = None query_timeout: Optional[int] = Field(None, gt=0) service: Optional[str] = None severity_threshold: Optional[int] = Field(None, ge=0, le=99) system: Optional[str] = None system_mq_query_timeout: Optional[int] = Field(None, gt=0) - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None username: Optional[str] = None @model_validator(mode='before') @@ -78,6 +82,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ibm_i/datadog_checks/ibm_i/config_models/shared.py b/ibm_i/datadog_checks/ibm_i/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/ibm_i/datadog_checks/ibm_i/config_models/shared.py +++ b/ibm_i/datadog_checks/ibm_i/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ibm_mq/datadog_checks/ibm_mq/config_models/instance.py b/ibm_mq/datadog_checks/ibm_mq/config_models/instance.py index 7d867a411947d..dd105d6101a9d 100644 --- a/ibm_mq/datadog_checks/ibm_mq/config_models/instance.py +++ b/ibm_mq/datadog_checks/ibm_mq/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,22 +22,24 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) auto_discover_channels: Optional[bool] = None auto_discover_queues: Optional[bool] = None channel: str = Field(..., min_length=1) - channel_status_mapping: Optional[Mapping[str, Any]] = None - channels: Optional[Sequence[str]] = None + channel_status_mapping: Optional[MappingProxyType[str, Any]] = None + channels: Optional[tuple[str, ...]] = None collect_reset_queue_metrics: Optional[bool] = None collect_statistics_metrics: Optional[bool] = None connection_name: Optional[str] = Field(None, min_length=1) @@ -53,16 +56,16 @@ class InstanceConfig(BaseModel): queue_manager: str = Field(..., min_length=1) queue_manager_process: Optional[str] = None queue_manager_timezone: Optional[str] = Field(None, min_length=1) - queue_patterns: Optional[Sequence[str]] = None - queue_regex: Optional[Sequence[str]] = None - queue_tag_re: Optional[Mapping[str, Any]] = None - queues: Optional[Sequence[str]] = None + queue_patterns: Optional[tuple[str, ...]] = None + queue_regex: Optional[tuple[str, ...]] = None + queue_tag_re: Optional[MappingProxyType[str, Any]] = None + queues: Optional[tuple[str, ...]] = None service: Optional[str] = None ssl_auth: Optional[bool] = None ssl_certificate_label: Optional[str] = None ssl_cipher_spec: Optional[str] = None ssl_key_repository_location: Optional[str] = Field(None, min_length=1) - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[int] = None try_basic_auth: Optional[bool] = None username: Optional[str] = Field(None, min_length=1) @@ -80,6 +83,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ibm_mq/datadog_checks/ibm_mq/config_models/shared.py b/ibm_mq/datadog_checks/ibm_mq/config_models/shared.py index 980a6f2d7be75..3b0415833b08a 100644 --- a/ibm_mq/datadog_checks/ibm_mq/config_models/shared.py +++ b/ibm_mq/datadog_checks/ibm_mq/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) queue_manager_process: Optional[str] = None @@ -41,6 +42,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ibm_was/datadog_checks/ibm_was/config_models/instance.py b/ibm_was/datadog_checks/ibm_was/config_models/instance.py index 484f6fb8b9aec..501b106cbd54e 100644 --- a/ibm_was/datadog_checks/ibm_was/config_models/instance.py +++ b/ibm_was/datadog_checks/ibm_was/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,41 +22,46 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class CustomQuery(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) metric_prefix: Optional[str] = None stat: Optional[str] = None - tag_keys: Optional[Sequence[str]] = None + tag_keys: Optional[tuple[str, ...]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -65,12 +71,12 @@ class InstanceConfig(BaseModel): aws_region: Optional[str] = None aws_service: Optional[str] = None connect_timeout: Optional[float] = None - custom_queries: Optional[Sequence[CustomQuery]] = None - custom_queries_units_gauge: Optional[Sequence[str]] = None + custom_queries: Optional[tuple[CustomQuery, ...]] = None + custom_queries_units_gauge: Optional[tuple[str, ...]] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -91,13 +97,13 @@ class InstanceConfig(BaseModel): service: Optional[str] = None servlet_url: str skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_global_custom_queries: Optional[str] = None @@ -117,6 +123,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ibm_was/datadog_checks/ibm_was/config_models/shared.py b/ibm_was/datadog_checks/ibm_was/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/ibm_was/datadog_checks/ibm_was/config_models/shared.py +++ b/ibm_was/datadog_checks/ibm_was/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ignite/datadog_checks/ignite/config_models/instance.py b/ignite/datadog_checks/ignite/config_models/instance.py index 631a321dda3bb..7f94ed9d0769f 100644 --- a/ignite/datadog_checks/ignite/config_models/instance.py +++ b/ignite/datadog_checks/ignite/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,6 +22,7 @@ class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_jvm_metrics: Optional[bool] = None @@ -42,7 +43,7 @@ class InstanceConfig(BaseModel): rmi_connection_timeout: Optional[float] = None rmi_registry_ssl: Optional[bool] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tools_jar_path: Optional[str] = None trust_store_password: Optional[str] = None trust_store_path: Optional[str] = None @@ -61,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ignite/datadog_checks/ignite/config_models/shared.py b/ignite/datadog_checks/ignite/config_models/shared.py index 0db55a6d064d5..2e8fd64cd388e 100644 --- a/ignite/datadog_checks/ignite/config_models/shared.py +++ b/ignite/datadog_checks/ignite/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,10 +23,11 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_metrics: Optional[bool] = None - conf: Optional[Sequence[Mapping[str, Any]]] = None + conf: Optional[tuple[MappingProxyType[str, Any], ...]] = None is_jmx: bool new_gc_metrics: Optional[bool] = None service: Optional[str] = None @@ -44,6 +46,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/iis/datadog_checks/iis/config_models/instance.py b/iis/datadog_checks/iis/config_models/instance.py index c7122a2901ca0..3bd53110b1023 100644 --- a/iis/datadog_checks/iis/config_models/instance.py +++ b/iis/datadog_checks/iis/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator from typing_extensions import Literal @@ -22,14 +23,16 @@ class AppPool(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Counter(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -42,6 +45,7 @@ class Counter(BaseModel): class InstanceCounts(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) monitored: Optional[str] = None @@ -51,11 +55,12 @@ class InstanceCounts(BaseModel): class ExtraMetrics(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - counters: Sequence[Mapping[str, Union[str, Counter]]] - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + counters: tuple[MappingProxyType[str, Union[str, Counter]], ...] + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None instance_counts: Optional[InstanceCounts] = None name: str tag_name: Optional[str] = None @@ -64,19 +69,21 @@ class ExtraMetrics(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metrics(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - counters: Sequence[Mapping[str, Union[str, Counter]]] - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + counters: tuple[MappingProxyType[str, Union[str, Counter]], ...] + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None instance_counts: Optional[InstanceCounts] = None name: str tag_name: Optional[str] = None @@ -85,35 +92,37 @@ class Metrics(BaseModel): class Site(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - additional_metrics: Optional[Sequence[Sequence[str]]] = None - app_pools: Optional[Union[Sequence[str], AppPool]] = None - counter_data_types: Optional[Sequence[str]] = None + additional_metrics: Optional[tuple[tuple[str, ...], ...]] = None + app_pools: Optional[Union[tuple[str, ...], AppPool]] = None + counter_data_types: Optional[tuple[str, ...]] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - extra_metrics: Optional[Mapping[str, ExtraMetrics]] = None + extra_metrics: Optional[MappingProxyType[str, ExtraMetrics]] = None host: Optional[str] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Mapping[str, Metrics]] = None + metrics: Optional[MappingProxyType[str, Metrics]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') password: Optional[str] = None server: Optional[str] = None server_tag: Optional[str] = None service: Optional[str] = None - sites: Optional[Union[Sequence[str], Site]] = None - tags: Optional[Sequence[str]] = None + sites: Optional[Union[tuple[str, ...], Site]] = None + tags: Optional[tuple[str, ...]] = None use_legacy_check_version: Optional[bool] = None username: Optional[str] = None @@ -130,6 +139,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/iis/datadog_checks/iis/config_models/shared.py b/iis/datadog_checks/iis/config_models/shared.py index aa58639466c05..f7b81f614312a 100644 --- a/iis/datadog_checks/iis/config_models/shared.py +++ b/iis/datadog_checks/iis/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -40,6 +41,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/impala/datadog_checks/impala/config_models/instance.py b/impala/datadog_checks/impala/config_models/instance.py index 316d8f5856387..542f44b3c1c9d 100644 --- a/impala/datadog_checks/impala/config_models/instance.py +++ b/impala/datadog_checks/impala/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator from typing_extensions import Literal @@ -22,14 +23,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -39,14 +42,16 @@ class ExtraMetric(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -56,24 +61,27 @@ class Metric(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -90,18 +98,18 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -111,7 +119,7 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') non_cumulative_histogram_buckets: Optional[bool] = None @@ -120,24 +128,24 @@ class InstanceConfig(BaseModel): password: Optional[str] = None persist_connections: Optional[bool] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None service: Optional[str] = None service_type: Literal['daemon', 'statestore', 'catalog'] - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None tag_by_endpoint: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_latest_spec: Optional[bool] = None @@ -158,6 +166,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/impala/datadog_checks/impala/config_models/shared.py b/impala/datadog_checks/impala/config_models/shared.py index cddf15255ec30..502b9edbbd176 100644 --- a/impala/datadog_checks/impala/config_models/shared.py +++ b/impala/datadog_checks/impala/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/istio/datadog_checks/istio/config_models/instance.py b/istio/datadog_checks/istio/config_models/instance.py index c9118b04f664a..a3ccfcffe8242 100644 --- a/istio/datadog_checks/istio/config_models/instance.py +++ b/istio/datadog_checks/istio/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,22 +41,25 @@ class ExtraMetric(BaseModel): class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -61,14 +67,16 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -78,24 +86,27 @@ class Metric(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -115,21 +126,21 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None istio_mesh_endpoint: Optional[str] = None istiod_endpoint: Optional[str] = None kerberos_auth: Optional[str] = None @@ -141,10 +152,10 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') non_cumulative_histogram_buckets: Optional[bool] = None @@ -155,10 +166,10 @@ class InstanceConfig(BaseModel): prometheus_metrics_prefix: Optional[str] = None prometheus_url: Optional[str] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None send_distribution_buckets: Optional[bool] = None send_distribution_counts_as_monotonic: Optional[bool] = None @@ -167,20 +178,20 @@ class InstanceConfig(BaseModel): send_monotonic_counter: Optional[bool] = None send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None tag_by_endpoint: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_latest_spec: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None use_openmetrics: Optional[bool] = None @@ -200,6 +211,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/istio/datadog_checks/istio/config_models/shared.py b/istio/datadog_checks/istio/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/istio/datadog_checks/istio/config_models/shared.py +++ b/istio/datadog_checks/istio/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/jboss_wildfly/datadog_checks/jboss_wildfly/config_models/instance.py b/jboss_wildfly/datadog_checks/jboss_wildfly/config_models/instance.py index 27518398030cb..2c2f4a044f099 100644 --- a/jboss_wildfly/datadog_checks/jboss_wildfly/config_models/instance.py +++ b/jboss_wildfly/datadog_checks/jboss_wildfly/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,6 +22,7 @@ class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_jvm_metrics: Optional[bool] = None @@ -42,7 +43,7 @@ class InstanceConfig(BaseModel): rmi_connection_timeout: Optional[float] = None rmi_registry_ssl: Optional[bool] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tools_jar_path: Optional[str] = None trust_store_password: Optional[str] = None trust_store_path: Optional[str] = None @@ -61,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/jboss_wildfly/datadog_checks/jboss_wildfly/config_models/shared.py b/jboss_wildfly/datadog_checks/jboss_wildfly/config_models/shared.py index 4450cb75df5e6..8ea2b4af38c8d 100644 --- a/jboss_wildfly/datadog_checks/jboss_wildfly/config_models/shared.py +++ b/jboss_wildfly/datadog_checks/jboss_wildfly/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,11 +23,12 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_metrics: Optional[bool] = None - conf: Optional[Sequence[Mapping[str, Any]]] = None - custom_jar_paths: Optional[Sequence[str]] = None + conf: Optional[tuple[MappingProxyType[str, Any], ...]] = None + custom_jar_paths: Optional[tuple[str, ...]] = None is_jmx: bool new_gc_metrics: Optional[bool] = None service: Optional[str] = None @@ -45,6 +47,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kafka/datadog_checks/kafka/config_models/instance.py b/kafka/datadog_checks/kafka/config_models/instance.py index 631a321dda3bb..7f94ed9d0769f 100644 --- a/kafka/datadog_checks/kafka/config_models/instance.py +++ b/kafka/datadog_checks/kafka/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,6 +22,7 @@ class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_jvm_metrics: Optional[bool] = None @@ -42,7 +43,7 @@ class InstanceConfig(BaseModel): rmi_connection_timeout: Optional[float] = None rmi_registry_ssl: Optional[bool] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tools_jar_path: Optional[str] = None trust_store_password: Optional[str] = None trust_store_path: Optional[str] = None @@ -61,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kafka/datadog_checks/kafka/config_models/shared.py b/kafka/datadog_checks/kafka/config_models/shared.py index 0db55a6d064d5..2e8fd64cd388e 100644 --- a/kafka/datadog_checks/kafka/config_models/shared.py +++ b/kafka/datadog_checks/kafka/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,10 +23,11 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_metrics: Optional[bool] = None - conf: Optional[Sequence[Mapping[str, Any]]] = None + conf: Optional[tuple[MappingProxyType[str, Any], ...]] = None is_jmx: bool new_gc_metrics: Optional[bool] = None service: Optional[str] = None @@ -44,6 +46,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kafka_consumer/datadog_checks/kafka_consumer/config_models/instance.py b/kafka_consumer/datadog_checks/kafka_consumer/config_models/instance.py index 55c8a77f3824c..e85e3e0340d0b 100644 --- a/kafka_consumer/datadog_checks/kafka_consumer/config_models/instance.py +++ b/kafka_consumer/datadog_checks/kafka_consumer/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,14 +22,16 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class SaslOauthTokenProvider(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) client_id: Optional[str] = None @@ -39,14 +42,15 @@ class SaslOauthTokenProvider(BaseModel): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - consumer_groups: Optional[Mapping[str, Any]] = None - consumer_groups_regex: Optional[Mapping[str, Any]] = None + consumer_groups: Optional[MappingProxyType[str, Any]] = None + consumer_groups_regex: Optional[MappingProxyType[str, Any]] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None kafka_client_api_version: Optional[str] = None - kafka_connect_str: Union[str, Sequence[str]] + kafka_connect_str: Union[str, tuple[str, ...]] metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None monitor_all_broker_highwatermarks: Optional[bool] = None @@ -61,7 +65,7 @@ class InstanceConfig(BaseModel): sasl_plain_username: Optional[str] = None security_protocol: Optional[str] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_crlfile: Optional[str] = None @@ -83,6 +87,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kafka_consumer/datadog_checks/kafka_consumer/config_models/shared.py b/kafka_consumer/datadog_checks/kafka_consumer/config_models/shared.py index 1209ce0b60d1b..78c8e99a92c5d 100644 --- a/kafka_consumer/datadog_checks/kafka_consumer/config_models/shared.py +++ b/kafka_consumer/datadog_checks/kafka_consumer/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) kafka_timeout: Optional[int] = None @@ -40,6 +41,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kong/datadog_checks/kong/config_models/instance.py b/kong/datadog_checks/kong/config_models/instance.py index 3ea2106b6038d..3cdea3a0d5326 100644 --- a/kong/datadog_checks/kong/config_models/instance.py +++ b/kong/datadog_checks/kong/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,14 +41,16 @@ class ExtraMetric(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -55,24 +60,27 @@ class Metric(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -89,18 +97,18 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -111,7 +119,7 @@ class InstanceConfig(BaseModel): kong_status_url: Optional[str] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') non_cumulative_histogram_buckets: Optional[bool] = None @@ -120,23 +128,23 @@ class InstanceConfig(BaseModel): password: Optional[str] = None persist_connections: Optional[bool] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None service: Optional[str] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None tag_by_endpoint: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_latest_spec: Optional[bool] = None @@ -157,6 +165,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kong/datadog_checks/kong/config_models/shared.py b/kong/datadog_checks/kong/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/kong/datadog_checks/kong/config_models/shared.py +++ b/kong/datadog_checks/kong/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kube_apiserver_metrics/datadog_checks/kube_apiserver_metrics/config_models/instance.py b/kube_apiserver_metrics/datadog_checks/kube_apiserver_metrics/config_models/instance.py index 08bcf458d13e8..65ba7d5420cc3 100644 --- a/kube_apiserver_metrics/datadog_checks/kube_apiserver_metrics/config_models/instance.py +++ b/kube_apiserver_metrics/datadog_checks/kube_apiserver_metrics/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,30 +22,34 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -52,24 +57,27 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -84,14 +92,14 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -101,10 +109,10 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, str]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, str]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = None ntlm_domain: Optional[str] = None @@ -124,16 +132,16 @@ class InstanceConfig(BaseModel): send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_legacy_auth_encoding: Optional[bool] = None use_process_start_time: Optional[bool] = None username: Optional[str] = None @@ -151,6 +159,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kube_apiserver_metrics/datadog_checks/kube_apiserver_metrics/config_models/shared.py b/kube_apiserver_metrics/datadog_checks/kube_apiserver_metrics/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/kube_apiserver_metrics/datadog_checks/kube_apiserver_metrics/config_models/shared.py +++ b/kube_apiserver_metrics/datadog_checks/kube_apiserver_metrics/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kube_dns/datadog_checks/kube_dns/config_models/instance.py b/kube_dns/datadog_checks/kube_dns/config_models/instance.py index db57870d93a16..bae6663f3883e 100644 --- a/kube_dns/datadog_checks/kube_dns/config_models/instance.py +++ b/kube_dns/datadog_checks/kube_dns/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,30 +22,34 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -52,24 +57,27 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -84,15 +92,15 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None health_url: Optional[str] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -102,10 +110,10 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, str]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, str]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = None ntlm_domain: Optional[str] = None @@ -125,16 +133,16 @@ class InstanceConfig(BaseModel): send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_legacy_auth_encoding: Optional[bool] = None use_process_start_time: Optional[bool] = None username: Optional[str] = None @@ -152,6 +160,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kube_dns/datadog_checks/kube_dns/config_models/shared.py b/kube_dns/datadog_checks/kube_dns/config_models/shared.py index cddf15255ec30..502b9edbbd176 100644 --- a/kube_dns/datadog_checks/kube_dns/config_models/shared.py +++ b/kube_dns/datadog_checks/kube_dns/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kube_metrics_server/datadog_checks/kube_metrics_server/config_models/instance.py b/kube_metrics_server/datadog_checks/kube_metrics_server/config_models/instance.py index 860d9668d06d8..c840d2b513530 100644 --- a/kube_metrics_server/datadog_checks/kube_metrics_server/config_models/instance.py +++ b/kube_metrics_server/datadog_checks/kube_metrics_server/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,30 +22,34 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -52,24 +57,27 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -84,15 +92,15 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None health_url: Optional[str] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -102,10 +110,10 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, str]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, str]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = None ntlm_domain: Optional[str] = None @@ -124,16 +132,16 @@ class InstanceConfig(BaseModel): send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_legacy_auth_encoding: Optional[bool] = None use_process_start_time: Optional[bool] = None username: Optional[str] = None @@ -151,6 +159,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kube_metrics_server/datadog_checks/kube_metrics_server/config_models/shared.py b/kube_metrics_server/datadog_checks/kube_metrics_server/config_models/shared.py index cddf15255ec30..502b9edbbd176 100644 --- a/kube_metrics_server/datadog_checks/kube_metrics_server/config_models/shared.py +++ b/kube_metrics_server/datadog_checks/kube_metrics_server/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kube_proxy/datadog_checks/kube_proxy/config_models/instance.py b/kube_proxy/datadog_checks/kube_proxy/config_models/instance.py index 860d9668d06d8..c840d2b513530 100644 --- a/kube_proxy/datadog_checks/kube_proxy/config_models/instance.py +++ b/kube_proxy/datadog_checks/kube_proxy/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,30 +22,34 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -52,24 +57,27 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -84,15 +92,15 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None health_url: Optional[str] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -102,10 +110,10 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, str]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, str]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = None ntlm_domain: Optional[str] = None @@ -124,16 +132,16 @@ class InstanceConfig(BaseModel): send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_legacy_auth_encoding: Optional[bool] = None use_process_start_time: Optional[bool] = None username: Optional[str] = None @@ -151,6 +159,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kube_proxy/datadog_checks/kube_proxy/config_models/shared.py b/kube_proxy/datadog_checks/kube_proxy/config_models/shared.py index cddf15255ec30..502b9edbbd176 100644 --- a/kube_proxy/datadog_checks/kube_proxy/config_models/shared.py +++ b/kube_proxy/datadog_checks/kube_proxy/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kube_scheduler/datadog_checks/kube_scheduler/config_models/instance.py b/kube_scheduler/datadog_checks/kube_scheduler/config_models/instance.py index 9994d4ff14809..cb6d19be4f878 100644 --- a/kube_scheduler/datadog_checks/kube_scheduler/config_models/instance.py +++ b/kube_scheduler/datadog_checks/kube_scheduler/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,30 +22,34 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -52,24 +57,27 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -84,15 +92,15 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None health_url: Optional[str] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -102,12 +110,12 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None leader_election: Optional[bool] = None leader_election_kind: Optional[str] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, str]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, str]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = None ntlm_domain: Optional[str] = None @@ -126,16 +134,16 @@ class InstanceConfig(BaseModel): send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_legacy_auth_encoding: Optional[bool] = None use_process_start_time: Optional[bool] = None username: Optional[str] = None @@ -153,6 +161,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kube_scheduler/datadog_checks/kube_scheduler/config_models/shared.py b/kube_scheduler/datadog_checks/kube_scheduler/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/kube_scheduler/datadog_checks/kube_scheduler/config_models/shared.py +++ b/kube_scheduler/datadog_checks/kube_scheduler/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kubelet/datadog_checks/kubelet/config_models/instance.py b/kubelet/datadog_checks/kubelet/config_models/instance.py index 94a9cf2bfcb6a..2d1e177d7b965 100644 --- a/kubelet/datadog_checks/kubelet/config_models/instance.py +++ b/kubelet/datadog_checks/kubelet/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,30 +22,34 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -52,24 +57,27 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -86,16 +94,16 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - enabled_gauges: Optional[Sequence[str]] = None - enabled_rates: Optional[Sequence[str]] = None - exclude_labels: Optional[Sequence[str]] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + enabled_gauges: Optional[tuple[str, ...]] = None + enabled_rates: Optional[tuple[str, ...]] = None + exclude_labels: Optional[tuple[str, ...]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -106,10 +114,10 @@ class InstanceConfig(BaseModel): kubelet_metrics_endpoint: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, str]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, str]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = None ntlm_domain: Optional[str] = None @@ -129,16 +137,16 @@ class InstanceConfig(BaseModel): send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_legacy_auth_encoding: Optional[bool] = None use_process_start_time: Optional[bool] = None username: Optional[str] = None @@ -156,6 +164,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kubelet/datadog_checks/kubelet/config_models/shared.py b/kubelet/datadog_checks/kubelet/config_models/shared.py index 59c534d071001..6e5763403db19 100644 --- a/kubelet/datadog_checks/kubelet/config_models/shared.py +++ b/kubelet/datadog_checks/kubelet/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kyototycoon/datadog_checks/kyototycoon/config_models/instance.py b/kyototycoon/datadog_checks/kyototycoon/config_models/instance.py index 2b910204564cc..439de8d6a19d9 100644 --- a/kyototycoon/datadog_checks/kyototycoon/config_models/instance.py +++ b/kyototycoon/datadog_checks/kyototycoon/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,8 +63,8 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -80,13 +85,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -105,6 +110,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/kyototycoon/datadog_checks/kyototycoon/config_models/shared.py b/kyototycoon/datadog_checks/kyototycoon/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/kyototycoon/datadog_checks/kyototycoon/config_models/shared.py +++ b/kyototycoon/datadog_checks/kyototycoon/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/lighttpd/datadog_checks/lighttpd/config_models/instance.py b/lighttpd/datadog_checks/lighttpd/config_models/instance.py index c9aaef1aef14b..c8494d73c5c44 100644 --- a/lighttpd/datadog_checks/lighttpd/config_models/instance.py +++ b/lighttpd/datadog_checks/lighttpd/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,8 +63,8 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -79,13 +84,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -104,6 +109,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/lighttpd/datadog_checks/lighttpd/config_models/shared.py b/lighttpd/datadog_checks/lighttpd/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/lighttpd/datadog_checks/lighttpd/config_models/shared.py +++ b/lighttpd/datadog_checks/lighttpd/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/linkerd/datadog_checks/linkerd/config_models/instance.py b/linkerd/datadog_checks/linkerd/config_models/instance.py index e57304ed42cee..4b5e2263e66e2 100644 --- a/linkerd/datadog_checks/linkerd/config_models/instance.py +++ b/linkerd/datadog_checks/linkerd/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,22 +41,25 @@ class ExtraMetric(BaseModel): class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -61,14 +67,16 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -78,24 +86,27 @@ class Metric(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -115,21 +126,21 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -139,10 +150,10 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') non_cumulative_histogram_buckets: Optional[bool] = None @@ -153,10 +164,10 @@ class InstanceConfig(BaseModel): prometheus_metrics_prefix: Optional[str] = None prometheus_url: Optional[str] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None send_distribution_buckets: Optional[bool] = None send_distribution_counts_as_monotonic: Optional[bool] = None @@ -165,20 +176,20 @@ class InstanceConfig(BaseModel): send_monotonic_counter: Optional[bool] = None send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None tag_by_endpoint: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_latest_spec: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None use_process_start_time: Optional[bool] = None @@ -197,6 +208,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/linkerd/datadog_checks/linkerd/config_models/shared.py b/linkerd/datadog_checks/linkerd/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/linkerd/datadog_checks/linkerd/config_models/shared.py +++ b/linkerd/datadog_checks/linkerd/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/linux_proc_extras/datadog_checks/linux_proc_extras/config_models/instance.py b/linux_proc_extras/datadog_checks/linux_proc_extras/config_models/instance.py index 32d51a43106c7..1e1d349da8dd1 100644 --- a/linux_proc_extras/datadog_checks/linux_proc_extras/config_models/instance.py +++ b/linux_proc_extras/datadog_checks/linux_proc_extras/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None @@ -38,7 +40,7 @@ class InstanceConfig(BaseModel): metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -53,6 +55,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/linux_proc_extras/datadog_checks/linux_proc_extras/config_models/shared.py b/linux_proc_extras/datadog_checks/linux_proc_extras/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/linux_proc_extras/datadog_checks/linux_proc_extras/config_models/shared.py +++ b/linux_proc_extras/datadog_checks/linux_proc_extras/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/mapr/datadog_checks/mapr/config_models/instance.py b/mapr/datadog_checks/mapr/config_models/instance.py index 1c96a015ba27d..636c97702c85f 100644 --- a/mapr/datadog_checks/mapr/config_models/instance.py +++ b/mapr/datadog_checks/mapr/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None @@ -37,12 +39,12 @@ class InstanceConfig(BaseModel): empty_default_hostname: Optional[bool] = None hostname: Optional[str] = None metric_patterns: Optional[MetricPatterns] = None - metric_whitelist: Optional[Sequence[str]] = None + metric_whitelist: Optional[tuple[str, ...]] = None min_collection_interval: Optional[float] = None service: Optional[str] = None stream_path: Optional[str] = None streams_count: Optional[int] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None ticket_location: Optional[str] = None @model_validator(mode='before') @@ -58,6 +60,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/mapr/datadog_checks/mapr/config_models/shared.py b/mapr/datadog_checks/mapr/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/mapr/datadog_checks/mapr/config_models/shared.py +++ b/mapr/datadog_checks/mapr/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/mapreduce/datadog_checks/mapreduce/config_models/instance.py b/mapreduce/datadog_checks/mapreduce/config_models/instance.py index 28d64960f3f86..4c87238aa9067 100644 --- a/mapreduce/datadog_checks/mapreduce/config_models/instance.py +++ b/mapreduce/datadog_checks/mapreduce/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -60,8 +65,8 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None disable_legacy_cluster_tag: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -81,13 +86,13 @@ class InstanceConfig(BaseModel): resourcemanager_uri: str service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -106,6 +111,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/mapreduce/datadog_checks/mapreduce/config_models/shared.py b/mapreduce/datadog_checks/mapreduce/config_models/shared.py index 0134382ffc5b8..1147dd440bedf 100644 --- a/mapreduce/datadog_checks/mapreduce/config_models/shared.py +++ b/mapreduce/datadog_checks/mapreduce/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,20 +22,22 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - general_counters: Optional[Sequence[Mapping[str, Any]]] = None - job_specific_counters: Optional[Sequence[Mapping[str, Any]]] = None + general_counters: Optional[tuple[MappingProxyType[str, Any], ...]] = None + job_specific_counters: Optional[tuple[MappingProxyType[str, Any], ...]] = None proxy: Optional[Proxy] = None service: Optional[str] = None skip_proxy: Optional[bool] = None @@ -53,6 +56,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/marathon/datadog_checks/marathon/config_models/instance.py b/marathon/datadog_checks/marathon/config_models/instance.py index ba80721d113ae..d157c4e48a2ee 100644 --- a/marathon/datadog_checks/marathon/config_models/instance.py +++ b/marathon/datadog_checks/marathon/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) acs_url: Optional[str] = None @@ -59,9 +64,9 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None group: Optional[str] = None - headers: Optional[Mapping[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -69,7 +74,7 @@ class InstanceConfig(BaseModel): kerberos_hostname: Optional[str] = None kerberos_keytab: Optional[str] = None kerberos_principal: Optional[str] = None - label_tags: Optional[Sequence[str]] = None + label_tags: Optional[tuple[str, ...]] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None @@ -81,13 +86,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None url: str @@ -107,6 +112,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/marathon/datadog_checks/marathon/config_models/shared.py b/marathon/datadog_checks/marathon/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/marathon/datadog_checks/marathon/config_models/shared.py +++ b/marathon/datadog_checks/marathon/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/marklogic/datadog_checks/marklogic/config_models/instance.py b/marklogic/datadog_checks/marklogic/config_models/instance.py index 374308be96131..c4eda10e09454 100644 --- a/marklogic/datadog_checks/marklogic/config_models/instance.py +++ b/marklogic/datadog_checks/marklogic/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -59,8 +64,8 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_checks: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -77,16 +82,16 @@ class InstanceConfig(BaseModel): proxy: Optional[Proxy] = None read_timeout: Optional[float] = None request_size: Optional[float] = None - resource_filters: Optional[Sequence[Mapping[str, Any]]] = None + resource_filters: Optional[tuple[MappingProxyType[str, Any], ...]] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None url: str @@ -106,6 +111,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/marklogic/datadog_checks/marklogic/config_models/shared.py b/marklogic/datadog_checks/marklogic/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/marklogic/datadog_checks/marklogic/config_models/shared.py +++ b/marklogic/datadog_checks/marklogic/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/mcache/datadog_checks/mcache/config_models/instance.py b/mcache/datadog_checks/mcache/config_models/instance.py index a7d97edbeb977..fd5d084eb848a 100644 --- a/mcache/datadog_checks/mcache/config_models/instance.py +++ b/mcache/datadog_checks/mcache/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,27 +22,29 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None - options: Optional[Mapping[str, Any]] = None + options: Optional[MappingProxyType[str, Any]] = None password: Optional[str] = None port: Optional[int] = None service: Optional[str] = None socket: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None url: Optional[str] = None username: Optional[str] = None @@ -58,6 +61,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/mcache/datadog_checks/mcache/config_models/shared.py b/mcache/datadog_checks/mcache/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/mcache/datadog_checks/mcache/config_models/shared.py +++ b/mcache/datadog_checks/mcache/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/mesos_master/datadog_checks/mesos_master/config_models/instance.py b/mesos_master/datadog_checks/mesos_master/config_models/instance.py index b0c9dd6112c5c..2707f8f1d2979 100644 --- a/mesos_master/datadog_checks/mesos_master/config_models/instance.py +++ b/mesos_master/datadog_checks/mesos_master/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,8 +63,8 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -78,13 +83,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None url: str @@ -104,6 +109,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/mesos_master/datadog_checks/mesos_master/config_models/shared.py b/mesos_master/datadog_checks/mesos_master/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/mesos_master/datadog_checks/mesos_master/config_models/shared.py +++ b/mesos_master/datadog_checks/mesos_master/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/mesos_slave/datadog_checks/mesos_slave/config_models/instance.py b/mesos_slave/datadog_checks/mesos_slave/config_models/instance.py index 032e50574fccc..edb21588ec278 100644 --- a/mesos_slave/datadog_checks/mesos_slave/config_models/instance.py +++ b/mesos_slave/datadog_checks/mesos_slave/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -59,8 +64,8 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -80,14 +85,14 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None - tasks: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None + tasks: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None url: str @@ -107,6 +112,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/mesos_slave/datadog_checks/mesos_slave/config_models/shared.py b/mesos_slave/datadog_checks/mesos_slave/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/mesos_slave/datadog_checks/mesos_slave/config_models/shared.py +++ b/mesos_slave/datadog_checks/mesos_slave/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/mongo/datadog_checks/mongo/config_models/instance.py b/mongo/datadog_checks/mongo/config_models/instance.py index cfd5dd0d29e78..e906bc975f637 100644 --- a/mongo/datadog_checks/mongo/config_models/instance.py +++ b/mongo/datadog_checks/mongo/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,6 +22,7 @@ class Field(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) field_name: Optional[str] = None @@ -30,46 +32,49 @@ class Field(BaseModel): class CustomQuery(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) database: Optional[str] = None - fields: Optional[Sequence[Field]] = None + fields: Optional[tuple[Field, ...]] = None metric_prefix: Optional[str] = None - query: Optional[Mapping[str, Any]] = None - tags: Optional[Sequence[str]] = None + query: Optional[MappingProxyType[str, Any]] = None + tags: Optional[tuple[str, ...]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - additional_metrics: Optional[Sequence[str]] = None - collections: Optional[Sequence[str]] = None + additional_metrics: Optional[tuple[str, ...]] = None + collections: Optional[tuple[str, ...]] = None collections_indexes_stats: Optional[bool] = None connection_scheme: Optional[str] = None - custom_queries: Optional[Sequence[CustomQuery]] = None + custom_queries: Optional[tuple[CustomQuery, ...]] = None database: Optional[str] = None - dbnames: Optional[Sequence[str]] = None + dbnames: Optional[tuple[str, ...]] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - hosts: Optional[Union[str, Sequence[str]]] = None + hosts: Optional[Union[str, tuple[str, ...]]] = None metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None - options: Optional[Mapping[str, Any]] = None + options: Optional[MappingProxyType[str, Any]] = None password: Optional[str] = None replica_check: Optional[bool] = None server: Optional[str] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[int] = None tls: Optional[bool] = None tls_allow_invalid_certificates: Optional[bool] = None @@ -97,6 +102,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/mongo/datadog_checks/mongo/config_models/shared.py b/mongo/datadog_checks/mongo/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/mongo/datadog_checks/mongo/config_models/shared.py +++ b/mongo/datadog_checks/mongo/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/mysql/datadog_checks/mysql/config_models/instance.py b/mysql/datadog_checks/mysql/config_models/instance.py index 9e05824b265d6..5a4dbe6178c96 100644 --- a/mysql/datadog_checks/mysql/config_models/instance.py +++ b/mysql/datadog_checks/mysql/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,6 +22,7 @@ class Aws(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) instance_endpoint: Optional[str] = None @@ -28,6 +30,7 @@ class Aws(BaseModel): class Azure(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) deployment_type: Optional[str] = None @@ -36,15 +39,17 @@ class Azure(BaseModel): class CustomQuery(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - columns: Optional[Sequence[Mapping[str, Any]]] = None + columns: Optional[tuple[MappingProxyType[str, Any], ...]] = None query: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None class Gcp(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) instance_id: Optional[str] = None @@ -53,14 +58,16 @@ class Gcp(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class ObfuscatorOptions(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) collect_commands: Optional[bool] = None @@ -73,6 +80,7 @@ class ObfuscatorOptions(BaseModel): class Options(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) disable_innodb_metrics: Optional[bool] = None @@ -91,6 +99,7 @@ class Options(BaseModel): class QueryActivity(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) collection_interval: Optional[float] = None @@ -99,6 +108,7 @@ class QueryActivity(BaseModel): class QueryMetrics(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) collection_interval: Optional[float] = None @@ -107,6 +117,7 @@ class QueryMetrics(BaseModel): class QuerySamples(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) collection_interval: Optional[float] = None @@ -126,6 +137,7 @@ class QuerySamples(BaseModel): class Ssl(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) ca: Optional[str] = None @@ -137,15 +149,16 @@ class Ssl(BaseModel): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - additional_status: Optional[Sequence[Mapping[str, Any]]] = None - additional_variable: Optional[Sequence[Mapping[str, Any]]] = None + additional_status: Optional[tuple[MappingProxyType[str, Any], ...]] = None + additional_variable: Optional[tuple[MappingProxyType[str, Any], ...]] = None aws: Optional[Aws] = None azure: Optional[Azure] = None charset: Optional[str] = None connect_timeout: Optional[float] = None - custom_queries: Optional[Sequence[CustomQuery]] = None + custom_queries: Optional[tuple[CustomQuery, ...]] = None dbm: Optional[bool] = None defaults_file: Optional[str] = None disable_generic_tags: Optional[bool] = None @@ -162,7 +175,7 @@ class InstanceConfig(BaseModel): options: Optional[Options] = None password: Optional[str] = None port: Optional[float] = None - queries: Optional[Sequence[Mapping[str, Any]]] = None + queries: Optional[tuple[MappingProxyType[str, Any], ...]] = None query_activity: Optional[QueryActivity] = None query_metrics: Optional[QueryMetrics] = None query_samples: Optional[QuerySamples] = None @@ -170,7 +183,7 @@ class InstanceConfig(BaseModel): service: Optional[str] = None sock: Optional[str] = None ssl: Optional[Ssl] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None use_global_custom_queries: Optional[str] = None username: Optional[str] = None @@ -187,6 +200,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/mysql/datadog_checks/mysql/config_models/shared.py b/mysql/datadog_checks/mysql/config_models/shared.py index 45d1293f12b20..888ffc02ce622 100644 --- a/mysql/datadog_checks/mysql/config_models/shared.py +++ b/mysql/datadog_checks/mysql/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,15 +23,20 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - global_custom_queries: Optional[Sequence[Mapping[str, Any]]] = None + global_custom_queries: Optional[tuple[MappingProxyType[str, Any], ...]] = None service: Optional[str] = None @model_validator(mode='before') def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/nagios/datadog_checks/nagios/config_models/instance.py b/nagios/datadog_checks/nagios/config_models/instance.py index 89bcad3570e22..4eb7bf630d1b3 100644 --- a/nagios/datadog_checks/nagios/config_models/instance.py +++ b/nagios/datadog_checks/nagios/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_events: Optional[bool] = None @@ -42,7 +44,7 @@ class InstanceConfig(BaseModel): nagios_conf: str passive_checks_events: Optional[bool] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -57,6 +59,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/nagios/datadog_checks/nagios/config_models/shared.py b/nagios/datadog_checks/nagios/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/nagios/datadog_checks/nagios/config_models/shared.py +++ b/nagios/datadog_checks/nagios/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/network/datadog_checks/network/config_models/instance.py b/network/datadog_checks/network/config_models/instance.py index a54b47ef2a2c1..a528ac6438260 100644 --- a/network/datadog_checks/network/config_models/instance.py +++ b/network/datadog_checks/network/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,18 +21,20 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - blacklist_conntrack_metrics: Optional[Sequence[str]] = None + blacklist_conntrack_metrics: Optional[tuple[str, ...]] = None collect_aws_ena_metrics: Optional[bool] = None collect_connection_queues: Optional[bool] = None collect_connection_state: Optional[bool] = None @@ -44,13 +46,13 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None excluded_interface_re: Optional[str] = None - excluded_interfaces: Optional[Sequence[str]] = None + excluded_interfaces: Optional[tuple[str, ...]] = None metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None use_sudo_conntrack: Optional[bool] = None - whitelist_conntrack_metrics: Optional[Sequence[str]] = None + whitelist_conntrack_metrics: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -65,6 +67,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/network/datadog_checks/network/config_models/shared.py b/network/datadog_checks/network/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/network/datadog_checks/network/config_models/shared.py +++ b/network/datadog_checks/network/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/nfsstat/datadog_checks/nfsstat/config_models/instance.py b/nfsstat/datadog_checks/nfsstat/config_models/instance.py index 9fd87afb27b4b..8b81148f03f3d 100644 --- a/nfsstat/datadog_checks/nfsstat/config_models/instance.py +++ b/nfsstat/datadog_checks/nfsstat/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None @@ -37,7 +39,7 @@ class InstanceConfig(BaseModel): metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -52,6 +54,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/nfsstat/datadog_checks/nfsstat/config_models/shared.py b/nfsstat/datadog_checks/nfsstat/config_models/shared.py index e262ac1b3291a..98e1fb86347b3 100644 --- a/nfsstat/datadog_checks/nfsstat/config_models/shared.py +++ b/nfsstat/datadog_checks/nfsstat/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) autofs_enabled: Optional[bool] = None @@ -41,6 +42,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/nginx/datadog_checks/nginx/config_models/instance.py b/nginx/datadog_checks/nginx/config_models/instance.py index 2eeafce0ed9fb..94a768c1efe45 100644 --- a/nginx/datadog_checks/nginx/config_models/instance.py +++ b/nginx/datadog_checks/nginx/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,8 +63,8 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -81,13 +86,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -109,6 +114,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/nginx/datadog_checks/nginx/config_models/shared.py b/nginx/datadog_checks/nginx/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/nginx/datadog_checks/nginx/config_models/shared.py +++ b/nginx/datadog_checks/nginx/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/nginx_ingress_controller/datadog_checks/nginx_ingress_controller/config_models/instance.py b/nginx_ingress_controller/datadog_checks/nginx_ingress_controller/config_models/instance.py index f5050d760dcee..c14ccdc94b7d9 100644 --- a/nginx_ingress_controller/datadog_checks/nginx_ingress_controller/config_models/instance.py +++ b/nginx_ingress_controller/datadog_checks/nginx_ingress_controller/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,30 +22,34 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -52,24 +57,27 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -85,14 +93,14 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -102,10 +110,10 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, str]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, str]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = None ntlm_domain: Optional[str] = None @@ -124,16 +132,16 @@ class InstanceConfig(BaseModel): send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_legacy_auth_encoding: Optional[bool] = None use_process_start_time: Optional[bool] = None username: Optional[str] = None @@ -151,6 +159,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/nginx_ingress_controller/datadog_checks/nginx_ingress_controller/config_models/shared.py b/nginx_ingress_controller/datadog_checks/nginx_ingress_controller/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/nginx_ingress_controller/datadog_checks/nginx_ingress_controller/config_models/shared.py +++ b/nginx_ingress_controller/datadog_checks/nginx_ingress_controller/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/openldap/datadog_checks/openldap/config_models/instance.py b/openldap/datadog_checks/openldap/config_models/instance.py index 480864e5965d4..1c0f067401a6f 100644 --- a/openldap/datadog_checks/openldap/config_models/instance.py +++ b/openldap/datadog_checks/openldap/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,18 +22,20 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - custom_queries: Optional[Sequence[Mapping[str, Any]]] = None + custom_queries: Optional[tuple[MappingProxyType[str, Any], ...]] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None @@ -43,7 +46,7 @@ class InstanceConfig(BaseModel): ssl_cert: Optional[str] = None ssl_key: Optional[str] = None ssl_verify: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None url: str username: Optional[str] = None @@ -60,6 +63,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/openldap/datadog_checks/openldap/config_models/shared.py b/openldap/datadog_checks/openldap/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/openldap/datadog_checks/openldap/config_models/shared.py +++ b/openldap/datadog_checks/openldap/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/openmetrics/datadog_checks/openmetrics/config_models/instance.py b/openmetrics/datadog_checks/openmetrics/config_models/instance.py index 2497c1d2a92b2..0668d730a6f2b 100644 --- a/openmetrics/datadog_checks/openmetrics/config_models/instance.py +++ b/openmetrics/datadog_checks/openmetrics/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,22 +41,25 @@ class ExtraMetric(BaseModel): class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -61,14 +67,16 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -78,24 +86,27 @@ class Metric(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -115,21 +126,21 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -139,10 +150,10 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Sequence[Union[str, Mapping[str, Union[str, Metric]]]] + metrics: tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...] min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') non_cumulative_histogram_buckets: Optional[bool] = None @@ -153,10 +164,10 @@ class InstanceConfig(BaseModel): prometheus_metrics_prefix: Optional[str] = None prometheus_url: Optional[str] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None send_distribution_buckets: Optional[bool] = None send_distribution_counts_as_monotonic: Optional[bool] = None @@ -165,20 +176,20 @@ class InstanceConfig(BaseModel): send_monotonic_counter: Optional[bool] = None send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None tag_by_endpoint: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_latest_spec: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None use_process_start_time: Optional[bool] = None @@ -197,6 +208,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/openmetrics/datadog_checks/openmetrics/config_models/shared.py b/openmetrics/datadog_checks/openmetrics/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/openmetrics/datadog_checks/openmetrics/config_models/shared.py +++ b/openmetrics/datadog_checks/openmetrics/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/openstack_controller/datadog_checks/openstack_controller/config_models/instance.py b/openstack_controller/datadog_checks/openstack_controller/config_models/instance.py index 8d0db0b9856d2..c43fdd8202552 100644 --- a/openstack_controller/datadog_checks/openstack_controller/config_models/instance.py +++ b/openstack_controller/datadog_checks/openstack_controller/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -55,7 +60,7 @@ class InstanceConfig(BaseModel): aws_host: Optional[str] = None aws_region: Optional[str] = None aws_service: Optional[str] = None - blacklist_project_names: Optional[Sequence[str]] = None + blacklist_project_names: Optional[tuple[str, ...]] = None collect_hypervisor_load: Optional[bool] = None collect_hypervisor_metrics: Optional[bool] = None collect_network_metrics: Optional[bool] = None @@ -65,10 +70,10 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - exclude_network_ids: Optional[Sequence[str]] = None - exclude_server_ids: Optional[Sequence[str]] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_network_ids: Optional[tuple[str, ...]] = None + exclude_server_ids: Optional[tuple[str, ...]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -92,21 +97,21 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_agent_proxy: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None use_shortname: Optional[bool] = None - user: Optional[Mapping[str, Any]] = None + user: Optional[MappingProxyType[str, Any]] = None username: Optional[str] = None - whitelist_project_names: Optional[Sequence[str]] = None + whitelist_project_names: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -121,6 +126,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/openstack_controller/datadog_checks/openstack_controller/config_models/shared.py b/openstack_controller/datadog_checks/openstack_controller/config_models/shared.py index 59c534d071001..6e5763403db19 100644 --- a/openstack_controller/datadog_checks/openstack_controller/config_models/shared.py +++ b/openstack_controller/datadog_checks/openstack_controller/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/oracle/datadog_checks/oracle/config_models/instance.py b/oracle/datadog_checks/oracle/config_models/instance.py index 75f1e7097531a..48736a554b35f 100644 --- a/oracle/datadog_checks/oracle/config_models/instance.py +++ b/oracle/datadog_checks/oracle/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,27 +22,30 @@ class CustomQuery(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - columns: Optional[Sequence[Mapping[str, Any]]] = None + columns: Optional[tuple[MappingProxyType[str, Any], ...]] = None query: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - custom_queries: Optional[Sequence[CustomQuery]] = None + custom_queries: Optional[tuple[CustomQuery, ...]] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None jdbc_driver_path: Optional[str] = None @@ -56,7 +60,7 @@ class InstanceConfig(BaseModel): server: str service: Optional[str] = None service_name: str - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None use_global_custom_queries: Optional[str] = None username: str @@ -73,6 +77,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/oracle/datadog_checks/oracle/config_models/shared.py b/oracle/datadog_checks/oracle/config_models/shared.py index 18baeec9cb208..2f357778127b6 100644 --- a/oracle/datadog_checks/oracle/config_models/shared.py +++ b/oracle/datadog_checks/oracle/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,9 +23,10 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - global_custom_queries: Optional[Sequence[Mapping[str, Any]]] = None + global_custom_queries: Optional[tuple[MappingProxyType[str, Any], ...]] = None service: Optional[str] = None use_instant_client: Optional[bool] = None @@ -41,6 +43,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/pdh_check/datadog_checks/pdh_check/config_models/instance.py b/pdh_check/datadog_checks/pdh_check/config_models/instance.py index b81d8fd6d013c..5a996eda7537b 100644 --- a/pdh_check/datadog_checks/pdh_check/config_models/instance.py +++ b/pdh_check/datadog_checks/pdh_check/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,30 +21,32 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - additional_metrics: Optional[Sequence[Sequence[str]]] = None + additional_metrics: Optional[tuple[tuple[str, ...], ...]] = None admin_share: Optional[str] = None - counter_data_types: Optional[Sequence[str]] = None + counter_data_types: Optional[tuple[str, ...]] = None countersetname: str disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None host: Optional[str] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Sequence[Sequence[str]] + metrics: tuple[tuple[str, ...], ...] min_collection_interval: Optional[float] = None password: Optional[str] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None username: Optional[str] = None @model_validator(mode='before') @@ -60,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/pdh_check/datadog_checks/pdh_check/config_models/shared.py b/pdh_check/datadog_checks/pdh_check/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/pdh_check/datadog_checks/pdh_check/config_models/shared.py +++ b/pdh_check/datadog_checks/pdh_check/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/pgbouncer/datadog_checks/pgbouncer/config_models/instance.py b/pgbouncer/datadog_checks/pgbouncer/config_models/instance.py index 1a8f390a5a15e..806eb3519a1fd 100644 --- a/pgbouncer/datadog_checks/pgbouncer/config_models/instance.py +++ b/pgbouncer/datadog_checks/pgbouncer/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_per_client_metrics: Optional[bool] = None @@ -43,7 +45,7 @@ class InstanceConfig(BaseModel): password: Optional[str] = None port: Optional[int] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None use_cached: Optional[bool] = None username: Optional[str] = None @@ -60,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/pgbouncer/datadog_checks/pgbouncer/config_models/shared.py b/pgbouncer/datadog_checks/pgbouncer/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/pgbouncer/datadog_checks/pgbouncer/config_models/shared.py +++ b/pgbouncer/datadog_checks/pgbouncer/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/php_fpm/datadog_checks/php_fpm/config_models/instance.py b/php_fpm/datadog_checks/php_fpm/config_models/instance.py index 887c6ff718942..c0130805b0472 100644 --- a/php_fpm/datadog_checks/php_fpm/config_models/instance.py +++ b/php_fpm/datadog_checks/php_fpm/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,8 +63,8 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None http_host: Optional[str] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None @@ -82,13 +87,13 @@ class InstanceConfig(BaseModel): service: Optional[str] = None skip_proxy: Optional[bool] = None status_url: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_fastcgi: Optional[bool] = None @@ -108,6 +113,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/php_fpm/datadog_checks/php_fpm/config_models/shared.py b/php_fpm/datadog_checks/php_fpm/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/php_fpm/datadog_checks/php_fpm/config_models/shared.py +++ b/php_fpm/datadog_checks/php_fpm/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/postfix/datadog_checks/postfix/config_models/instance.py b/postfix/datadog_checks/postfix/config_models/instance.py index 37078bb780d3c..94be59d72e2f1 100644 --- a/postfix/datadog_checks/postfix/config_models/instance.py +++ b/postfix/datadog_checks/postfix/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) config_directory: Optional[str] = None @@ -38,9 +40,9 @@ class InstanceConfig(BaseModel): empty_default_hostname: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None - queues: Optional[Sequence[str]] = None + queues: Optional[tuple[str, ...]] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -55,6 +57,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/postfix/datadog_checks/postfix/config_models/shared.py b/postfix/datadog_checks/postfix/config_models/shared.py index 8ef1ae63aed9b..c5a83632dd619 100644 --- a/postfix/datadog_checks/postfix/config_models/shared.py +++ b/postfix/datadog_checks/postfix/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) postfix_user: Optional[str] = None @@ -41,6 +42,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/postgres/datadog_checks/postgres/config_models/instance.py b/postgres/datadog_checks/postgres/config_models/instance.py index 6f7fad8e0a4ec..9297bcbc5a050 100644 --- a/postgres/datadog_checks/postgres/config_models/instance.py +++ b/postgres/datadog_checks/postgres/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,6 +22,7 @@ class Aws(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) instance_endpoint: Optional[str] = None @@ -29,6 +31,7 @@ class Aws(BaseModel): class Azure(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) deployment_type: Optional[str] = None @@ -37,6 +40,7 @@ class Azure(BaseModel): class CollectSettings(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) collection_interval: Optional[float] = None @@ -45,17 +49,19 @@ class CollectSettings(BaseModel): class DatabaseAutodiscovery(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) enabled: Optional[bool] = None - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None max_databases: Optional[int] = None refresh: Optional[int] = None class Gcp(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) instance_id: Optional[str] = None @@ -64,14 +70,16 @@ class Gcp(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class ObfuscatorOptions(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) collect_commands: Optional[bool] = None @@ -85,6 +93,7 @@ class ObfuscatorOptions(BaseModel): class QueryActivity(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) collection_interval: Optional[float] = None @@ -94,6 +103,7 @@ class QueryActivity(BaseModel): class QueryMetrics(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) collection_interval: Optional[float] = None @@ -103,6 +113,7 @@ class QueryMetrics(BaseModel): class QuerySamples(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) collection_interval: Optional[float] = None @@ -117,21 +128,23 @@ class QuerySamples(BaseModel): class Relation(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) relation_name: Optional[str] = None relation_regex: Optional[str] = None relation_schema: Optional[str] = None - relkind: Optional[Sequence[str]] = None - schemas: Optional[Sequence[str]] = None + relkind: Optional[tuple[str, ...]] = None + schemas: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - activity_metrics_excluded_aggregations: Optional[Sequence[str]] = None + activity_metrics_excluded_aggregations: Optional[tuple[str, ...]] = None application_name: Optional[str] = None aws: Optional[Aws] = None azure: Optional[Azure] = None @@ -143,7 +156,7 @@ class InstanceConfig(BaseModel): collect_function_metrics: Optional[bool] = None collect_settings: Optional[CollectSettings] = None collect_wal_metrics: Optional[bool] = None - custom_queries: Optional[Sequence[Mapping[str, Any]]] = None + custom_queries: Optional[tuple[MappingProxyType[str, Any], ...]] = None data_directory: Optional[str] = None database_autodiscovery: Optional[DatabaseAutodiscovery] = None dbm: Optional[bool] = None @@ -154,7 +167,7 @@ class InstanceConfig(BaseModel): gcp: Optional[Gcp] = None host: str idle_connection_timeout: Optional[int] = None - ignore_databases: Optional[Sequence[str]] = None + ignore_databases: Optional[tuple[str, ...]] = None log_unobfuscated_plans: Optional[bool] = None log_unobfuscated_queries: Optional[bool] = None max_connections: Optional[int] = None @@ -169,7 +182,7 @@ class InstanceConfig(BaseModel): query_metrics: Optional[QueryMetrics] = None query_samples: Optional[QuerySamples] = None query_timeout: Optional[int] = None - relations: Optional[Sequence[Union[str, Relation]]] = None + relations: Optional[tuple[Union[str, Relation], ...]] = None reported_hostname: Optional[str] = None service: Optional[str] = None ssl: Optional[str] = None @@ -179,7 +192,7 @@ class InstanceConfig(BaseModel): ssl_root_cert: Optional[str] = None table_count_limit: Optional[int] = None tag_replication_role: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None username: str @model_validator(mode='before') @@ -195,6 +208,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/postgres/datadog_checks/postgres/config_models/shared.py b/postgres/datadog_checks/postgres/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/postgres/datadog_checks/postgres/config_models/shared.py +++ b/postgres/datadog_checks/postgres/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/powerdns_recursor/datadog_checks/powerdns_recursor/config_models/instance.py b/powerdns_recursor/datadog_checks/powerdns_recursor/config_models/instance.py index 5ceeba7f7c159..a8c78448d6949 100644 --- a/powerdns_recursor/datadog_checks/powerdns_recursor/config_models/instance.py +++ b/powerdns_recursor/datadog_checks/powerdns_recursor/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -59,8 +64,8 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None host: str kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None @@ -81,13 +86,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -107,6 +112,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/powerdns_recursor/datadog_checks/powerdns_recursor/config_models/shared.py b/powerdns_recursor/datadog_checks/powerdns_recursor/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/powerdns_recursor/datadog_checks/powerdns_recursor/config_models/shared.py +++ b/powerdns_recursor/datadog_checks/powerdns_recursor/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/presto/datadog_checks/presto/config_models/instance.py b/presto/datadog_checks/presto/config_models/instance.py index 631a321dda3bb..7f94ed9d0769f 100644 --- a/presto/datadog_checks/presto/config_models/instance.py +++ b/presto/datadog_checks/presto/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,6 +22,7 @@ class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_jvm_metrics: Optional[bool] = None @@ -42,7 +43,7 @@ class InstanceConfig(BaseModel): rmi_connection_timeout: Optional[float] = None rmi_registry_ssl: Optional[bool] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tools_jar_path: Optional[str] = None trust_store_password: Optional[str] = None trust_store_path: Optional[str] = None @@ -61,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/presto/datadog_checks/presto/config_models/shared.py b/presto/datadog_checks/presto/config_models/shared.py index 0db55a6d064d5..2e8fd64cd388e 100644 --- a/presto/datadog_checks/presto/config_models/shared.py +++ b/presto/datadog_checks/presto/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,10 +23,11 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_metrics: Optional[bool] = None - conf: Optional[Sequence[Mapping[str, Any]]] = None + conf: Optional[tuple[MappingProxyType[str, Any], ...]] = None is_jmx: bool new_gc_metrics: Optional[bool] = None service: Optional[str] = None @@ -44,6 +46,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/process/datadog_checks/process/config_models/instance.py b/process/datadog_checks/process/config_models/instance.py index 981f21e38fee4..66f60f4f22b0a 100644 --- a/process/datadog_checks/process/config_models/instance.py +++ b/process/datadog_checks/process/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +22,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_children: Optional[bool] = None @@ -43,10 +46,10 @@ class InstanceConfig(BaseModel): pid: Optional[int] = None pid_cache_duration: Optional[int] = None pid_file: Optional[str] = None - search_string: Optional[Sequence[str]] = None + search_string: Optional[tuple[str, ...]] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None - thresholds: Optional[Mapping[str, Any]] = None + tags: Optional[tuple[str, ...]] = None + thresholds: Optional[MappingProxyType[str, Any]] = None try_sudo: Optional[bool] = None user: Optional[str] = None @@ -63,6 +66,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/process/datadog_checks/process/config_models/shared.py b/process/datadog_checks/process/config_models/shared.py index 6a773c518a17f..08b161e50eb3e 100644 --- a/process/datadog_checks/process/config_models/shared.py +++ b/process/datadog_checks/process/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) access_denied_cache_duration: Optional[int] = None @@ -43,6 +44,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/prometheus/datadog_checks/prometheus/config_models/instance.py b/prometheus/datadog_checks/prometheus/config_models/instance.py index d1d6ff0d2fde5..6f6492ab3e44d 100644 --- a/prometheus/datadog_checks/prometheus/config_models/instance.py +++ b/prometheus/datadog_checks/prometheus/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,14 +22,16 @@ class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -37,15 +40,16 @@ class LabelJoins(BaseModel): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - exclude_labels: Optional[Sequence[str]] = None + exclude_labels: Optional[tuple[str, ...]] = None health_service_check: Optional[bool] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None max_returned_metrics: Optional[int] = None - metrics: Sequence[Union[Mapping[str, str], str]] + metrics: tuple[Union[MappingProxyType[str, str], str], ...] namespace: str prometheus_metrics_prefix: Optional[str] = None prometheus_timeout: Optional[int] = None @@ -55,7 +59,7 @@ class InstanceConfig(BaseModel): ssl_ca_cert: Optional[str] = None ssl_cert: Optional[str] = None ssl_private_key: Optional[str] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -70,6 +74,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/prometheus/datadog_checks/prometheus/config_models/shared.py b/prometheus/datadog_checks/prometheus/config_models/shared.py index d7f4dd28de478..4b2eecdc07b8b 100644 --- a/prometheus/datadog_checks/prometheus/config_models/shared.py +++ b/prometheus/datadog_checks/prometheus/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/proxysql/datadog_checks/proxysql/config_models/instance.py b/proxysql/datadog_checks/proxysql/config_models/instance.py index 86141964cbc9c..88eec60149e3d 100644 --- a/proxysql/datadog_checks/proxysql/config_models/instance.py +++ b/proxysql/datadog_checks/proxysql/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,18 +21,20 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - additional_metrics: Optional[Sequence[str]] = None + additional_metrics: Optional[tuple[str, ...]] = None connect_timeout: Optional[int] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None @@ -43,7 +45,7 @@ class InstanceConfig(BaseModel): port: int read_timeout: Optional[int] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_private_key: Optional[str] = None @@ -65,6 +67,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/proxysql/datadog_checks/proxysql/config_models/shared.py b/proxysql/datadog_checks/proxysql/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/proxysql/datadog_checks/proxysql/config_models/shared.py +++ b/proxysql/datadog_checks/proxysql/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/pulsar/datadog_checks/pulsar/config_models/instance.py b/pulsar/datadog_checks/pulsar/config_models/instance.py index 6634ff2831f5b..285eb30da8256 100644 --- a/pulsar/datadog_checks/pulsar/config_models/instance.py +++ b/pulsar/datadog_checks/pulsar/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,14 +41,16 @@ class ExtraMetric(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -55,24 +60,27 @@ class Metric(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -89,18 +97,18 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -110,7 +118,7 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') non_cumulative_histogram_buckets: Optional[bool] = None @@ -119,23 +127,23 @@ class InstanceConfig(BaseModel): password: Optional[str] = None persist_connections: Optional[bool] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None service: Optional[str] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None tag_by_endpoint: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_latest_spec: Optional[bool] = None @@ -156,6 +164,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/pulsar/datadog_checks/pulsar/config_models/shared.py b/pulsar/datadog_checks/pulsar/config_models/shared.py index cddf15255ec30..502b9edbbd176 100644 --- a/pulsar/datadog_checks/pulsar/config_models/shared.py +++ b/pulsar/datadog_checks/pulsar/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/rabbitmq/datadog_checks/rabbitmq/config_models/instance.py b/rabbitmq/datadog_checks/rabbitmq/config_models/instance.py index 6252b5547851d..12005d48eb824 100644 --- a/rabbitmq/datadog_checks/rabbitmq/config_models/instance.py +++ b/rabbitmq/datadog_checks/rabbitmq/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,14 +41,16 @@ class ExtraMetric(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -55,6 +60,7 @@ class Metric(BaseModel): class PrometheusPlugin(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) include_aggregated_endpoint: Optional[bool] = None @@ -64,24 +70,27 @@ class PrometheusPlugin(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -99,20 +108,20 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exchanges: Optional[Sequence[str]] = None - exchanges_regexes: Optional[Sequence[str]] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - headers: Optional[Mapping[str, Any]] = None + exchanges: Optional[tuple[str, ...]] = None + exchanges_regexes: Optional[tuple[str, ...]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -122,11 +131,11 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') - nodes: Optional[Sequence[str]] = None - nodes_regexes: Optional[Sequence[str]] = None + nodes: Optional[tuple[str, ...]] = None + nodes_regexes: Optional[tuple[str, ...]] = None non_cumulative_histogram_buckets: Optional[bool] = None ntlm_domain: Optional[str] = None openmetrics_endpoint: Optional[str] = None @@ -134,34 +143,34 @@ class InstanceConfig(BaseModel): persist_connections: Optional[bool] = None prometheus_plugin: Optional[PrometheusPlugin] = None proxy: Optional[Proxy] = None - queues: Optional[Sequence[str]] = None - queues_regexes: Optional[Sequence[str]] = None + queues: Optional[tuple[str, ...]] = None + queues_regexes: Optional[tuple[str, ...]] = None rabbitmq_api_url: Optional[str] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None service: Optional[str] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None tag_by_endpoint: Optional[bool] = None tag_families: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_latest_spec: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None use_process_start_time: Optional[bool] = None username: Optional[str] = None - vhosts: Optional[Sequence[str]] = None + vhosts: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -176,6 +185,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/rabbitmq/datadog_checks/rabbitmq/config_models/shared.py b/rabbitmq/datadog_checks/rabbitmq/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/rabbitmq/datadog_checks/rabbitmq/config_models/shared.py +++ b/rabbitmq/datadog_checks/rabbitmq/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/redisdb/datadog_checks/redisdb/config_models/instance.py b/redisdb/datadog_checks/redisdb/config_models/instance.py index a466b28bc8b6d..b5d5b3b7af50e 100644 --- a/redisdb/datadog_checks/redisdb/config_models/instance.py +++ b/redisdb/datadog_checks/redisdb/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_client_metrics: Optional[bool] = None @@ -39,7 +41,7 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None host: str - keys: Optional[Sequence[str]] = None + keys: Optional[tuple[str, ...]] = None metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None password: Optional[str] = None @@ -52,7 +54,7 @@ class InstanceConfig(BaseModel): ssl_cert_reqs: Optional[int] = None ssl_certfile: Optional[str] = None ssl_keyfile: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None unix_socket_path: Optional[str] = None username: Optional[str] = None warn_on_missing_keys: Optional[bool] = None @@ -70,6 +72,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/redisdb/datadog_checks/redisdb/config_models/shared.py b/redisdb/datadog_checks/redisdb/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/redisdb/datadog_checks/redisdb/config_models/shared.py +++ b/redisdb/datadog_checks/redisdb/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/rethinkdb/datadog_checks/rethinkdb/config_models/instance.py b/rethinkdb/datadog_checks/rethinkdb/config_models/instance.py index ec190b2619840..c40ac6e34fea5 100644 --- a/rethinkdb/datadog_checks/rethinkdb/config_models/instance.py +++ b/rethinkdb/datadog_checks/rethinkdb/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None @@ -40,7 +42,7 @@ class InstanceConfig(BaseModel): password: Optional[str] = None port: Optional[int] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tls_ca_cert: Optional[str] = None username: Optional[str] = None @@ -57,6 +59,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/rethinkdb/datadog_checks/rethinkdb/config_models/shared.py b/rethinkdb/datadog_checks/rethinkdb/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/rethinkdb/datadog_checks/rethinkdb/config_models/shared.py +++ b/rethinkdb/datadog_checks/rethinkdb/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/riak/datadog_checks/riak/config_models/instance.py b/riak/datadog_checks/riak/config_models/instance.py index b0c9dd6112c5c..2707f8f1d2979 100644 --- a/riak/datadog_checks/riak/config_models/instance.py +++ b/riak/datadog_checks/riak/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,8 +63,8 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -78,13 +83,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None url: str @@ -104,6 +109,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/riak/datadog_checks/riak/config_models/shared.py b/riak/datadog_checks/riak/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/riak/datadog_checks/riak/config_models/shared.py +++ b/riak/datadog_checks/riak/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/riakcs/datadog_checks/riakcs/config_models/instance.py b/riakcs/datadog_checks/riakcs/config_models/instance.py index fb25a1a11912b..01e83b839a436 100644 --- a/riakcs/datadog_checks/riakcs/config_models/instance.py +++ b/riakcs/datadog_checks/riakcs/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) access_id: Optional[str] = None @@ -39,12 +41,12 @@ class InstanceConfig(BaseModel): host: Optional[str] = None is_secure: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[str]] = None + metrics: Optional[tuple[str, ...]] = None min_collection_interval: Optional[float] = None port: Optional[int] = None s3_root: Optional[str] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -59,6 +61,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/riakcs/datadog_checks/riakcs/config_models/shared.py b/riakcs/datadog_checks/riakcs/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/riakcs/datadog_checks/riakcs/config_models/shared.py +++ b/riakcs/datadog_checks/riakcs/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/sap_hana/datadog_checks/sap_hana/config_models/instance.py b/sap_hana/datadog_checks/sap_hana/config_models/instance.py index 5b3dea4f94eee..add9cd8afa266 100644 --- a/sap_hana/datadog_checks/sap_hana/config_models/instance.py +++ b/sap_hana/datadog_checks/sap_hana/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,29 +22,32 @@ class CustomQuery(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - columns: Optional[Sequence[Mapping[str, Any]]] = None + columns: Optional[tuple[MappingProxyType[str, Any], ...]] = None query: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) batch_size: Optional[int] = None - connection_properties: Optional[Mapping[str, Any]] = None - custom_queries: Optional[Sequence[CustomQuery]] = None + connection_properties: Optional[MappingProxyType[str, Any]] = None + custom_queries: Optional[tuple[CustomQuery, ...]] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None @@ -55,7 +59,7 @@ class InstanceConfig(BaseModel): schema_: Optional[str] = Field(None, alias='schema') server: str service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None @@ -81,6 +85,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/sap_hana/datadog_checks/sap_hana/config_models/shared.py b/sap_hana/datadog_checks/sap_hana/config_models/shared.py index 314a5343f67bf..dcc4bca04b104 100644 --- a/sap_hana/datadog_checks/sap_hana/config_models/shared.py +++ b/sap_hana/datadog_checks/sap_hana/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,9 +23,10 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - global_custom_queries: Optional[Sequence[Mapping[str, Any]]] = None + global_custom_queries: Optional[tuple[MappingProxyType[str, Any], ...]] = None persist_db_connections: Optional[bool] = None service: Optional[str] = None @@ -41,6 +43,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/scylla/datadog_checks/scylla/config_models/instance.py b/scylla/datadog_checks/scylla/config_models/instance.py index 4db066610b71d..45c2c0bae967d 100644 --- a/scylla/datadog_checks/scylla/config_models/instance.py +++ b/scylla/datadog_checks/scylla/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,30 +22,34 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class IgnoreMetricsByLabels(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_label_key: Optional[str] = None - target_label_value_list: Optional[Sequence[str]] = None + target_label_value_list: Optional[tuple[str, ...]] = None class TargetMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) label_to_match: Optional[str] = None - labels_to_get: Optional[Sequence[str]] = None + labels_to_get: Optional[tuple[str, ...]] = None class LabelJoins(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) target_metric: Optional[TargetMetric] = None @@ -52,24 +57,27 @@ class LabelJoins(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -84,14 +92,14 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None health_service_check: Optional[bool] = None - ignore_metrics: Optional[Sequence[str]] = None + ignore_metrics: Optional[tuple[str, ...]] = None ignore_metrics_by_labels: Optional[IgnoreMetricsByLabels] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -101,11 +109,11 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None label_joins: Optional[LabelJoins] = None label_to_hostname: Optional[str] = None - labels_mapper: Optional[Mapping[str, Any]] = None + labels_mapper: Optional[MappingProxyType[str, Any]] = None log_requests: Optional[bool] = None - metric_groups: Optional[Sequence[str]] = None + metric_groups: Optional[tuple[str, ...]] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, str]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, str]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = None ntlm_domain: Optional[str] = None @@ -124,16 +132,16 @@ class InstanceConfig(BaseModel): send_monotonic_with_gauge: Optional[bool] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None - type_overrides: Optional[Mapping[str, Any]] = None + type_overrides: Optional[MappingProxyType[str, Any]] = None use_legacy_auth_encoding: Optional[bool] = None use_process_start_time: Optional[bool] = None username: Optional[str] = None @@ -151,6 +159,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/scylla/datadog_checks/scylla/config_models/shared.py b/scylla/datadog_checks/scylla/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/scylla/datadog_checks/scylla/config_models/shared.py +++ b/scylla/datadog_checks/scylla/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/silk/datadog_checks/silk/config_models/instance.py b/silk/datadog_checks/silk/config_models/instance.py index 249a49fadd219..73b01995ae298 100644 --- a/silk/datadog_checks/silk/config_models/instance.py +++ b/silk/datadog_checks/silk/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -60,8 +65,8 @@ class InstanceConfig(BaseModel): empty_default_hostname: Optional[bool] = None enable_blocksize_statistics: Optional[bool] = None enable_read_write_statistics: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None host_address: str kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None @@ -81,13 +86,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -106,6 +111,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/silk/datadog_checks/silk/config_models/shared.py b/silk/datadog_checks/silk/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/silk/datadog_checks/silk/config_models/shared.py +++ b/silk/datadog_checks/silk/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/singlestore/datadog_checks/singlestore/config_models/instance.py b/singlestore/datadog_checks/singlestore/config_models/instance.py index 9400f1b6e557e..693ac7a5f8376 100644 --- a/singlestore/datadog_checks/singlestore/config_models/instance.py +++ b/singlestore/datadog_checks/singlestore/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,29 +22,32 @@ class CustomQuery(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - columns: Optional[Sequence[Mapping[str, Any]]] = None + columns: Optional[tuple[MappingProxyType[str, Any], ...]] = None query: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_system_metrics: Optional[bool] = None connect_timeout: Optional[int] = None - custom_queries: Optional[Sequence[CustomQuery]] = None + custom_queries: Optional[tuple[CustomQuery, ...]] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None host: str @@ -54,7 +58,7 @@ class InstanceConfig(BaseModel): port: Optional[int] = None read_timeout: Optional[int] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_private_key: Optional[str] = None @@ -78,6 +82,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/singlestore/datadog_checks/singlestore/config_models/shared.py b/singlestore/datadog_checks/singlestore/config_models/shared.py index 45d1293f12b20..888ffc02ce622 100644 --- a/singlestore/datadog_checks/singlestore/config_models/shared.py +++ b/singlestore/datadog_checks/singlestore/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,15 +23,20 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - global_custom_queries: Optional[Sequence[Mapping[str, Any]]] = None + global_custom_queries: Optional[tuple[MappingProxyType[str, Any], ...]] = None service: Optional[str] = None @model_validator(mode='before') def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/snowflake/datadog_checks/snowflake/config_models/instance.py b/snowflake/datadog_checks/snowflake/config_models/instance.py index e307b0710ed5e..36c5022150f37 100644 --- a/snowflake/datadog_checks/snowflake/config_models/instance.py +++ b/snowflake/datadog_checks/snowflake/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,24 +22,27 @@ class CustomQuery(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - columns: Optional[Sequence[Mapping[str, Any]]] = None + columns: Optional[tuple[MappingProxyType[str, Any], ...]] = None query: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) account: str @@ -46,12 +50,12 @@ class InstanceConfig(BaseModel): authenticator: Optional[str] = None client_prefetch_threads: Optional[int] = None client_session_keep_alive: Optional[bool] = None - custom_queries: Optional[Sequence[CustomQuery]] = None + custom_queries: Optional[tuple[CustomQuery, ...]] = None database: Optional[str] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None login_timeout: Optional[int] = None - metric_groups: Optional[Sequence[str]] = None + metric_groups: Optional[tuple[str, ...]] = None metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None ocsp_response_cache_filename: Optional[str] = None @@ -62,7 +66,7 @@ class InstanceConfig(BaseModel): role: str schema_: Optional[str] = Field(None, alias='schema') service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None token: Optional[str] = None token_path: Optional[str] = None use_global_custom_queries: Optional[str] = None @@ -82,6 +86,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/snowflake/datadog_checks/snowflake/config_models/shared.py b/snowflake/datadog_checks/snowflake/config_models/shared.py index 562a329103e69..b2982be772b20 100644 --- a/snowflake/datadog_checks/snowflake/config_models/shared.py +++ b/snowflake/datadog_checks/snowflake/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,9 +23,10 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - global_custom_queries: Optional[Sequence[Mapping[str, Any]]] = None + global_custom_queries: Optional[tuple[MappingProxyType[str, Any], ...]] = None proxy_host: Optional[str] = None proxy_password: Optional[str] = None proxy_port: Optional[int] = None @@ -35,6 +37,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/solr/datadog_checks/solr/config_models/instance.py b/solr/datadog_checks/solr/config_models/instance.py index 631a321dda3bb..7f94ed9d0769f 100644 --- a/solr/datadog_checks/solr/config_models/instance.py +++ b/solr/datadog_checks/solr/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,6 +22,7 @@ class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_jvm_metrics: Optional[bool] = None @@ -42,7 +43,7 @@ class InstanceConfig(BaseModel): rmi_connection_timeout: Optional[float] = None rmi_registry_ssl: Optional[bool] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tools_jar_path: Optional[str] = None trust_store_password: Optional[str] = None trust_store_path: Optional[str] = None @@ -61,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/solr/datadog_checks/solr/config_models/shared.py b/solr/datadog_checks/solr/config_models/shared.py index 0db55a6d064d5..2e8fd64cd388e 100644 --- a/solr/datadog_checks/solr/config_models/shared.py +++ b/solr/datadog_checks/solr/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,10 +23,11 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_metrics: Optional[bool] = None - conf: Optional[Sequence[Mapping[str, Any]]] = None + conf: Optional[tuple[MappingProxyType[str, Any], ...]] = None is_jmx: bool new_gc_metrics: Optional[bool] = None service: Optional[str] = None @@ -44,6 +46,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/sonarqube/datadog_checks/sonarqube/config_models/instance.py b/sonarqube/datadog_checks/sonarqube/config_models/instance.py index 378d5d10b95f9..469470d7f6c01 100644 --- a/sonarqube/datadog_checks/sonarqube/config_models/instance.py +++ b/sonarqube/datadog_checks/sonarqube/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,33 +22,37 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ComponentsDiscovery(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Mapping[str, Any]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[MappingProxyType[str, Any]] = None limit: Optional[int] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -57,15 +62,15 @@ class InstanceConfig(BaseModel): aws_region: Optional[str] = None aws_service: Optional[str] = None collect_default_jvm_metrics: Optional[bool] = None - components: Optional[Mapping[str, Any]] = None + components: Optional[MappingProxyType[str, Any]] = None components_discovery: Optional[ComponentsDiscovery] = None connect_timeout: Optional[float] = None - default_exclude: Optional[Sequence[str]] = None - default_include: Optional[Sequence[str]] = None + default_exclude: Optional[tuple[str, ...]] = None + default_include: Optional[tuple[str, ...]] = None default_tag: Optional[str] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None host: Optional[str] = None is_jmx: Optional[bool] = None java_bin_path: Optional[str] = None @@ -96,13 +101,13 @@ class InstanceConfig(BaseModel): rmi_registry_ssl: Optional[bool] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None tools_jar_path: Optional[str] = None @@ -126,6 +131,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/sonarqube/datadog_checks/sonarqube/config_models/shared.py b/sonarqube/datadog_checks/sonarqube/config_models/shared.py index 83534741d4019..8e35eb51f1c45 100644 --- a/sonarqube/datadog_checks/sonarqube/config_models/shared.py +++ b/sonarqube/datadog_checks/sonarqube/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,20 +22,22 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_metrics: Optional[bool] = None - conf: Optional[Sequence[Mapping[str, Any]]] = None + conf: Optional[tuple[MappingProxyType[str, Any], ...]] = None is_jmx: Optional[bool] = None new_gc_metrics: Optional[bool] = None proxy: Optional[Proxy] = None @@ -56,6 +59,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/spark/datadog_checks/spark/config_models/instance.py b/spark/datadog_checks/spark/config_models/instance.py index d5833281005c9..81b8d2bf97c8e 100644 --- a/spark/datadog_checks/spark/config_models/instance.py +++ b/spark/datadog_checks/spark/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -62,8 +67,8 @@ class InstanceConfig(BaseModel): empty_default_hostname: Optional[bool] = None enable_query_name_tag: Optional[bool] = None executor_level_metrics: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -86,16 +91,16 @@ class InstanceConfig(BaseModel): spark_cluster_mode: Optional[str] = None spark_pre_20_mode: Optional[bool] = None spark_proxy_enabled: Optional[bool] = None - spark_ui_ports: Optional[Sequence[int]] = None + spark_ui_ports: Optional[tuple[int, ...]] = None spark_url: str streaming_metrics: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -114,6 +119,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/spark/datadog_checks/spark/config_models/shared.py b/spark/datadog_checks/spark/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/spark/datadog_checks/spark/config_models/shared.py +++ b/spark/datadog_checks/spark/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/sqlserver/datadog_checks/sqlserver/config_models/instance.py b/sqlserver/datadog_checks/sqlserver/config_models/instance.py index c7a2d3dd7b7e9..6f632ed3e705e 100644 --- a/sqlserver/datadog_checks/sqlserver/config_models/instance.py +++ b/sqlserver/datadog_checks/sqlserver/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,6 +22,7 @@ class Aws(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) instance_endpoint: Optional[str] = None @@ -28,6 +30,7 @@ class Aws(BaseModel): class Azure(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) deployment_type: Optional[str] = None @@ -36,15 +39,17 @@ class Azure(BaseModel): class CustomQuery(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - columns: Optional[Sequence[Mapping[str, Any]]] = None + columns: Optional[tuple[MappingProxyType[str, Any], ...]] = None query: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None class Gcp(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) instance_id: Optional[str] = None @@ -53,14 +58,16 @@ class Gcp(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class ObfuscatorOptions(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) collect_commands: Optional[bool] = None @@ -73,6 +80,7 @@ class ObfuscatorOptions(BaseModel): class QueryActivity(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) collection_interval: Optional[float] = None @@ -81,6 +89,7 @@ class QueryActivity(BaseModel): class QueryMetrics(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) collection_interval: Optional[float] = None @@ -95,24 +104,25 @@ class QueryMetrics(BaseModel): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) adoprovider: Optional[str] = None ao_database: Optional[str] = None autodiscovery_db_service_check: Optional[bool] = None - autodiscovery_exclude: Optional[Sequence[str]] = None - autodiscovery_include: Optional[Sequence[str]] = None + autodiscovery_exclude: Optional[tuple[str, ...]] = None + autodiscovery_include: Optional[tuple[str, ...]] = None availability_group: Optional[str] = None aws: Optional[Aws] = None azure: Optional[Azure] = None command_timeout: Optional[int] = None connection_string: Optional[str] = None connector: Optional[str] = None - custom_queries: Optional[Sequence[CustomQuery]] = None + custom_queries: Optional[tuple[CustomQuery, ...]] = None database: Optional[str] = None database_autodiscovery: Optional[bool] = None database_autodiscovery_interval: Optional[int] = None - db_fragmentation_object_names: Optional[Sequence[str]] = None + db_fragmentation_object_names: Optional[tuple[str, ...]] = None dbm: Optional[bool] = None disable_generic_tags: Optional[bool] = None driver: Optional[str] = None @@ -143,7 +153,7 @@ class InstanceConfig(BaseModel): server_version: Optional[str] = None service: Optional[str] = None stored_procedure: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None use_global_custom_queries: Optional[str] = None username: Optional[str] = None @@ -160,6 +170,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/sqlserver/datadog_checks/sqlserver/config_models/shared.py b/sqlserver/datadog_checks/sqlserver/config_models/shared.py index 12d1bc5787102..37a0c2e3a9923 100644 --- a/sqlserver/datadog_checks/sqlserver/config_models/shared.py +++ b/sqlserver/datadog_checks/sqlserver/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,16 +23,21 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - custom_metrics: Optional[Sequence[Mapping[str, Any]]] = None - global_custom_queries: Optional[Sequence[Mapping[str, Any]]] = None + custom_metrics: Optional[tuple[MappingProxyType[str, Any], ...]] = None + global_custom_queries: Optional[tuple[MappingProxyType[str, Any], ...]] = None service: Optional[str] = None @model_validator(mode='before') def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/squid/datadog_checks/squid/config_models/instance.py b/squid/datadog_checks/squid/config_models/instance.py index 3c25b1571159d..7b43002819846 100644 --- a/squid/datadog_checks/squid/config_models/instance.py +++ b/squid/datadog_checks/squid/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,8 +63,8 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None host: Optional[str] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None @@ -81,13 +86,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -106,6 +111,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/squid/datadog_checks/squid/config_models/shared.py b/squid/datadog_checks/squid/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/squid/datadog_checks/squid/config_models/shared.py +++ b/squid/datadog_checks/squid/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ssh_check/datadog_checks/ssh_check/config_models/instance.py b/ssh_check/datadog_checks/ssh_check/config_models/instance.py index 93c090ff165a3..3ee695d37cb8e 100644 --- a/ssh_check/datadog_checks/ssh_check/config_models/instance.py +++ b/ssh_check/datadog_checks/ssh_check/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) add_missing_keys: Optional[bool] = None @@ -44,7 +46,7 @@ class InstanceConfig(BaseModel): private_key_type: Optional[str] = None service: Optional[str] = None sftp_check: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None username: str @model_validator(mode='before') @@ -60,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/ssh_check/datadog_checks/ssh_check/config_models/shared.py b/ssh_check/datadog_checks/ssh_check/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/ssh_check/datadog_checks/ssh_check/config_models/shared.py +++ b/ssh_check/datadog_checks/ssh_check/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/statsd/datadog_checks/statsd/config_models/instance.py b/statsd/datadog_checks/statsd/config_models/instance.py index 89f10fefd2b8c..a7cd45378be68 100644 --- a/statsd/datadog_checks/statsd/config_models/instance.py +++ b/statsd/datadog_checks/statsd/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None @@ -39,7 +41,7 @@ class InstanceConfig(BaseModel): min_collection_interval: Optional[float] = None port: Optional[int] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None @model_validator(mode='before') @@ -55,6 +57,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/statsd/datadog_checks/statsd/config_models/shared.py b/statsd/datadog_checks/statsd/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/statsd/datadog_checks/statsd/config_models/shared.py +++ b/statsd/datadog_checks/statsd/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/strimzi/datadog_checks/strimzi/config_models/instance.py b/strimzi/datadog_checks/strimzi/config_models/instance.py index 040fc5bd6ec7a..a373219c88010 100644 --- a/strimzi/datadog_checks/strimzi/config_models/instance.py +++ b/strimzi/datadog_checks/strimzi/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,14 +41,16 @@ class ExtraMetric(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -55,24 +60,27 @@ class Metric(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -90,18 +98,18 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -111,7 +119,7 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') non_cumulative_histogram_buckets: Optional[bool] = None @@ -120,23 +128,23 @@ class InstanceConfig(BaseModel): password: Optional[str] = None persist_connections: Optional[bool] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None service: Optional[str] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None tag_by_endpoint: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None topic_operator_endpoint: Optional[str] = None @@ -159,6 +167,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/strimzi/datadog_checks/strimzi/config_models/shared.py b/strimzi/datadog_checks/strimzi/config_models/shared.py index 59c534d071001..6e5763403db19 100644 --- a/strimzi/datadog_checks/strimzi/config_models/shared.py +++ b/strimzi/datadog_checks/strimzi/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/supervisord/datadog_checks/supervisord/config_models/instance.py b/supervisord/datadog_checks/supervisord/config_models/instance.py index 17d891e0cf7e6..1e4b71ad06284 100644 --- a/supervisord/datadog_checks/supervisord/config_models/instance.py +++ b/supervisord/datadog_checks/supervisord/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None @@ -40,11 +42,11 @@ class InstanceConfig(BaseModel): name: str password: Optional[str] = None port: Optional[int] = None - proc_names: Optional[Sequence[str]] = None - proc_regex: Optional[Sequence[str]] = None + proc_names: Optional[tuple[str, ...]] = None + proc_regex: Optional[tuple[str, ...]] = None service: Optional[str] = None socket: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None username: Optional[str] = None @model_validator(mode='before') @@ -60,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/supervisord/datadog_checks/supervisord/config_models/shared.py b/supervisord/datadog_checks/supervisord/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/supervisord/datadog_checks/supervisord/config_models/shared.py +++ b/supervisord/datadog_checks/supervisord/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/system_core/datadog_checks/system_core/config_models/instance.py b/system_core/datadog_checks/system_core/config_models/instance.py index 9fd87afb27b4b..8b81148f03f3d 100644 --- a/system_core/datadog_checks/system_core/config_models/instance.py +++ b/system_core/datadog_checks/system_core/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None @@ -37,7 +39,7 @@ class InstanceConfig(BaseModel): metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -52,6 +54,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/system_core/datadog_checks/system_core/config_models/shared.py b/system_core/datadog_checks/system_core/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/system_core/datadog_checks/system_core/config_models/shared.py +++ b/system_core/datadog_checks/system_core/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/system_swap/datadog_checks/system_swap/config_models/instance.py b/system_swap/datadog_checks/system_swap/config_models/instance.py index 9fd87afb27b4b..8b81148f03f3d 100644 --- a/system_swap/datadog_checks/system_swap/config_models/instance.py +++ b/system_swap/datadog_checks/system_swap/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None @@ -37,7 +39,7 @@ class InstanceConfig(BaseModel): metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -52,6 +54,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/system_swap/datadog_checks/system_swap/config_models/shared.py b/system_swap/datadog_checks/system_swap/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/system_swap/datadog_checks/system_swap/config_models/shared.py +++ b/system_swap/datadog_checks/system_swap/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/tcp_check/datadog_checks/tcp_check/config_models/instance.py b/tcp_check/datadog_checks/tcp_check/config_models/instance.py index e2a8ae99e2c47..0f6e788cb36db 100644 --- a/tcp_check/datadog_checks/tcp_check/config_models/instance.py +++ b/tcp_check/datadog_checks/tcp_check/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_response_time: Optional[bool] = None @@ -44,7 +46,7 @@ class InstanceConfig(BaseModel): name: str port: int service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None @model_validator(mode='before') @@ -60,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/tcp_check/datadog_checks/tcp_check/config_models/shared.py b/tcp_check/datadog_checks/tcp_check/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/tcp_check/datadog_checks/tcp_check/config_models/shared.py +++ b/tcp_check/datadog_checks/tcp_check/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/teamcity/datadog_checks/teamcity/config_models/instance.py b/teamcity/datadog_checks/teamcity/config_models/instance.py index 924b244acb9c7..579f9eb9a7597 100644 --- a/teamcity/datadog_checks/teamcity/config_models/instance.py +++ b/teamcity/datadog_checks/teamcity/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,14 +41,16 @@ class ExtraMetric(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -55,42 +60,47 @@ class Metric(BaseModel): class IncludeItem(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None limit: Optional[int] = 5 class Projects(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[IncludeItem]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[IncludeItem, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -113,21 +123,21 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None experimental_metrics: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - global_build_configs_exclude: Optional[Sequence[str]] = None - global_build_configs_include: Optional[Sequence[str]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + global_build_configs_exclude: Optional[tuple[str, ...]] = None + global_build_configs_include: Optional[tuple[str, ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -137,7 +147,7 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') non_cumulative_histogram_buckets: Optional[bool] = None @@ -148,17 +158,17 @@ class InstanceConfig(BaseModel): projects: Optional[Projects] = None projects_refresh_interval: Optional[int] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None server: str service: Optional[str] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None tag_by_endpoint: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None tests_health_check: Optional[bool] = None timeout: Optional[float] = None @@ -166,7 +176,7 @@ class InstanceConfig(BaseModel): tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_latest_spec: Optional[bool] = None @@ -188,6 +198,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/teamcity/datadog_checks/teamcity/config_models/shared.py b/teamcity/datadog_checks/teamcity/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/teamcity/datadog_checks/teamcity/config_models/shared.py +++ b/teamcity/datadog_checks/teamcity/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/temporal/datadog_checks/temporal/config_models/instance.py b/temporal/datadog_checks/temporal/config_models/instance.py index 364568d359afa..b6a897cec5b0e 100644 --- a/temporal/datadog_checks/temporal/config_models/instance.py +++ b/temporal/datadog_checks/temporal/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,14 +41,16 @@ class ExtraMetric(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -55,24 +60,27 @@ class Metric(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -89,18 +97,18 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -110,7 +118,7 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') non_cumulative_histogram_buckets: Optional[bool] = None @@ -119,23 +127,23 @@ class InstanceConfig(BaseModel): password: Optional[str] = None persist_connections: Optional[bool] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None service: Optional[str] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None tag_by_endpoint: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_latest_spec: Optional[bool] = None @@ -156,6 +164,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/temporal/datadog_checks/temporal/config_models/shared.py b/temporal/datadog_checks/temporal/config_models/shared.py index 59c534d071001..6e5763403db19 100644 --- a/temporal/datadog_checks/temporal/config_models/shared.py +++ b/temporal/datadog_checks/temporal/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/teradata/datadog_checks/teradata/config_models/instance.py b/teradata/datadog_checks/teradata/config_models/instance.py index 603c66a0857d0..7a8f0d990f1af 100644 --- a/teradata/datadog_checks/teradata/config_models/instance.py +++ b/teradata/datadog_checks/teradata/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator from typing_extensions import Literal @@ -22,32 +23,36 @@ class CustomQuery(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - columns: Optional[Sequence[Mapping[str, Any]]] = None + columns: Optional[tuple[MappingProxyType[str, Any], ...]] = None query: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Table(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) account: Optional[str] = None @@ -55,7 +60,7 @@ class InstanceConfig(BaseModel): auth_mechanism: Optional[Literal['TD2', 'TDNEGO', 'LDAP', 'KRB5', 'JWT']] = None collect_res_usage_metrics: Optional[bool] = None collect_table_disk_metrics: Optional[bool] = None - custom_queries: Optional[Sequence[CustomQuery]] = None + custom_queries: Optional[tuple[CustomQuery, ...]] = None database: str disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None @@ -69,8 +74,8 @@ class InstanceConfig(BaseModel): service: Optional[str] = None ssl_mode: Optional[Literal['Allow', 'Disable', 'Prefer', 'Require']] = None ssl_protocol: Optional[str] = None - tables: Optional[Union[Sequence[str], Table]] = None - tags: Optional[Sequence[str]] = None + tables: Optional[Union[tuple[str, ...], Table]] = None + tags: Optional[tuple[str, ...]] = None use_global_custom_queries: Optional[str] = None username: Optional[str] = None @@ -87,6 +92,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/teradata/datadog_checks/teradata/config_models/shared.py b/teradata/datadog_checks/teradata/config_models/shared.py index 505547fd024b3..985fd9fe4fea0 100644 --- a/teradata/datadog_checks/teradata/config_models/shared.py +++ b/teradata/datadog_checks/teradata/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,15 +23,20 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - global_custom_queries: Optional[Sequence[Mapping[str, Any]]] = None + global_custom_queries: Optional[tuple[MappingProxyType[str, Any], ...]] = None service: Optional[str] = None @model_validator(mode='before') def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/tls/datadog_checks/tls/config_models/instance.py b/tls/datadog_checks/tls/config_models/instance.py index 8020a455598d3..73f75f2f30674 100644 --- a/tls/datadog_checks/tls/config_models/instance.py +++ b/tls/datadog_checks/tls/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator from typing_extensions import Literal @@ -22,18 +22,20 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - allowed_versions: Optional[Sequence[str]] = None + allowed_versions: Optional[tuple[str, ...]] = None days_critical: Optional[float] = None days_warning: Optional[float] = None disable_generic_tags: Optional[bool] = None @@ -52,7 +54,7 @@ class InstanceConfig(BaseModel): server_hostname: Optional[str] = None service: Optional[str] = None start_tls: Optional[Literal['postgres', 'mysql']] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[int] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None @@ -75,6 +77,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/tls/datadog_checks/tls/config_models/shared.py b/tls/datadog_checks/tls/config_models/shared.py index b8e50175791f5..bc883797f259b 100644 --- a/tls/datadog_checks/tls/config_models/shared.py +++ b/tls/datadog_checks/tls/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,9 +22,10 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - allowed_versions: Optional[Sequence[str]] = None + allowed_versions: Optional[tuple[str, ...]] = None fetch_intermediate_certs: Optional[bool] = None service: Optional[str] = None @@ -41,6 +42,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/tomcat/datadog_checks/tomcat/config_models/instance.py b/tomcat/datadog_checks/tomcat/config_models/instance.py index 631a321dda3bb..7f94ed9d0769f 100644 --- a/tomcat/datadog_checks/tomcat/config_models/instance.py +++ b/tomcat/datadog_checks/tomcat/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,6 +22,7 @@ class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_jvm_metrics: Optional[bool] = None @@ -42,7 +43,7 @@ class InstanceConfig(BaseModel): rmi_connection_timeout: Optional[float] = None rmi_registry_ssl: Optional[bool] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tools_jar_path: Optional[str] = None trust_store_password: Optional[str] = None trust_store_path: Optional[str] = None @@ -61,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/tomcat/datadog_checks/tomcat/config_models/shared.py b/tomcat/datadog_checks/tomcat/config_models/shared.py index 0db55a6d064d5..2e8fd64cd388e 100644 --- a/tomcat/datadog_checks/tomcat/config_models/shared.py +++ b/tomcat/datadog_checks/tomcat/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,10 +23,11 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_metrics: Optional[bool] = None - conf: Optional[Sequence[Mapping[str, Any]]] = None + conf: Optional[tuple[MappingProxyType[str, Any], ...]] = None is_jmx: bool new_gc_metrics: Optional[bool] = None service: Optional[str] = None @@ -44,6 +46,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/torchserve/datadog_checks/torchserve/config_models/instance.py b/torchserve/datadog_checks/torchserve/config_models/instance.py index 173a9700a8f92..eec02e4461d61 100644 --- a/torchserve/datadog_checks/torchserve/config_models/instance.py +++ b/torchserve/datadog_checks/torchserve/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,14 +41,16 @@ class ExtraMetric(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -55,24 +60,27 @@ class Metric(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -89,20 +97,20 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exclude: Optional[Sequence[str]] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - headers: Optional[Mapping[str, Any]] = None + exclude: Optional[tuple[str, ...]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_tags: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None inference_api_url: Optional[str] = None interval: Optional[int] = None kerberos_auth: Optional[str] = None @@ -116,7 +124,7 @@ class InstanceConfig(BaseModel): log_requests: Optional[bool] = None management_api_url: Optional[str] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') non_cumulative_histogram_buckets: Optional[bool] = None @@ -125,24 +133,24 @@ class InstanceConfig(BaseModel): password: Optional[str] = None persist_connections: Optional[bool] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None service: Optional[str] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None submit_events: Optional[bool] = None tag_by_endpoint: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_latest_spec: Optional[bool] = None @@ -163,6 +171,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/torchserve/datadog_checks/torchserve/config_models/shared.py b/torchserve/datadog_checks/torchserve/config_models/shared.py index 59c534d071001..6e5763403db19 100644 --- a/torchserve/datadog_checks/torchserve/config_models/shared.py +++ b/torchserve/datadog_checks/torchserve/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/traffic_server/datadog_checks/traffic_server/config_models/instance.py b/traffic_server/datadog_checks/traffic_server/config_models/instance.py index ba7171e7584f0..3d50ee3023c8b 100644 --- a/traffic_server/datadog_checks/traffic_server/config_models/instance.py +++ b/traffic_server/datadog_checks/traffic_server/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,8 +63,8 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -78,13 +83,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None traffic_server_url: str @@ -104,6 +109,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/traffic_server/datadog_checks/traffic_server/config_models/shared.py b/traffic_server/datadog_checks/traffic_server/config_models/shared.py index d7f4dd28de478..4b2eecdc07b8b 100644 --- a/traffic_server/datadog_checks/traffic_server/config_models/shared.py +++ b/traffic_server/datadog_checks/traffic_server/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/twemproxy/datadog_checks/twemproxy/config_models/instance.py b/twemproxy/datadog_checks/twemproxy/config_models/instance.py index 3dc6609fbfe2a..498587276e17c 100644 --- a/twemproxy/datadog_checks/twemproxy/config_models/instance.py +++ b/twemproxy/datadog_checks/twemproxy/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None @@ -39,7 +41,7 @@ class InstanceConfig(BaseModel): min_collection_interval: Optional[float] = None port: int service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None @model_validator(mode='before') def _initial_validation(cls, values): @@ -54,6 +56,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/twemproxy/datadog_checks/twemproxy/config_models/shared.py b/twemproxy/datadog_checks/twemproxy/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/twemproxy/datadog_checks/twemproxy/config_models/shared.py +++ b/twemproxy/datadog_checks/twemproxy/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/twistlock/datadog_checks/twistlock/config_models/instance.py b/twistlock/datadog_checks/twistlock/config_models/instance.py index 7694701addcd6..f66bb49b620b8 100644 --- a/twistlock/datadog_checks/twistlock/config_models/instance.py +++ b/twistlock/datadog_checks/twistlock/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,32 +22,36 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -58,8 +63,8 @@ class InstanceConfig(BaseModel): connect_timeout: Optional[float] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -79,13 +84,13 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None url: str @@ -105,6 +110,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/twistlock/datadog_checks/twistlock/config_models/shared.py b/twistlock/datadog_checks/twistlock/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/twistlock/datadog_checks/twistlock/config_models/shared.py +++ b/twistlock/datadog_checks/twistlock/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/varnish/datadog_checks/varnish/config_models/instance.py b/varnish/datadog_checks/varnish/config_models/instance.py index b5c4b5be06528..6684dcbff9d65 100644 --- a/varnish/datadog_checks/varnish/config_models/instance.py +++ b/varnish/datadog_checks/varnish/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) daemon_host: Optional[str] = None @@ -37,12 +39,12 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics_filter: Optional[Sequence[str]] = None + metrics_filter: Optional[tuple[str, ...]] = None min_collection_interval: Optional[float] = None name: Optional[str] = None secretfile: Optional[str] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None varnishadm: Optional[str] = None varnishstat: str @@ -59,6 +61,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/varnish/datadog_checks/varnish/config_models/shared.py b/varnish/datadog_checks/varnish/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/varnish/datadog_checks/varnish/config_models/shared.py +++ b/varnish/datadog_checks/varnish/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/vault/datadog_checks/vault/config_models/instance.py b/vault/datadog_checks/vault/config_models/instance.py index 723f4c3a0c09e..41695bbc2a9c2 100644 --- a/vault/datadog_checks/vault/config_models/instance.py +++ b/vault/datadog_checks/vault/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,14 +41,16 @@ class ExtraMetric(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -55,24 +60,27 @@ class Metric(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -94,18 +102,18 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -115,7 +123,7 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') no_token: Optional[bool] = None @@ -125,23 +133,23 @@ class InstanceConfig(BaseModel): password: Optional[str] = None persist_connections: Optional[bool] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None service: Optional[str] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None tag_by_endpoint: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_latest_spec: Optional[bool] = None @@ -163,6 +171,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/vault/datadog_checks/vault/config_models/shared.py b/vault/datadog_checks/vault/config_models/shared.py index fa44821e002af..d85e8eb5227ea 100644 --- a/vault/datadog_checks/vault/config_models/shared.py +++ b/vault/datadog_checks/vault/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/vertica/datadog_checks/vertica/config_models/instance.py b/vertica/datadog_checks/vertica/config_models/instance.py index 5ff3252ebf90e..4f998ec8f7c6e 100644 --- a/vertica/datadog_checks/vertica/config_models/instance.py +++ b/vertica/datadog_checks/vertica/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,34 +22,37 @@ class CustomQuery(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - columns: Optional[Sequence[Mapping[str, Any]]] = None + columns: Optional[tuple[MappingProxyType[str, Any], ...]] = None query: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - backup_servers: Optional[Sequence[Mapping[str, Any]]] = None + backup_servers: Optional[tuple[MappingProxyType[str, Any], ...]] = None client_lib_log_level: Optional[str] = None connection_load_balance: Optional[bool] = None - custom_queries: Optional[Sequence[CustomQuery]] = None + custom_queries: Optional[tuple[CustomQuery, ...]] = None db: Optional[str] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - metric_groups: Optional[Sequence[str]] = None + metric_groups: Optional[tuple[str, ...]] = None metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None only_custom_queries: Optional[bool] = None @@ -56,7 +60,7 @@ class InstanceConfig(BaseModel): port: Optional[int] = None server: Optional[str] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[int] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None @@ -81,6 +85,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/vertica/datadog_checks/vertica/config_models/shared.py b/vertica/datadog_checks/vertica/config_models/shared.py index 45d1293f12b20..888ffc02ce622 100644 --- a/vertica/datadog_checks/vertica/config_models/shared.py +++ b/vertica/datadog_checks/vertica/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,15 +23,20 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - global_custom_queries: Optional[Sequence[Mapping[str, Any]]] = None + global_custom_queries: Optional[tuple[MappingProxyType[str, Any], ...]] = None service: Optional[str] = None @model_validator(mode='before') def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/voltdb/datadog_checks/voltdb/config_models/instance.py b/voltdb/datadog_checks/voltdb/config_models/instance.py index c8f00330406fb..96346aa77d233 100644 --- a/voltdb/datadog_checks/voltdb/config_models/instance.py +++ b/voltdb/datadog_checks/voltdb/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,41 +22,46 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class CustomQuery(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - columns: Optional[Sequence[Mapping[str, Any]]] = None + columns: Optional[tuple[MappingProxyType[str, Any], ...]] = None query: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -65,11 +71,11 @@ class InstanceConfig(BaseModel): aws_region: Optional[str] = None aws_service: Optional[str] = None connect_timeout: Optional[float] = None - custom_queries: Optional[Sequence[CustomQuery]] = None + custom_queries: Optional[tuple[CustomQuery, ...]] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -90,14 +96,14 @@ class InstanceConfig(BaseModel): request_size: Optional[float] = None service: Optional[str] = None skip_proxy: Optional[bool] = None - statistics_components: Optional[Sequence[str]] = None - tags: Optional[Sequence[str]] = None + statistics_components: Optional[tuple[str, ...]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None url: str @@ -118,6 +124,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/voltdb/datadog_checks/voltdb/config_models/shared.py b/voltdb/datadog_checks/voltdb/config_models/shared.py index 175a57ff6454f..b9877fe209ed2 100644 --- a/voltdb/datadog_checks/voltdb/config_models/shared.py +++ b/voltdb/datadog_checks/voltdb/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,19 +22,21 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) - global_custom_queries: Optional[Sequence[Mapping[str, Any]]] = None + global_custom_queries: Optional[tuple[MappingProxyType[str, Any], ...]] = None proxy: Optional[Proxy] = None service: Optional[str] = None skip_proxy: Optional[bool] = None @@ -52,6 +55,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/vsphere/datadog_checks/vsphere/config_models/instance.py b/vsphere/datadog_checks/vsphere/config_models/instance.py index 0dd11a1255934..9713f2bad1abd 100644 --- a/vsphere/datadog_checks/vsphere/config_models/instance.py +++ b/vsphere/datadog_checks/vsphere/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,38 +22,42 @@ class CollectPerInstanceFilters(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - cluster: Optional[Sequence[str]] = None - datastore: Optional[Sequence[str]] = None - host: Optional[Sequence[str]] = None - vm: Optional[Sequence[str]] = None + cluster: Optional[tuple[str, ...]] = None + datastore: Optional[tuple[str, ...]] = None + host: Optional[tuple[str, ...]] = None + vm: Optional[tuple[str, ...]] = None class MetricFilters(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - cluster: Optional[Sequence[str]] = None - datacenter: Optional[Sequence[str]] = None - datastore: Optional[Sequence[str]] = None - host: Optional[Sequence[str]] = None - vm: Optional[Sequence[str]] = None + cluster: Optional[tuple[str, ...]] = None + datacenter: Optional[tuple[str, ...]] = None + datastore: Optional[tuple[str, ...]] = None + host: Optional[tuple[str, ...]] = None + vm: Optional[tuple[str, ...]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class ResourceFilter(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - patterns: Optional[Sequence[str]] = None + patterns: Optional[tuple[str, ...]] = None property: Optional[str] = None resource: Optional[str] = None type: Optional[str] = None @@ -60,23 +65,26 @@ class ResourceFilter(BaseModel): class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class RestApiOptions(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -86,8 +94,8 @@ class RestApiOptions(BaseModel): aws_region: Optional[str] = None aws_service: Optional[str] = None connect_timeout: Optional[float] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -108,7 +116,7 @@ class RestApiOptions(BaseModel): tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -118,6 +126,7 @@ class RestApiOptions(BaseModel): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) attributes_prefix: Optional[str] = None @@ -133,7 +142,7 @@ class InstanceConfig(BaseModel): connection_reset_timeout: Optional[int] = None disable_generic_tags: Optional[bool] = None empty_default_hostname: bool - excluded_host_tags: Optional[Sequence[str]] = None + excluded_host_tags: Optional[tuple[str, ...]] = None host: str include_datastore_cluster_folder_tag: Optional[bool] = None max_historical_metrics: Optional[int] = None @@ -144,12 +153,12 @@ class InstanceConfig(BaseModel): password: str refresh_infrastructure_cache_interval: Optional[int] = None refresh_metrics_metadata_cache_interval: Optional[int] = None - resource_filters: Optional[Sequence[ResourceFilter]] = None + resource_filters: Optional[tuple[ResourceFilter, ...]] = None rest_api_options: Optional[RestApiOptions] = None service: Optional[str] = None ssl_capath: Optional[str] = None ssl_verify: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tags_prefix: Optional[str] = None threads_count: Optional[int] = None tls_ignore_warning: Optional[bool] = None @@ -172,6 +181,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/vsphere/datadog_checks/vsphere/config_models/shared.py b/vsphere/datadog_checks/vsphere/config_models/shared.py index f87d2a23237cd..ba923b55cb25e 100644 --- a/vsphere/datadog_checks/vsphere/config_models/shared.py +++ b/vsphere/datadog_checks/vsphere/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class RestApiOptions(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -40,6 +42,7 @@ class RestApiOptions(BaseModel): class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) rest_api_options: Optional[RestApiOptions] = None @@ -49,6 +52,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/weaviate/datadog_checks/weaviate/config_models/instance.py b/weaviate/datadog_checks/weaviate/config_models/instance.py index ea66679c7482e..c24a57f86980c 100644 --- a/weaviate/datadog_checks/weaviate/config_models/instance.py +++ b/weaviate/datadog_checks/weaviate/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,14 +22,16 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class ExtraMetric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -38,14 +41,16 @@ class ExtraMetric(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metric(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -55,24 +60,27 @@ class Metric(BaseModel): class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class ShareLabel(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - labels: Optional[Sequence[str]] = None - match: Optional[Sequence[str]] = None + labels: Optional[tuple[str, ...]] = None + match: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None @@ -89,18 +97,18 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - exclude_labels: Optional[Sequence[str]] = None - exclude_metrics: Optional[Sequence[str]] = None - exclude_metrics_by_labels: Optional[Mapping[str, Union[bool, Sequence[str]]]] = None - extra_headers: Optional[Mapping[str, Any]] = None - extra_metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, ExtraMetric]]]]] = None - headers: Optional[Mapping[str, Any]] = None + exclude_labels: Optional[tuple[str, ...]] = None + exclude_metrics: Optional[tuple[str, ...]] = None + exclude_metrics_by_labels: Optional[MappingProxyType[str, Union[bool, tuple[str, ...]]]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + extra_metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, ExtraMetric]]], ...]] = None + headers: Optional[MappingProxyType[str, Any]] = None histogram_buckets_as_distributions: Optional[bool] = None hostname_format: Optional[str] = None hostname_label: Optional[str] = None ignore_connection_errors: Optional[bool] = None - ignore_tags: Optional[Sequence[str]] = None - include_labels: Optional[Sequence[str]] = None + ignore_tags: Optional[tuple[str, ...]] = None + include_labels: Optional[tuple[str, ...]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -110,7 +118,7 @@ class InstanceConfig(BaseModel): kerberos_principal: Optional[str] = None log_requests: Optional[bool] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Optional[Sequence[Union[str, Mapping[str, Union[str, Metric]]]]] = None + metrics: Optional[tuple[Union[str, MappingProxyType[str, Union[str, Metric]]], ...]] = None min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') non_cumulative_histogram_buckets: Optional[bool] = None @@ -119,23 +127,23 @@ class InstanceConfig(BaseModel): password: Optional[str] = None persist_connections: Optional[bool] = None proxy: Optional[Proxy] = None - raw_line_filters: Optional[Sequence[str]] = None + raw_line_filters: Optional[tuple[str, ...]] = None raw_metric_prefix: Optional[str] = None read_timeout: Optional[float] = None - rename_labels: Optional[Mapping[str, Any]] = None + rename_labels: Optional[MappingProxyType[str, Any]] = None request_size: Optional[float] = None service: Optional[str] = None - share_labels: Optional[Mapping[str, Union[bool, ShareLabel]]] = None + share_labels: Optional[MappingProxyType[str, Union[bool, ShareLabel]]] = None skip_proxy: Optional[bool] = None tag_by_endpoint: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None telemetry: Optional[bool] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_latest_spec: Optional[bool] = None @@ -157,6 +165,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/weaviate/datadog_checks/weaviate/config_models/shared.py b/weaviate/datadog_checks/weaviate/config_models/shared.py index 59c534d071001..6e5763403db19 100644 --- a/weaviate/datadog_checks/weaviate/config_models/shared.py +++ b/weaviate/datadog_checks/weaviate/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,16 +21,18 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) proxy: Optional[Proxy] = None @@ -51,6 +53,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/weblogic/datadog_checks/weblogic/config_models/instance.py b/weblogic/datadog_checks/weblogic/config_models/instance.py index 631a321dda3bb..7f94ed9d0769f 100644 --- a/weblogic/datadog_checks/weblogic/config_models/instance.py +++ b/weblogic/datadog_checks/weblogic/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,6 +22,7 @@ class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_jvm_metrics: Optional[bool] = None @@ -42,7 +43,7 @@ class InstanceConfig(BaseModel): rmi_connection_timeout: Optional[float] = None rmi_registry_ssl: Optional[bool] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None tools_jar_path: Optional[str] = None trust_store_password: Optional[str] = None trust_store_path: Optional[str] = None @@ -61,6 +62,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/weblogic/datadog_checks/weblogic/config_models/shared.py b/weblogic/datadog_checks/weblogic/config_models/shared.py index 0db55a6d064d5..2e8fd64cd388e 100644 --- a/weblogic/datadog_checks/weblogic/config_models/shared.py +++ b/weblogic/datadog_checks/weblogic/config_models/shared.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -22,10 +23,11 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_default_metrics: Optional[bool] = None - conf: Optional[Sequence[Mapping[str, Any]]] = None + conf: Optional[tuple[MappingProxyType[str, Any], ...]] = None is_jmx: bool new_gc_metrics: Optional[bool] = None service: Optional[str] = None @@ -44,6 +46,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/win32_event_log/datadog_checks/win32_event_log/config_models/instance.py b/win32_event_log/datadog_checks/win32_event_log/config_models/instance.py index 1c13248580c2f..4b194c469cc5c 100644 --- a/win32_event_log/datadog_checks/win32_event_log/config_models/instance.py +++ b/win32_event_log/datadog_checks/win32_event_log/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator from typing_extensions import Literal @@ -22,26 +22,39 @@ class Filters(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - id: Optional[Sequence[int]] = None - source: Optional[Sequence[str]] = None + id: Optional[tuple[int, ...]] = None + source: Optional[tuple[str, ...]] = None type: Optional[ - Sequence[Literal['success', 'error', 'warning', 'information', 'success audit', 'failure audit']] + tuple[ + Literal[ + 'success', + 'error', + 'warning', + 'information', + 'success audit', + 'failure audit', + ], + ..., + ] ] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) auth_type: Optional[Literal['default', 'negotiate', 'kerberos', 'ntlm']] = None @@ -49,17 +62,17 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None domain: Optional[str] = None empty_default_hostname: Optional[bool] = None - event_format: Optional[Sequence[str]] = None - event_id: Optional[Sequence[str]] = None + event_format: Optional[tuple[str, ...]] = None + event_id: Optional[tuple[str, ...]] = None event_priority: Optional[Literal['normal', 'low']] = None - excluded_messages: Optional[Sequence[str]] = None + excluded_messages: Optional[tuple[str, ...]] = None filters: Optional[Filters] = None host: Optional[str] = None - included_messages: Optional[Sequence[str]] = None + included_messages: Optional[tuple[str, ...]] = None interpret_messages: Optional[bool] = None legacy_mode: Optional[bool] = None - log_file: Optional[Sequence[str]] = None - message_filters: Optional[Sequence[str]] = None + log_file: Optional[tuple[str, ...]] = None + message_filters: Optional[tuple[str, ...]] = None metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None password: Optional[str] = None @@ -68,18 +81,20 @@ class InstanceConfig(BaseModel): query: Optional[str] = None server: Optional[str] = None service: Optional[str] = None - source_name: Optional[Sequence[str]] = None + source_name: Optional[tuple[str, ...]] = None start: Optional[Literal['now', 'oldest']] = None tag_event_id: Optional[bool] = None tag_sid: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None - type: Optional[Sequence[str]] = None + type: Optional[tuple[str, ...]] = None user: Optional[str] = None @model_validator(mode='before') def _initial_validation(cls, values): - return validation.core.initialize_config(getattr(validators, 'initialize_instance', identity)(values)) + return validation.core.initialize_config( + getattr(validators, 'initialize_instance', identity)(values) + ) @field_validator('*', mode='before') def _ensure_defaults(cls, value, info): @@ -90,6 +105,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] @@ -97,7 +116,9 @@ def _run_validations(cls, value, info): if field_name not in info.context['configured_fields']: return value - return getattr(validators, f'instance_{info.field_name}', identity)(value, field=field) + return getattr(validators, f'instance_{info.field_name}', identity)( + value, field=field + ) @field_validator('*', mode='after') def _make_immutable(cls, value): @@ -105,4 +126,6 @@ def _make_immutable(cls, value): @model_validator(mode='after') def _final_validation(cls, model): - return validation.core.check_model(getattr(validators, 'check_instance', identity)(model)) + return validation.core.check_model( + getattr(validators, 'check_instance', identity)(model) + ) diff --git a/win32_event_log/datadog_checks/win32_event_log/config_models/shared.py b/win32_event_log/datadog_checks/win32_event_log/config_models/shared.py index f9bffdbac0436..13db73e796287 100644 --- a/win32_event_log/datadog_checks/win32_event_log/config_models/shared.py +++ b/win32_event_log/datadog_checks/win32_event_log/config_models/shared.py @@ -23,6 +23,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) default_event_priority: Optional[str] = None @@ -45,6 +46,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/windows_performance_counters/datadog_checks/windows_performance_counters/config_models/instance.py b/windows_performance_counters/datadog_checks/windows_performance_counters/config_models/instance.py index 45a72e9e57bdb..16da78945d7af 100644 --- a/windows_performance_counters/datadog_checks/windows_performance_counters/config_models/instance.py +++ b/windows_performance_counters/datadog_checks/windows_performance_counters/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Optional, Union from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator from typing_extensions import Literal @@ -22,6 +23,7 @@ class Counter(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, extra='allow', frozen=True, ) @@ -34,6 +36,7 @@ class Counter(BaseModel): class InstanceCounts(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) monitored: Optional[str] = None @@ -43,11 +46,12 @@ class InstanceCounts(BaseModel): class ExtraMetrics(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - counters: Sequence[Mapping[str, Union[str, Counter]]] - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + counters: tuple[MappingProxyType[str, Union[str, Counter]], ...] + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None instance_counts: Optional[InstanceCounts] = None name: str tag_name: Optional[str] = None @@ -56,19 +60,21 @@ class ExtraMetrics(BaseModel): class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Metrics(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - counters: Sequence[Mapping[str, Union[str, Counter]]] - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + counters: tuple[MappingProxyType[str, Union[str, Counter]], ...] + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None instance_counts: Optional[InstanceCounts] = None name: str tag_name: Optional[str] = None @@ -78,21 +84,22 @@ class Metrics(BaseModel): class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None enable_health_service_check: Optional[bool] = None - extra_metrics: Optional[Mapping[str, ExtraMetrics]] = None + extra_metrics: Optional[MappingProxyType[str, ExtraMetrics]] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Mapping[str, Metrics] + metrics: MappingProxyType[str, Metrics] min_collection_interval: Optional[float] = None namespace: Optional[str] = Field(None, pattern='\\w*') password: Optional[str] = None server: Optional[str] = None server_tag: Optional[str] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None use_legacy_check_version: Optional[bool] = None username: Optional[str] = None @@ -109,6 +116,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/windows_performance_counters/datadog_checks/windows_performance_counters/config_models/shared.py b/windows_performance_counters/datadog_checks/windows_performance_counters/config_models/shared.py index aa58639466c05..f7b81f614312a 100644 --- a/windows_performance_counters/datadog_checks/windows_performance_counters/config_models/shared.py +++ b/windows_performance_counters/datadog_checks/windows_performance_counters/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -40,6 +41,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/windows_service/datadog_checks/windows_service/config_models/instance.py b/windows_service/datadog_checks/windows_service/config_models/instance.py index 704d28d35a1e2..8ef9eb2e9fd04 100644 --- a/windows_service/datadog_checks/windows_service/config_models/instance.py +++ b/windows_service/datadog_checks/windows_service/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence, Union +from types import MappingProxyType +from typing import Any, Optional, Union from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +22,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None @@ -38,8 +41,8 @@ class InstanceConfig(BaseModel): metric_patterns: Optional[MetricPatterns] = None min_collection_interval: Optional[float] = None service: Optional[str] = None - services: Sequence[Union[str, Mapping[str, Any]]] - tags: Optional[Sequence[str]] = None + services: tuple[Union[str, MappingProxyType[str, Any]], ...] + tags: Optional[tuple[str, ...]] = None windows_service_startup_type_tag: Optional[bool] = None @model_validator(mode='before') @@ -55,6 +58,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/windows_service/datadog_checks/windows_service/config_models/shared.py b/windows_service/datadog_checks/windows_service/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/windows_service/datadog_checks/windows_service/config_models/shared.py +++ b/windows_service/datadog_checks/windows_service/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/wmi_check/datadog_checks/wmi_check/config_models/instance.py b/wmi_check/datadog_checks/wmi_check/config_models/instance.py index 7f208ac9d3c4b..1a6373e0c4fd4 100644 --- a/wmi_check/datadog_checks/wmi_check/config_models/instance.py +++ b/wmi_check/datadog_checks/wmi_check/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator @@ -21,32 +22,34 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) class_: str = Field(..., alias='class') disable_generic_tags: Optional[bool] = None empty_default_hostname: Optional[bool] = None - filters: Optional[Sequence[Mapping[str, Any]]] = None + filters: Optional[tuple[MappingProxyType[str, Any], ...]] = None host: Optional[str] = None metric_patterns: Optional[MetricPatterns] = None - metrics: Sequence[Sequence[str]] + metrics: tuple[tuple[str, ...], ...] min_collection_interval: Optional[float] = None namespace: Optional[str] = None password: Optional[str] = None provider: Optional[int] = None service: Optional[str] = None tag_by: Optional[str] = None - tag_queries: Optional[Sequence[Sequence[str]]] = None - tags: Optional[Sequence[str]] = None + tag_queries: Optional[tuple[tuple[str, ...], ...]] = None + tags: Optional[tuple[str, ...]] = None username: Optional[str] = None @model_validator(mode='before') @@ -62,6 +65,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/wmi_check/datadog_checks/wmi_check/config_models/shared.py b/wmi_check/datadog_checks/wmi_check/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/wmi_check/datadog_checks/wmi_check/config_models/shared.py +++ b/wmi_check/datadog_checks/wmi_check/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/yarn/datadog_checks/yarn/config_models/instance.py b/yarn/datadog_checks/yarn/config_models/instance.py index b45568e8f0844..a2b1127a594ad 100644 --- a/yarn/datadog_checks/yarn/config_models/instance.py +++ b/yarn/datadog_checks/yarn/config_models/instance.py @@ -9,7 +9,8 @@ from __future__ import annotations -from typing import Any, Mapping, Optional, Sequence +from types import MappingProxyType +from typing import Any, Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator from typing_extensions import Literal @@ -22,37 +23,41 @@ class AuthToken(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - reader: Optional[Mapping[str, Any]] = None - writer: Optional[Mapping[str, Any]] = None + reader: Optional[MappingProxyType[str, Any]] = None + writer: Optional[MappingProxyType[str, Any]] = None class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) allow_redirects: Optional[bool] = None - application_status_mapping: Optional[Mapping[str, Any]] = None - application_tags: Optional[Mapping[str, Any]] = None + application_status_mapping: Optional[MappingProxyType[str, Any]] = None + application_tags: Optional[MappingProxyType[str, Any]] = None auth_token: Optional[AuthToken] = None auth_type: Optional[str] = None aws_host: Optional[str] = None @@ -62,8 +67,19 @@ class InstanceConfig(BaseModel): collect_app_metrics: Optional[bool] = None collect_apps_all_states: Optional[bool] = None collect_apps_states_list: Optional[ - Sequence[ - Literal['ALL', 'NEW', 'NEW_SAVING', 'SUBMITTED', 'ACCEPTED', 'RUNNING', 'FINISHED', 'FAILED', 'KILLED'] + tuple[ + Literal[ + 'ALL', + 'NEW', + 'NEW_SAVING', + 'SUBMITTED', + 'ACCEPTED', + 'RUNNING', + 'FINISHED', + 'FAILED', + 'KILLED', + ], + ..., ] ] = None collect_node_metrics: Optional[bool] = None @@ -71,8 +87,8 @@ class InstanceConfig(BaseModel): disable_generic_tags: Optional[bool] = None disable_legacy_cluster_tag: Optional[bool] = None empty_default_hostname: Optional[bool] = None - extra_headers: Optional[Mapping[str, Any]] = None - headers: Optional[Mapping[str, Any]] = None + extra_headers: Optional[MappingProxyType[str, Any]] = None + headers: Optional[MappingProxyType[str, Any]] = None kerberos_auth: Optional[str] = None kerberos_cache: Optional[str] = None kerberos_delegate: Optional[bool] = None @@ -87,20 +103,20 @@ class InstanceConfig(BaseModel): password: Optional[str] = None persist_connections: Optional[bool] = None proxy: Optional[Proxy] = None - queue_blacklist: Optional[Sequence[str]] = None + queue_blacklist: Optional[tuple[str, ...]] = None read_timeout: Optional[float] = None request_size: Optional[float] = None resourcemanager_uri: Optional[str] = None service: Optional[str] = None skip_proxy: Optional[bool] = None split_yarn_application_tags: Optional[bool] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[float] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None tls_ignore_warning: Optional[bool] = None tls_private_key: Optional[str] = None - tls_protocols_allowed: Optional[Sequence[str]] = None + tls_protocols_allowed: Optional[tuple[str, ...]] = None tls_use_host_header: Optional[bool] = None tls_verify: Optional[bool] = None use_legacy_auth_encoding: Optional[bool] = None @@ -108,7 +124,9 @@ class InstanceConfig(BaseModel): @model_validator(mode='before') def _initial_validation(cls, values): - return validation.core.initialize_config(getattr(validators, 'initialize_instance', identity)(values)) + return validation.core.initialize_config( + getattr(validators, 'initialize_instance', identity)(values) + ) @field_validator('*', mode='before') def _ensure_defaults(cls, value, info): @@ -119,6 +137,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] @@ -126,7 +148,9 @@ def _run_validations(cls, value, info): if field_name not in info.context['configured_fields']: return value - return getattr(validators, f'instance_{info.field_name}', identity)(value, field=field) + return getattr(validators, f'instance_{info.field_name}', identity)( + value, field=field + ) @field_validator('*', mode='after') def _make_immutable(cls, value): @@ -134,4 +158,6 @@ def _make_immutable(cls, value): @model_validator(mode='after') def _final_validation(cls, model): - return validation.core.check_model(getattr(validators, 'check_instance', identity)(model)) + return validation.core.check_model( + getattr(validators, 'check_instance', identity)(model) + ) diff --git a/yarn/datadog_checks/yarn/config_models/shared.py b/yarn/datadog_checks/yarn/config_models/shared.py index f7577f84507f0..7622f450d5f35 100644 --- a/yarn/datadog_checks/yarn/config_models/shared.py +++ b/yarn/datadog_checks/yarn/config_models/shared.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator from typing_extensions import Literal @@ -22,22 +22,35 @@ class Proxy(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) http: Optional[str] = None https: Optional[str] = None - no_proxy: Optional[Sequence[str]] = None + no_proxy: Optional[tuple[str, ...]] = None class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) collect_apps_all_states: Optional[bool] = None collect_apps_states_list: Optional[ - Sequence[ - Literal['ALL', 'NEW', 'NEW_SAVING', 'SUBMITTED', 'ACCEPTED', 'RUNNING', 'FINISHED', 'FAILED', 'KILLED'] + tuple[ + Literal[ + 'ALL', + 'NEW', + 'NEW_SAVING', + 'SUBMITTED', + 'ACCEPTED', + 'RUNNING', + 'FINISHED', + 'FAILED', + 'KILLED', + ], + ..., ] ] = None proxy: Optional[Proxy] = None @@ -47,7 +60,9 @@ class SharedConfig(BaseModel): @model_validator(mode='before') def _initial_validation(cls, values): - return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + return validation.core.initialize_config( + getattr(validators, 'initialize_shared', identity)(values) + ) @field_validator('*', mode='before') def _ensure_defaults(cls, value, info): @@ -58,6 +73,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'shared_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] @@ -65,7 +84,9 @@ def _run_validations(cls, value, info): if field_name not in info.context['configured_fields']: return value - return getattr(validators, f'shared_{info.field_name}', identity)(value, field=field) + return getattr(validators, f'shared_{info.field_name}', identity)( + value, field=field + ) @field_validator('*', mode='after') def _make_immutable(cls, value): @@ -73,4 +94,6 @@ def _make_immutable(cls, value): @model_validator(mode='after') def _final_validation(cls, model): - return validation.core.check_model(getattr(validators, 'check_shared', identity)(model)) + return validation.core.check_model( + getattr(validators, 'check_shared', identity)(model) + ) diff --git a/zk/datadog_checks/zk/config_models/instance.py b/zk/datadog_checks/zk/config_models/instance.py index ee76eaa040628..2587d3f4f62f9 100644 --- a/zk/datadog_checks/zk/config_models/instance.py +++ b/zk/datadog_checks/zk/config_models/instance.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Optional, Sequence +from typing import Optional from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -21,15 +21,17 @@ class MetricPatterns(BaseModel): model_config = ConfigDict( + arbitrary_types_allowed=True, frozen=True, ) - exclude: Optional[Sequence[str]] = None - include: Optional[Sequence[str]] = None + exclude: Optional[tuple[str, ...]] = None + include: Optional[tuple[str, ...]] = None class InstanceConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) disable_generic_tags: Optional[bool] = None @@ -41,7 +43,7 @@ class InstanceConfig(BaseModel): port: Optional[int] = None report_instance_mode: Optional[bool] = None service: Optional[str] = None - tags: Optional[Sequence[str]] = None + tags: Optional[tuple[str, ...]] = None timeout: Optional[int] = None tls_ca_cert: Optional[str] = None tls_cert: Optional[str] = None @@ -64,6 +66,10 @@ def _ensure_defaults(cls, value, info): return getattr(defaults, f'instance_{info.field_name}', lambda: value)() + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name] diff --git a/zk/datadog_checks/zk/config_models/shared.py b/zk/datadog_checks/zk/config_models/shared.py index 9de2608b18ec1..4fe2bfedd6454 100644 --- a/zk/datadog_checks/zk/config_models/shared.py +++ b/zk/datadog_checks/zk/config_models/shared.py @@ -22,6 +22,7 @@ class SharedConfig(BaseModel): model_config = ConfigDict( validate_default=True, + arbitrary_types_allowed=True, frozen=True, ) service: Optional[str] = None @@ -30,6 +31,10 @@ class SharedConfig(BaseModel): def _initial_validation(cls, values): return validation.core.initialize_config(getattr(validators, 'initialize_shared', identity)(values)) + @field_validator('*', mode='before') + def _correct_initial_types(cls, value): + return validation.utils.make_immutable(value) + @field_validator('*') def _run_validations(cls, value, info): field = cls.model_fields[info.field_name]