Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions fiddle/_src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,22 +348,22 @@ def __getattr__(self, name: str):
) and _field_uses_default_factory(self.__fn_or_cls__, name):
raise ValueError(
"Can't get default value for dataclass field "
+ f'{self.__fn_or_cls__.__qualname__}.{name} '
+ f'{self._fn_or_cls_name_repr()}.{name} '
+ 'since it uses a default_factory.'
)
if param is not None and param.default is not param.empty:
return param.default
msg = (
f"No parameter '{name}' has been set on {self!r} "
f"(Buildable='{self.__fn_or_cls__.__qualname__}', missing "
f"(Buildable='{self._fn_or_cls_name_repr()}', missing "
f"parameter='{name}')."
)
# TODO(b/219988937): Implement an edit distance function and display valid
# attributes that are close to `name`.
if hasattr(self.__fn_or_cls__, name):
msg += (
f' Note: {self.__fn_or_cls__.__module__}.'
f'{self.__fn_or_cls__.__qualname__} has an attribute/method with '
f'{self._fn_or_cls_name_repr()} has an attribute/method with '
'this name, so this could be caused by using a '
f'fdl.{self.__class__.__qualname__} in '
'place of the actual function or class being configured. Did you '
Expand Down
13 changes: 13 additions & 0 deletions fiddle/_src/config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import copy
import dataclasses
import functools
import pickle
import sys
import threading
Expand Down Expand Up @@ -851,6 +852,18 @@ def test_nonexistent_attribute_error(self):
with self.assertRaisesRegex(AttributeError, expected_msg):
getattr(class_config, 'nonexistent_arg')

def test_partial_nonexistent_attribute_error(self):
# This test serves as a regression test that `functools.partial`
# wasn't well handled in error reporting code.
partial_fn = functools.partial(basic_fn, arg1=1)
cfg = fdl.Config(partial_fn)
# The expected error should indicate the missing parameter, not crash trying
# to access __qualname__ on the partial object.
with self.assertRaisesRegex(
AttributeError, r"No parameter 'nonexistent_arg' has been set"
):
getattr(cfg, 'nonexistent_arg')

def test_nonexistent_parameter_error(self):
class_config = fdl.Config(SampleClass)
expected_msg = (r"No parameter named 'nonexistent_arg' exists for "
Expand Down
Loading