Skip to content

wrap_kvs will wrap the instance but self of instance is not wrapped #18

@andeaseme

Description

@andeaseme

This behavior is discovered while trying to display available options in a dropdown with streamlitfront without accessing the actual value until it is needed.

The get item of an instance is different from the get item from the self within the instance's method when wrapping a class with wrap_kvs. The self behaves as if the instance is not wrapped.

The test below has two classes:

  1. DoubleWrapSquareStore reapplies wrap_kvs to self in the item_getter method call.
  2. SingleWrapSquareStore does not reapply wrap_kvs and acts like it is not wrapped but you would expect the instance and self to have the same behavior.

Test:

import math
from dataclasses import dataclass
from typing import Any

from dol import wrap_kvs


@dataclass
class ItemGetter:
    """Wraps value in a callable to be retrieved later"""

    instance: Any
    key: Any

    def __call__(self):
        return self.instance[self.key]


wrap_kvs_as_square_data = wrap_kvs(data_of_obj=lambda x: x * x, obj_of_data=math.sqrt)


@wrap_kvs_as_square_data
class DoubleWrapSquareStore(dict):
    def item_getter(self, key) -> ItemGetter:
        """The instance self has wrap_kvs applied again to retain the data conversion"""
        return ItemGetter(instance=wrap_kvs_as_square_data(self), key=key)


@wrap_kvs_as_square_data
class SingleWrapSquareStore(dict):
    def item_getter(self, key) -> ItemGetter:
        """The instance self does not have wrap_kvs reapplied and does not act like the instance"""
        return ItemGetter(instance=self, key=key)


def test_square_store(ss):
    ss['2'] = 2
    ig_from_instance = ItemGetter(ss, '2')()
    ig_from_self = ss.item_getter('2')()

    print(
        f'\nTesting {type(ss).__name__}'
        'These values should be equal:',
        f"{ss['2']=}",
        f'{ig_from_instance=}',
        f'{ig_from_self=}',
        sep='\n',
    )

    assert (
        ss['2'] == ig_from_instance
    ), f'{type(ss).__name__}: ItemGetter value from instance does not match actual value'

    ig_2 = ss.item_getter('2')
    assert (
        ss['2'] == ig_from_self
    ), f'{type(ss).__name__}: ItemGetter value from self does not match actual value'

    assert (
        ig_from_instance == ig_from_self
    ), f'{type(ss).__name__}: ItemGetter value from instance does not match ItemGetter value from self'


test_square_store(DoubleWrapSquareStore())
test_square_store(SingleWrapSquareStore())

Result:

============================= test session starts ==============================
collecting ... 
Testing DoubleWrapSquareStoreThese values should be equal:
ss['2']=2.0
ig_from_instance=2.0
ig_from_self=2.0

Testing SingleWrapSquareStoreThese values should be equal:
ss['2']=2.0
ig_from_instance=2.0
ig_from_self=4

plunk/ap/pain/wrap_kvs_and_self.py:None (plunk/ap/pain/wrap_kvs_and_self.py)
wrap_kvs_and_self.py:64: in <module>
    test_square_store(SingleWrapSquareStore())
wrap_kvs_and_self.py:54: in test_square_store
    assert (
E   AssertionError: SingleWrapSquareStore: ItemGetter value from self does not match actual value
E   assert 2.0 == 4






collected 0 items / 1 error

=============================== 1 error in 0.13s ===============================

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions