0

I have a very simple class that defines properties like:

class Person:
    fields = set()

    @property
    def id(self):
        self.fields.add('id')
        return 'person.id'

The idea is for this class to record which properties have been accessed. Now the problem comes when I need to start supporting: person.metadata.key where metadata is basically an HStore object or 1 level JSON, the key is arbitrary and the idea is for the class Person so record access to any of the keys in metadata. I tried something like this:

class CustomerBulkContext:

    fields = set()

    class PersonMetadata:
        def __getitem__(self, attr):
            fields.add(f'metadata.{attr}')
            return f'person.metadata.{attr}'

    metadata = CustomerMetadataContext()

Now obviously the problem is that fields inside PersonMetadata is not a known variable at this point. How can I overcome this issue, I don't know if it's possible to do in Python without too much code.

PepperoniPizza
  • 8,842
  • 9
  • 58
  • 100
  • Might be looking for this? https://stackoverflow.com/a/16279578/9848926 – Dillon Miller May 29 '20 at 00:05
  • 1
    There is no clean way to do this. You'd have to have the object returned by `.metadata` communicate that – juanpa.arrivillaga May 29 '20 at 00:15
  • 1
    @juanpa.arrivillaga is right. To expand on his answer, you will need to count data access in the class that actually contains the data being accessed. This is because the `get` dunder methods (`__getattribute__`, `__getitem__`, etc.) only receive a ref of the item inside themselves. i.e. `object.object1.object2` will have `object` receiving `object1`, and `object1` receiving `object2`. In other words, `object` never sees `object2` access. Unless you want to do some funky run-time code inspection, or larger wrapper class, which both are more messy, this implementation won't be "super" clean. – felipe May 29 '20 at 00:22
  • 2
    dont you think use of `logger` would be better option ? – sahasrara62 May 29 '20 at 00:23
  • What do you mean by "behave as dictionary" in the title of this question, btw? – juanpa.arrivillaga May 29 '20 at 00:25

1 Answers1

0

In order to track accesses like person.metadata.key you'd have to have person.metadata return an object which itself tracks how it was accessed. In order to track the whole chain, you'd pass the chain so far to the object.

Something like:

class AccessTracker:
    def __init__(self, path=()):
        self._path = path

    def __getattr__(self, name):
        print('Accessed %s in %s' % (name, self._path))
        return AccessTracker(self._path + (name,))
Jiří Baum
  • 6,697
  • 2
  • 17
  • 17