Suspension error on print (or how to preload simple object columns?)

This is either a bug report, or me doing something weird. I’m doing a print statement and getting a suspension error. The suspension error is because I’ve got a simple object column access hidden inside of a __getitem__ call.

The weird bit is that I can print out the value of the simple object column directly, which should do a server round trip if needed to fetch the value. After that, I would expect the round trip to not be needed, but it seems to be trying anyway.

So I don’t know if this is a bug report about the suspension error in the first place, or about the fact that the simple object column seems to be trying to do a round trip for each access. Probably both?

Here’s the code that prints (the first line works, the second does not):

    print(self.it.row['data'])
    print(self.it)

And here’s the class (self.it is an instance of this class, attached to a database row):

@anvil.server.portable_class
class TestClass():
  def __init__(self, row):
    self.row = row
    self.attributes = ['description']
    
  def __getitem__(self, key):
    if key not in self.attributes:
      raise AttributeError(f"{key} not found")
      
    return self.row['data'][key]
  
  def __str__(self):
    result = '{'
    
    for attribute in self.attributes:
      value = self.__getitem__(attribute)
      result += f"{attribute}: {value}, "
      
    result = result[:-2]
    result += '}'
    return result

And the clone link with it all put together: Anvil | Login

I haven’t cloned or tried, but your question reminds me of this: SuspensionError calling datetime.strptime in an iterator - #6 by stefano.menci

Sorry, I don’t have time right now, maybe later, I thought I would mention that, just in case we are lucky and it helps.

I’m totally fine if the suspension error is correct, and I need to preload the simple object column, but that also doesn’t seem to be working.

After @stefano.menci post we wrote something about blocking code and listed the dunders that could and couldn’t suspend

Common dunders that do not support blocking code:

  • __iter__
  • __repr__
  • __str__
  • __bool__
  • Number dunders like __add__, __mul__
  • Comparison dunders like __eq__, __gt__

Common dunders that do support blocking code:

  • __getattr__, __setattr__
  • __getitem__, __setitem__
  • __next__
  • __dir__
  • __init__, __new__
  • __len__
  • __contains__

As to how to preload the simple object - it doesn’t look like that’s getting cached on the client.
We’ll look into that.

I’d suggest converting your __str__ method into a to_json method or something.
Then print(self.to_json())

sidenote: we’ll format the docs so that the bullet points appear correctly!

3 Likes

That’d be appreciated, I’m definitely seeing a round trip for every access to the simple object column, not just the first.

Edit: Interestingly, in the larger app where I encountered this, there’s a flow that does seem to cache the simple object column in the client (at least, the call to __str__ works). The simple example didn’t recreate that, but if it’d be helpful to see it I can work more on recreating that flow.

Double edit: nope, that other flow was actually a bug on my end, not the simple object column being cached.

1 Like