We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Support `parametrize(...)` assignments in the `__defaults__` macro
**Is your feature request related to a problem? Please describe.**

The `__defaults__` BUILD file construct helps eliminate the need for boilerplate target field assignments across an entire
directory tree. However, it does not support assigning the result of the `parametrize` macro to a field.

```
# BUILD

__defaults__({
    python_sources: dict(resolve=parametrize(my_resolves())), # InvalidFieldTypeException: expects string, not Parametrize
})
```

**Describe the solution you'd like**

Support `parametrize` in this context in the natural way, i.e. interpret applicable targets as having the field assigned to
`parametrize(...)`.

**Describe alternatives you've considered**

Modifying `tailor` to populate this field on a per-directory basis might work.

**Additional context**

This is very useful when a single Python subproject is intended to run under several lockfiles.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/python/pants/engine/internals/defaults.py`
Content:
```
1 # Copyright 2022 Pants project contributors (see CONTRIBUTORS.md).
2 # Licensed under the Apache License, Version 2.0 (see LICENSE).
3 """The `BuildFileDefaultsParserState.set_defaults` is used by the pants.engine.internals.Parser,
4 exposed as the `__defaults__` BUILD file symbol.
5 
6 When parsing a BUILD (from the rule `pants.engine.internals.build_files.parse_address_family`) the
7 defaults from the closest parent BUILD file is passed as input to the parser, and the new defaults
8 resulting after the BUILD file have been parsed is returned in the `AddressFamily`.
9 
10 These defaults are then applied when creating the `TargetAdaptor` targets by the `Registrar` in the
11 parser.
12 """
13 from __future__ import annotations
14 
15 from dataclasses import dataclass
16 from typing import Any, Iterable, Mapping, Tuple, Union
17 
18 from pants.engine.addresses import Address
19 from pants.engine.target import (
20     Field,
21     ImmutableValue,
22     InvalidFieldException,
23     RegisteredTargetTypes,
24     Target,
25     TargetGenerator,
26 )
27 from pants.engine.unions import UnionMembership
28 from pants.util.frozendict import FrozenDict
29 
30 SetDefaultsValueT = Mapping[str, Any]
31 SetDefaultsKeyT = Union[str, Tuple[str, ...]]
32 SetDefaultsT = Mapping[SetDefaultsKeyT, SetDefaultsValueT]
33 
34 
35 class BuildFileDefaults(FrozenDict[str, FrozenDict[str, ImmutableValue]]):
36     """Map target types to default field values."""
37 
38 
39 @dataclass
40 class BuildFileDefaultsParserState:
41     address: Address
42     defaults: dict[str, Mapping[str, Any]]
43     registered_target_types: RegisteredTargetTypes
44     union_membership: UnionMembership
45 
46     @classmethod
47     def create(
48         cls,
49         path: str,
50         defaults: BuildFileDefaults,
51         registered_target_types: RegisteredTargetTypes,
52         union_membership: UnionMembership,
53     ) -> BuildFileDefaultsParserState:
54         return cls(
55             address=Address(path, generated_name="__defaults__"),
56             defaults=dict(defaults),
57             registered_target_types=registered_target_types,
58             union_membership=union_membership,
59         )
60 
61     def get_frozen_defaults(self) -> BuildFileDefaults:
62         types = self.registered_target_types.aliases_to_types
63         return BuildFileDefaults(
64             {
65                 target_alias: FrozenDict(
66                     {
67                         field_type.alias: field_type.compute_value(
68                             raw_value=default, address=self.address
69                         )
70                         for field_alias, default in fields.items()
71                         for field_type in self._target_type_field_types(types[target_alias])
72                         if field_alias in (field_type.alias, field_type.deprecated_alias)
73                     }
74                 )
75                 for target_alias, fields in self.defaults.items()
76             }
77         )
78 
79     def get(self, target_alias: str) -> Mapping[str, Any]:
80         # Used by `pants.engine.internals.parser.Parser._generate_symbols.Registrar.__call__`
81         return self.defaults.get(target_alias, {})
82 
83     def set_defaults(
84         self,
85         *args: SetDefaultsT,
86         all: SetDefaultsValueT | None = None,
87         extend: bool = False,
88         **kwargs,
89     ) -> None:
90         defaults: dict[str, dict[str, Any]] = (
91             {} if not extend else {k: dict(v) for k, v in self.defaults.items()}
92         )
93 
94         if all is not None:
95             self._process_defaults(
96                 defaults,
97                 {tuple(self.registered_target_types.aliases): all},
98                 ignore_unknown_fields=True,
99             )
100 
101         for arg in args:
102             self._process_defaults(defaults, arg)
103 
104         # Update with new defaults, dropping targets without any default values.
105         for tgt, default in defaults.items():
106             if not default:
107                 self.defaults.pop(tgt, None)
108             else:
109                 self.defaults[tgt] = default
110 
111     def _target_type_field_types(self, target_type: type[Target]) -> tuple[type[Field], ...]:
112         return (
113             *target_type.class_field_types(self.union_membership),
114             *(target_type.moved_fields if issubclass(target_type, TargetGenerator) else ()),
115         )
116 
117     def _process_defaults(
118         self,
119         defaults: dict[str, dict[str, Any]],
120         targets_defaults: SetDefaultsT,
121         ignore_unknown_fields: bool = False,
122     ):
123         if not isinstance(targets_defaults, dict):
124             raise ValueError(
125                 f"Expected dictionary mapping targets to default field values for {self.address} "
126                 f"but got: {type(targets_defaults).__name__}."
127             )
128 
129         types = self.registered_target_types.aliases_to_types
130         for target, default in targets_defaults.items():
131             if not isinstance(default, dict):
132                 raise ValueError(
133                     f"Invalid default field values in {self.address} for target type {target}, "
134                     f"must be an `dict` but was {default!r} with type `{type(default).__name__}`."
135                 )
136 
137             targets: Iterable[str]
138             targets = target if isinstance(target, tuple) else (target,)
139             for target_alias in map(str, targets):
140                 if target_alias in types:
141                     target_type = types[target_alias]
142                 else:
143                     raise ValueError(f"Unrecognized target type {target_alias} in {self.address}.")
144 
145                 # Copy default dict if we may mutate it.
146                 raw_values = dict(default) if ignore_unknown_fields else default
147 
148                 # Validate that field exists on target
149                 valid_field_aliases = set(
150                     target_type._get_field_aliases_to_field_types(
151                         self._target_type_field_types(target_type)
152                     ).keys()
153                 )
154 
155                 for field_alias in default.keys():
156                     if field_alias not in valid_field_aliases:
157                         if ignore_unknown_fields:
158                             del raw_values[field_alias]
159                         else:
160                             raise InvalidFieldException(
161                                 f"Unrecognized field `{field_alias}` for target {target_type.alias}. "
162                                 f"Valid fields are: {', '.join(sorted(valid_field_aliases))}.",
163                             )
164 
165                 # TODO: support parametrization ? --needs special care due to Parametrize object not
166                 # being hashable, and thus not acceptable in a FrozenDict instance.
167 
168                 # Merge all provided defaults for this call.
169                 defaults.setdefault(target_type.alias, {}).update(raw_values)
170
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/python/pants/engine/internals/defaults.py b/src/python/pants/engine/internals/defaults.py
--- a/src/python/pants/engine/internals/defaults.py
+++ b/src/python/pants/engine/internals/defaults.py
@@ -13,9 +13,10 @@
 from __future__ import annotations
 
 from dataclasses import dataclass
