2

I know you can define data descriptors for a class instance using the __get__ and __set__ methods. Is it possible to define something similar for an imported module ?

Use case:

I have a large test file with a lot of dictionaries defined in a test_data.py (legacy code), therefore all of them are **mutable and cannot be modified by individual tests without using deepcopy

I want to be able to modify these dictionaries

  1. Without re-writing the data into classes
  2. without calling deepcopy in tests.

Test data:

expected_response_1 = dict(status=False)

Test case:

from test import test_data

data = test_data.expected_response_1
data['status'] = True

print(data)
# --> {'status': True}

print(test_data.expected_response_1)
# --> {'status': False}

Is there any *python-magic i can use to always return a copy of expected_response_1

Tobey
  • 1,400
  • 1
  • 10
  • 25
  • Maybe you can use a tool like https://dictdiffer.readthedocs.io/en/latest/ It has the feature of change, diff and revert dictionaries. – Cartucho Dec 13 '18 at 12:11

2 Answers2

1

This cannot be done directly since descriptors need to be defined as class attributes (which mean you'd have to add them to the builtin module type, which is not allowed).

BUT you can just use a simple wrapper around your test_data module and use the __getattr__() magic method:

class DataWrapper(object):
    def __init__(self, module):
        self._module = module

    def __getattr__(self, name):
        val = getattr(self._module, name)
        return copy.deepcopy(val)


from test import test_data
test_data = WrapperData(test_data)
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
0

I think you mean that dictionaries are mutable, and you want to change the dictionaries in the test case without modifying the original dictionary.

You can indeed use deepcopy, which is not a bad practice at all. You can also change the test_data module to provide the dictionaries as class properties: this will return a new dictionary every time, with the original content:

test_data.py:

class test_data:

    @property
    @staticmethod
    def expected_response_1:
        return dict(status=False)

test_case.py:

from test.test_data import test_data

data = test_data.expected_response_1
data['status'] = True

print(data)
# --> {'status': True}

print(test_data.expected_response_1)
# --> {'status': False}
Manu Valdés
  • 2,343
  • 1
  • 19
  • 28
  • Yes, I do mean mutable lol. I was hoping not use classes because there are alot of very nested dictionaries, and it doesn't look lime an improvement to just using deepcopy – Tobey Dec 13 '18 at 12:22