def test_getattr_path_and_setattr_path(): class Baz: def __init__(self): self.quux = 3 class Bar: def __init__(self): self.baz = Baz() class Foo: def __init__(self): self.bar = Bar() foo = Foo() assert getattr_path(foo, 'bar__baz__quux') == 3 setattr_path(foo, 'bar__baz__quux', 7) assert getattr_path(foo, 'bar__baz__quux') == 7 setattr_path(foo, 'bar__baz', None) assert getattr_path(foo, 'bar__baz__quux') is None setattr_path(foo, 'bar', None) assert foo.bar is None
def test_getattr_path_and_setattr_path(): class Baz(object): def __init__(self): self.quux = 3 class Bar(object): def __init__(self): self.baz = Baz() class Foo(object): def __init__(self): self.bar = Bar() foo = Foo() assert 3 == getattr_path(foo, 'bar__baz__quux') setattr_path(foo, 'bar__baz__quux', 7) assert 7 == getattr_path(foo, 'bar__baz__quux') setattr_path(foo, 'bar__baz', None) assert None is getattr_path(foo, 'bar__baz__quux') setattr_path(foo, 'bar', None) assert None is foo.bar
def test_getattr_missing_attribute(): obj = object() with pytest.raises(AttributeError) as e: getattr_path(obj, 'foo') assert str( e.value ) == "'object' object has no attribute path 'foo', since 'object' object has no attribute 'foo'" with pytest.raises(AttributeError) as e: getattr_path(Struct(foo=object()), 'foo__bar') assert str( e.value ) == "'Struct' object has no attribute path 'foo__bar', since 'object' object has no attribute 'bar'"
def reinvoke(obj: Any, additional_kwargs: Dict[str, Any]) -> Any: assert is_reinvokable( obj ), f'reinvoke() called on object with missing @reinvokable constructor decorator: {obj!r}' additional_kwargs_namespace = Namespace(additional_kwargs) kwargs = {} for name, saved_param in items(obj._iommi_saved_params): try: new_param = getattr_path(additional_kwargs_namespace, name) except AttributeError: kwargs[name] = saved_param else: if is_reinvokable(saved_param): assert isinstance(new_param, dict) kwargs[name] = reinvoke(saved_param, new_param) else: if isinstance(saved_param, Namespace): kwargs[name] = Namespace(saved_param, new_param) else: kwargs[name] = new_param additional_kwargs_namespace.pop('call_target', None) kwargs = Namespace( additional_kwargs_namespace, kwargs) # Also include those keys not already in the original result = type(obj)(**kwargs) retain_special_cases(obj, result) return result
def reinvoke_new_defaults(obj: Any, additional_kwargs: Dict[str, Any]) -> Any: assert is_reinvokable(obj), f'reinvoke_new_defaults() called on object with ' \ f'missing @reinvokable constructor decorator: {obj!r}' additional_kwargs_namespace = Namespace(additional_kwargs) kwargs = Namespace(additional_kwargs_namespace) for name, saved_param in items(obj._iommi_saved_params): try: new_param = getattr_path(additional_kwargs_namespace, name) except AttributeError: kwargs[name] = saved_param else: if is_reinvokable(saved_param): assert isinstance(new_param, dict) kwargs[name] = reinvoke_new_defaults(saved_param, new_param) else: if isinstance(saved_param, Namespace): kwargs[name] = Namespace(new_param, saved_param) else: kwargs[name] = saved_param additional_kwargs_namespace.pop('call_target', None) try: result = type(obj)(**kwargs) except TypeError as e: raise InvalidStyleConfigurationException( f'Object {obj!r} could not be updated with style configuration {flatten(additional_kwargs_namespace)}' ) from e retain_special_cases(obj, result) return result
def reinvoke(self, additional_kwargs: Dict[str, Any]) -> "Traversable": assert hasattr(self, '_iommi_saved_params'), f'reinvoke() called on class with missing @reinvokable decorator: {self.__class__.__name__}' additional_kwargs_namespace = Namespace(additional_kwargs) kwargs = {} for name, saved_param in items(self._iommi_saved_params): try: new_param = getattr_path(additional_kwargs_namespace, name) except AttributeError: kwargs[name] = saved_param else: if hasattr(saved_param, 'reinvoke'): assert isinstance(new_param, dict) kwargs[name] = saved_param.reinvoke(new_param) else: if isinstance(saved_param, Namespace): kwargs[name] = Namespace(saved_param, new_param) else: kwargs[name] = new_param additional_kwargs_namespace.pop('call_target', None) kwargs = Namespace(additional_kwargs_namespace, kwargs) # Also include those keys not already in the original result = type(self)(**kwargs) result._name = self._name __tri_declarative_shortcut_stack = getattr(self, '__tri_declarative_shortcut_stack', None) if __tri_declarative_shortcut_stack is not None: setattr(result, '__tri_declarative_shortcut_stack', __tri_declarative_shortcut_stack) return result
def value_to_str_for_query(filter, v): if type(v) == bool: return {True: '1', False: '0'}.get(v) if type(v) in (int, float): return str(v) if isinstance(v, Model): model = type(v) search_field = filter.search_fields[0] try: v = getattr_path(v, search_field) except AttributeError: raise NoRegisteredSearchFieldException( f'{model.__name__} has no attribute {search_field}. Please register search fields with register_search_fields or specify search_fields.' ) return to_string_surrounded_by_quote(v)
def read_from_instance(field: 'Field', instance: Any) -> Any: return getattr_path(instance, field.attr)
def many_to_many_factory_write_to_instance(field, instance, value): getattr_path(instance, field.attr).set(value)
def many_to_many_factory_read_from_instance(field, instance): return getattr_path(instance, field.attr).all()
def test_getattr_default(): assert getattr_path(object(), 'foo', 17) == 17 assert getattr_path(Struct(foo=object()), 'foo__bar', 42) == 42 assert getattr_path(object(), 'foo', default=17) == 17 assert getattr_path(Struct(foo=object()), 'foo__bar', default=42) == 42
def test_getattr_empty_path(): obj = object() assert getattr_path(obj, '') is obj