-from typing import Any, Iterable, Mapping, Tuple, Union
+from typing import Any, Callable, Iterable, Mapping, Tuple, Union
 
 from pants.engine.addresses import Address
+from pants.engine.internals.parametrize import Parametrize
 from pants.engine.target import (
     Field,
     ImmutableValue,
@@ -26,6 +27,7 @@
 )
 from pants.engine.unions import UnionMembership
 from pants.util.frozendict import FrozenDict
+from pants.util.meta import frozen_after_init
 
 SetDefaultsValueT = Mapping[str, Any]
 SetDefaultsKeyT = Union[str, Tuple[str, ...]]
@@ -36,6 +38,36 @@
     """Map target types to default field values."""
 
 
+@frozen_after_init
+@dataclass(unsafe_hash=True)
+class ParametrizeDefault(Parametrize):
+    """A frozen version of `Parametrize` for defaults.
+
+    This is needed since all defaults must be hashable, which the `Parametrize` class is not nor can
+    it be as it may get unhashable data as input and is unaware of the field type it is being
+    applied to.
+    """
+
+    args: tuple[str, ...]
+    kwargs: FrozenDict[str, ImmutableValue]  # type: ignore[assignment]
+
+    def __init__(self, *args: str, **kwargs: ImmutableValue) -> None:
+        self.args = args
+        self.kwargs = FrozenDict(kwargs)
+
+    @classmethod
+    def create(
+        cls, freeze: Callable[[Any], ImmutableValue], parametrize: Parametrize
+    ) -> ParametrizeDefault:
+        return cls(
+            *map(freeze, parametrize.args),
+            **{kw: freeze(arg) for kw, arg in parametrize.kwargs.items()},
+        )
+
+    def __repr__(self) -> str:
+        return super().__repr__()
+
+
 @dataclass
 class BuildFileDefaultsParserState:
     address: Address
