Skip to content

Commit

Permalink
feat(common): implement copy protocol for Immutable base class
Browse files Browse the repository at this point in the history
  • Loading branch information
kszucs authored and cpcloud committed Apr 25, 2023
1 parent d2c32bf commit e61c66b
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 13 deletions.
8 changes: 7 additions & 1 deletion ibis/common/grounds.py
Expand Up @@ -155,8 +155,14 @@ def copy(self, **overrides: Any) -> Annotable:


class Immutable(Base):
def __copy__(self):
return self

def __deepcopy__(self, memo):
return self

def __setattr__(self, name: str, _: Any) -> None:
raise TypeError(
raise AttributeError(
f"Attribute {name!r} cannot be assigned to immutable instance of "
f"type {type(self)}"
)
Expand Down
35 changes: 23 additions & 12 deletions ibis/common/tests/test_grounds.py
Expand Up @@ -182,6 +182,26 @@ class MyExpr(Concrete):
c: Map[str, Integer]


def test_immutable():
class Foo(Immutable):
__slots__ = ("a", "b")

def __init__(self, a, b):
object.__setattr__(self, "a", a)
object.__setattr__(self, "b", b)

foo = Foo(1, 2)
assert foo.a == 1
assert foo.b == 2
with pytest.raises(AttributeError):
foo.a = 2
with pytest.raises(AttributeError):
foo.b = 3

assert copy.copy(foo) is foo
assert copy.deepcopy(foo) is foo


def test_annotable():
class InBetween(BetweenSimple):
pass
Expand Down Expand Up @@ -307,11 +327,11 @@ class ImmAnn(Immutable, Annotable):
upper = optional(is_int, default=None)

obj = AnnImm(3, lower=0, upper=4)
with pytest.raises(TypeError):
with pytest.raises(AttributeError):
obj.value = 1

obj = ImmAnn(3, lower=0, upper=4)
with pytest.raises(TypeError):
with pytest.raises(AttributeError):
obj.value = 1


Expand Down Expand Up @@ -715,15 +735,6 @@ class Between(Value, ConditionalOp):
)


def test_immutability():
class Value(Annotable, Immutable):
a = is_int

op = Value(1)
with pytest.raises(TypeError):
op.a = 3


class Value(Annotable):
i = is_int
j = attribute(is_int)
Expand Down Expand Up @@ -1071,7 +1082,7 @@ def test_concrete():
assert obj.argnames == ("value", "lower", "upper")

# immutable
with pytest.raises(TypeError):
with pytest.raises(AttributeError):
obj.value = 11

# hashable
Expand Down

0 comments on commit e61c66b

Please sign in to comment.