1

I have a class definition like

from tinydb import TinyDB

class DB(TinyDB):
    def __init__(self, filename):
        return super(DB, self).__init__(filename)

    def exists(self, url):
        return bool(self.search(Entry.url == url))

    def insert(self, *args, **kwargs):
        if len(self) > 100:
            self.purge_tables()

        return super(DB, self).insert(*args, **kwargs)

where TinyDB is from the tinydb package.

When I now try to run

database = db.DB('test.json')
database.insert({'title': 'Hello', 'url': 'foo'})

I get an error message

return super(DB, self).insert(*args, **kwargs)
AttributeError: 'super' object has no attribute 'insert'

Whereas when I do

from tinydb import TinyDB

database2 = TinyDB('test.json')
database2.insert({'title': 'Hello', 'url': 'foo'})

insert() is there, provided by

def __getattr__(self, name):
    """
    Forward all unknown attribute calls to the underlying standard table.
    """
    return getattr(self._table, name)

There seem to be some intricacies with this way of making attributes from one attribute within your class accessible to the outside.

Nils Werner
  • 34,832
  • 7
  • 76
  • 98

1 Answers1

1

Your last example works because of the __getattr__ method defined on TinyDB:

class TinyDB(object):
    # [....]
    def __getattr__(self, name):
        """
        Forward all unknown attribute calls to the underlying standard table.
        """
        return getattr(self._table, name)

and indeed, the insert method is defined on Table. You can fix your example by using:

def insert(self, *args, **kwargs):
    if len(self) > 100:
        self.purge_tables()

    return self._table.insert(*args, **kwargs)

this answer has more explanation on why it does not work like you expect.

Community
  • 1
  • 1
Jieter
  • 4,101
  • 1
  • 19
  • 31