@@ -58,15 +90,25 @@
             union_membership=union_membership,
         )
 
+    def _freeze_field_value(self, field_type: type[Field], value: Any) -> ImmutableValue:
+        if isinstance(value, ParametrizeDefault):
+            return value
+        elif isinstance(value, Parametrize):
+
+            def freeze(v: Any) -> ImmutableValue:
+                return self._freeze_field_value(field_type, v)
+
+            return ParametrizeDefault.create(freeze, value)
+        else:
+            return field_type.compute_value(raw_value=value, address=self.address)
+
     def get_frozen_defaults(self) -> BuildFileDefaults:
         types = self.registered_target_types.aliases_to_types
         return BuildFileDefaults(
             {
                 target_alias: FrozenDict(
                     {
-                        field_type.alias: field_type.compute_value(
-                            raw_value=default, address=self.address
-                        )
+                        field_type.alias: self._freeze_field_value(field_type, default)
                         for field_alias, default in fields.items()
                         for field_type in self._target_type_field_types(types[target_alias])
                         if field_alias in (field_type.alias, field_type.deprecated_alias)
@@ -162,8 +204,5 @@
                                 f"Valid fields are: {', '.join(sorted(valid_field_aliases))}.",
                             )
 
-                # TODO: support parametrization ? --needs special care due to Parametrize object not
-                # being hashable, and thus not acceptable in a FrozenDict instance.
-
                 # Merge all provided defaults for this call.
                 defaults.setdefault(target_type.alias, {}).update(raw_values)

{"golden_diff": "diff --git a/src/python/pants/engine/internals/defaults.py b/src/python/pants/engine/internals/defaults.py\n--- a/src/python/pants/engine/internals/defaults.py\n+++ b/src/python/pants/engine/internals/defaults.py\n@@ -13,9 +13,10 @@\n from __future__ import annotations\n \n from dataclasses import dataclass\n-from typing import Any, Iterable, Mapping, Tuple, Union\n+from typing import Any, Callable, Iterable, Mapping, Tuple, Union\n \n from pants.engine.addresses import Address\n+from pants.engine.internals.parametrize import Parametrize\n from pants.engine.target import (\n     Field,\n     ImmutableValue,\n@@ -26,6 +27,7 @@\n )\n from pants.engine.unions import UnionMembership\n from pants.util.frozendict import FrozenDict\n+from pants.util.meta import frozen_after_init\n \n SetDefaultsValueT = Mapping[str, Any]\n SetDefaultsKeyT = Union[str, Tuple[str, ...]]\n@@ -36,6 +38,36 @@\n     \"\"\"Map target types to default field values.\"\"\"\n \n \n+@frozen_after_init\n+@dataclass(unsafe_hash=True)\n+class ParametrizeDefault(Parametrize):\n+    \"\"\"A frozen version of `Parametrize` for defaults.\n+\n+    This is needed since all defaults must be hashable, which the `Parametrize` class is not nor can\n+    it be as it may get unhashable data as input and is unaware of the field type it is being\n+    applied to.\n+    \"\"\"\n+\n+    args: tuple[str, ...]\n+    kwargs: FrozenDict[str, ImmutableValue]  # type: ignore[assignment]\n+\n+    def __init__(self, *args: str, **kwargs: ImmutableValue) -> None:\n+        self.args = args\n+        self.kwargs = FrozenDict(kwargs)\n+\n+    @classmethod\n+    def create(\n+        cls, freeze: Callable[[Any], ImmutableValue], parametrize: Parametrize\n+    ) -> ParametrizeDefault:\n+        return cls(\n+            *map(freeze, parametrize.args),\n+            **{kw: freeze(arg) for kw, arg in parametrize.kwargs.items()},\n+        )\n+\n+    def __repr__(self) -> str:\n+        return super().__repr__()\n+\n+\n @dataclass\n class BuildFileDefaultsParserState:\n     address: Address\n@@ -58,15 +90,25 @@\n             union_membership=union_membership,\n         )\n \n+    def _freeze_field_value(self, field_type: type[Field], value: Any) -> ImmutableValue:\n+        if isinstance(value, ParametrizeDefault):\n+            return value\n+        elif isinstance(value, Parametrize):\n+\n+            def freeze(v: Any) -> ImmutableValue:\n+                return self._freeze_field_value(field_type, v)\n+\n+            return ParametrizeDefault.create(freeze, value)\n+        else:\n+            return field_type.compute_value(raw_value=value, address=self.address)\n+\n     def get_frozen_defaults(self) -> BuildFileDefaults:\n         types = self.registered_target_types.aliases_to_types\n         return BuildFileDefaults(\n             {\n                 target_alias: FrozenDict(\n                     {\n-                        field_type.alias: field_type.compute_value(\n-                            raw_value=default, address=self.address\n-                        )\n+                        field_type.alias: self._freeze_field_value(field_type, default)\n                         for field_alias, default in fields.items()\n                         for field_type in self._target_type_field_types(types[target_alias])\n                         if field_alias in (field_type.alias, field_type.deprecated_alias)\n@@ -162,8 +204,5 @@\n                                 f\"Valid fields are: {', '.join(sorted(valid_field_aliases))}.\",\n                             )\n \n-                # TODO: support parametrization ? --needs special care due to Parametrize object not\n-                # being hashable, and thus not acceptable in a FrozenDict instance.\n-\n                 # Merge all provided defaults for this call.\n                 defaults.setdefault(target_type.alias, {}).update(raw_values)\n", "issue": "Support `parametrize(...)` assignments in the `__defaults__` macro\n**Is your feature request related to a problem? Please describe.**\r\n\r\nThe `__defaults__` BUILD file construct helps eliminate the need for boilerplate target field assignments across an entire\r\ndirectory tree. However, it does not support assigning the result of the `parametrize` macro to a field.\r\n\r\n```\r\n# BUILD\r\n\r\n__defaults__({\r\n    python_sources: dict(resolve=parametrize(my_resolves())), # InvalidFieldTypeException: expects string, not Parametrize\r\n})\r\n```\r\n\r\n**Describe the solution you'd like**\r\n\r\nSupport `parametrize` in this context in the natural way, i.e. interpret applicable targets as having the field assigned to\r\n`parametrize(...)`.\r\n\r\n**Describe alternatives you've considered**\r\n\r\nModifying `tailor` to populate this field on a per-directory basis might work.\r\n\r\n**Additional context**\r\n\r\nThis is very useful when a single Python subproject is intended to run under several lockfiles.\n", "before_files": [{"content": "# Copyright 2022 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\"\"\"The `BuildFileDefaultsParserState.set_defaults` is used by the pants.engine.internals.Parser,\nexposed as the `__defaults__` BUILD file symbol.\n\nWhen parsing a BUILD (from the rule `pants.engine.internals.build_files.parse_address_family`) the\ndefaults from the closest parent BUILD file is passed as input to the parser, and the new defaults\nresulting after the BUILD file have been parsed is returned in the `AddressFamily`.\n\nThese defaults are then applied when creating the `TargetAdaptor` targets by the `Registrar` in the\nparser.\n\"\"\"\nfrom __future__ import annotations\n\nfrom dataclasses import dataclass\nfrom typing import Any, Iterable, Mapping, Tuple, Union\n\nfrom pants.engine.addresses import Address\nfrom pants.engine.target import (\n    Field,\n    ImmutableValue,\n    InvalidFieldException,\n    RegisteredTargetTypes,\n    Target,\n    TargetGenerator,\n)\nfrom pants.engine.unions import UnionMembership\nfrom pants.util.frozendict import FrozenDict\n\nSetDefaultsValueT = Mapping[str, Any]\nSetDefaultsKeyT = Union[str, Tuple[str, ...]]\nSetDefaultsT = Mapping[SetDefaultsKeyT, SetDefaultsValueT]\n\n\nclass BuildFileDefaults(FrozenDict[str, FrozenDict[str, ImmutableValue]]):\n    \"\"\"Map target types to default field values.\"\"\"\n\n\n@dataclass\nclass BuildFileDefaultsParserState:\n    address: Address\n    defaults: dict[str, Mapping[str, Any]]\n    registered_target_types: RegisteredTargetTypes\n    union_membership: UnionMembership\n\n    @classmethod\n    def create(\n        cls,\n        path: str,\n        defaults: BuildFileDefaults,\n        registered_target_types: RegisteredTargetTypes,\n        union_membership: UnionMembership,\n    ) -> BuildFileDefaultsParserState:\n        return cls(\n            address=Address(path, generated_name=\"__defaults__\"),\n            defaults=dict(defaults),\n            registered_target_types=registered_target_types,\n            union_membership=union_membership,\n        )\n\n    def get_frozen_defaults(self) -> BuildFileDefaults:\n        types = self.registered_target_types.aliases_to_types\n        return BuildFileDefaults(\n            {\n                target_alias: FrozenDict(\n                    {\n                        field_type.alias: field_type.compute_value(\n                            raw_value=default, address=self.address\n                        )\n                        for field_alias, default in fields.items()\n                        for field_type in self._target_type_field_types(types[target_alias])\n                        if field_alias in (field_type.alias, field_type.deprecated_alias)\n                    }\n                )\n                for target_alias, fields in self.defaults.items()\n            }\n        )\n\n    def get(self, target_alias: str) -> Mapping[str, Any]:\n        # Used by `pants.engine.internals.parser.Parser._generate_symbols.Registrar.__call__`\n        return self.defaults.get(target_alias, {})\n\n    def set_defaults(\n        self,\n        *args: SetDefaultsT,\n        all: SetDefaultsValueT | None = None,\n        extend: bool = False,\n        **kwargs,\n    ) -> None:\n        defaults: dict[str, dict[str, Any]] = (\n            {} if not extend else {k: dict(v) for k, v in self.defaults.items()}\n        )\n\n        if all is not None:\n            self._process_defaults(\n                defaults,\n                {tuple(self.registered_target_types.aliases): all},\n                ignore_unknown_fields=True,\n            )\n\n        for arg in args:\n            self._process_defaults(defaults, arg)\n\n        # Update with new defaults, dropping targets without any default values.\n        for tgt, default in defaults.items():\n            if not default:\n                self.defaults.pop(tgt, None)\n            else:\n                self.defaults[tgt] = default\n\n    def _target_type_field_types(self, target_type: type[Target]) -> tuple[type[Field], ...]:\n        return (\n            *target_type.class_field_types(self.union_membership),\n            *(target_type.moved_fields if issubclass(target_type, TargetGenerator) else ()),\n        )\n\n    def _process_defaults(\n        self,\n        defaults: dict[str, dict[str, Any]],\n        targets_defaults: SetDefaultsT,\n        ignore_unknown_fields: bool = False,\n    ):\n        if not isinstance(targets_defaults, dict):\n            raise ValueError(\n                f\"Expected dictionary mapping targets to default field values for {self.address} \"\n                f\"but got: {type(targets_defaults).__name__}.\"\n            )\n\n        types = self.registered_target_types.aliases_to_types\n        for target, default in targets_defaults.items():\n            if not isinstance(default, dict):\n                raise ValueError(\n                    f\"Invalid default field values in {self.address} for target type {target}, \"\n                    f\"must be an `dict` but was {default!r} with type `{type(default).__name__}`.\"\n                )\n\n            targets: Iterable[str]\n            targets = target if isinstance(target, tuple) else (target,)\n            for target_alias in map(str, targets):\n                if target_alias in types:\n                    target_type = types[target_alias]\n                else:\n                    raise ValueError(f\"Unrecognized target type {target_alias} in {self.address}.\")\n\n                # Copy default dict if we may mutate it.\n                raw_values = dict(default) if ignore_unknown_fields else default\n\n                # Validate that field exists on target\n                valid_field_aliases = set(\n                    target_type._get_field_aliases_to_field_types(\n                        self._target_type_field_types(target_type)\n                    ).keys()\n                )\n\n                for field_alias in default.keys():\n                    if field_alias not in valid_field_aliases:\n                        if ignore_unknown_fields:\n                            del raw_values[field_alias]\n                        else:\n                            raise InvalidFieldException(\n                                f\"Unrecognized field `{field_alias}` for target {target_type.alias}. \"\n                                f\"Valid fields are: {', '.join(sorted(valid_field_aliases))}.\",\n                            )\n\n                # TODO: support parametrization ? --needs special care due to Parametrize object not\n                # being hashable, and thus not acceptable in a FrozenDict instance.\n\n                # Merge all provided defaults for this call.\n                defaults.setdefault(target_type.alias, {}).update(raw_values)\n", "path": "src/python/pants/engine/internals/defaults.py"}], "after_files": [{"content": "# Copyright 2022 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\"\"\"The `BuildFileDefaultsParserState.set_defaults` is used by the pants.engine.internals.Parser,\nexposed as the `__defaults__` BUILD file symbol.\n\nWhen parsing a BUILD (from the rule `pants.engine.internals.build_files.parse_address_family`) the\ndefaults from the closest parent BUILD file is passed as input to the parser, and the new defaults\nresulting after the BUILD file have been parsed is returned in the `AddressFamily`.\n\nThese defaults are then applied when creating the `TargetAdaptor` targets by the `Registrar` in the\nparser.\n\"\"\"\nfrom __future__ import annotations\n\nfrom dataclasses import dataclass\nfrom typing import Any, Callable, Iterable, Mapping, Tuple, Union\n\nfrom pants.engine.addresses import Address\nfrom pants.engine.internals.parametrize import Parametrize\nfrom pants.engine.target import (\n    Field,\n    ImmutableValue,\n    InvalidFieldException,\n    RegisteredTargetTypes,\n    Target,\n    TargetGenerator,\n)\nfrom pants.engine.unions import UnionMembership\nfrom pants.util.frozendict import FrozenDict\nfrom pants.util.meta import frozen_after_init\n\nSetDefaultsValueT = Mapping[str, Any]\nSetDefaultsKeyT = Union[str, Tuple[str, ...]]\nSetDefaultsT = Mapping[SetDefaultsKeyT, SetDefaultsValueT]\n\n\nclass BuildFileDefaults(FrozenDict[str, FrozenDict[str, ImmutableValue]]):\n    \"\"\"Map target types to default field values.\"\"\"\n\n\n@frozen_after_init\n@dataclass(unsafe_hash=True)\nclass ParametrizeDefault(Parametrize):\n    \"\"\"A frozen version of `Parametrize` for defaults.\n\n    This is needed since all defaults must be hashable, which the `Parametrize` class is not nor can\n    it be as it may get unhashable data as input and is unaware of the field type it is being\n    applied to.\n    \"\"\"\n\n    args: tuple[str, ...]\n    kwargs: FrozenDict[str, ImmutableValue]  # type: ignore[assignment]\n\n    def __init__(self, *args: str, **kwargs: ImmutableValue) -> None:\n        self.args = args\n        self.kwargs = FrozenDict(kwargs)\n\n    @classmethod\n    def create(\n        cls, freeze: Callable[[Any], ImmutableValue], parametrize: Parametrize\n    ) -> ParametrizeDefault:\n        return cls(\n            *map(freeze, parametrize.args),\n            **{kw: freeze(arg) for kw, arg in parametrize.kwargs.items()},\n        )\n\n    def __repr__(self) -> str:\n        return super().__repr__()\n\n\n@dataclass\nclass BuildFileDefaultsParserState:\n    address: Address\n    defaults: dict[str, Mapping[str, Any]]\n    registered_target_types: RegisteredTargetTypes\n    union_membership: UnionMembership\n\n    @classmethod\n    def create(\n        cls,\n        path: str,\n        defaults: BuildFileDefaults,\n        registered_target_types: RegisteredTargetTypes,\n        union_membership: UnionMembership,\n    ) -> BuildFileDefaultsParserState:\n        return cls(\n            address=Address(path, generated_name=\"__defaults__\"),\n            defaults=dict(defaults),\n            registered_target_types=registered_target_types,\n            union_membership=union_membership,\n        )\n\n    def _freeze_field_value(self, field_type: type[Field], value: Any) -> ImmutableValue:\n        if isinstance(value, ParametrizeDefault):\n            return value\n        elif isinstance(value, Parametrize):\n\n            def freeze(v: Any) -> ImmutableValue:\n                return self._freeze_field_value(field_type, v)\n\n            return ParametrizeDefault.create(freeze, value)\n        else:\n            return field_type.compute_value(raw_value=value, address=self.address)\n\n    def get_frozen_defaults(self) -> BuildFileDefaults:\n        types = self.registered_target_types.aliases_to_types\n        return BuildFileDefaults(\n            {\n                target_alias: FrozenDict(\n                    {\n                        field_type.alias: self._freeze_field_value(field_type, default)\n                        for field_alias, default in fields.items()\n                        for field_type in self._target_type_field_types(types[target_alias])\n                        if field_alias in (field_type.alias, field_type.deprecated_alias)\n                    }\n                )\n                for target_alias, fields in self.defaults.items()\n            }\n        )\n\n    def get(self, target_alias: str) -> Mapping[str, Any]:\n        # Used by `pants.engine.internals.parser.Parser._generate_symbols.Registrar.__call__`\n        return self.defaults.get(target_alias, {})\n\n    def set_defaults(\n        self,\n        *args: SetDefaultsT,\n        all: SetDefaultsValueT | None = None,\n        extend: bool = False,\n        **kwargs,\n    ) -> None:\n        defaults: dict[str, dict[str, Any]] = (\n            {} if not extend else {k: dict(v) for k, v in self.defaults.items()}\n        )\n\n        if all is not None:\n            self._process_defaults(\n                defaults,\n                {tuple(self.registered_target_types.aliases): all},\n                ignore_unknown_fields=True,\n            )\n\n        for arg in args:\n            self._process_defaults(defaults, arg)\n\n        # Update with new defaults, dropping targets without any default values.\n        for tgt, default in defaults.items():\n            if not default:\n                self.defaults.pop(tgt, None)\n            else:\n                self.defaults[tgt] = default\n\n    def _target_type_field_types(self, target_type: type[Target]) -> tuple[type[Field], ...]:\n        return (\n            *target_type.class_field_types(self.union_membership),\n            *(target_type.moved_fields if issubclass(target_type, TargetGenerator) else ()),\n        )\n\n    def _process_defaults(\n        self,\n        defaults: dict[str, dict[str, Any]],\n        targets_defaults: SetDefaultsT,\n        ignore_unknown_fields: bool = False,\n    ):\n        if not isinstance(targets_defaults, dict):\n            raise ValueError(\n                f\"Expected dictionary mapping targets to default field values for {self.address} \"\n                f\"but got: {type(targets_defaults).__name__}.\"\n            )\n\n        types = self.registered_target_types.aliases_to_types\n        for target, default in targets_defaults.items():\n            if not isinstance(default, dict):\n                raise ValueError(\n                    f\"Invalid default field values in {self.address} for target type {target}, \"\n                    f\"must be an `dict` but was {default!r} with type `{type(default).__name__}`.\"\n                )\n\n            targets: Iterable[str]\n            targets = target if isinstance(target, tuple) else (target,)\n            for target_alias in map(str, targets):\n                if target_alias in types:\n                    target_type = types[target_alias]\n                else:\n                    raise ValueError(f\"Unrecognized target type {target_alias} in {self.address}.\")\n\n                # Copy default dict if we may mutate it.\n                raw_values = dict(default) if ignore_unknown_fields else default\n\n                # Validate that field exists on target\n                valid_field_aliases = set(\n                    target_type._get_field_aliases_to_field_types(\n                        self._target_type_field_types(target_type)\n                    ).keys()\n                )\n\n                for field_alias in default.keys():\n                    if field_alias not in valid_field_aliases:\n                        if ignore_unknown_fields:\n                            del raw_values[field_alias]\n                        else:\n                            raise InvalidFieldException(\n                                f\"Unrecognized field `{field_alias}` for target {target_type.alias}. \"\n                                f\"Valid fields are: {', '.join(sorted(valid_field_aliases))}.\",\n                            )\n\n                # Merge all provided defaults for this call.\n                defaults.setdefault(target_type.alias, {}).update(raw_values)\n", "path": "src/python/pants/engine/internals/defaults.py"}]}