[Accelerated Tables] get method on deleted rows doesn't error if a column doesn't exist

What I’m trying to do:
I’m trying to check if a row is deleted by using the get method on a row to check for a nonsense column and see if it errors.

If the column exists in the table, the row gives the anvil.tables.RowDeleted Error.

However, if a column doesn’t exist on a row that’s been deleted, using the get method doesn’t error out

Clone link:
share a copy of your app

Looking at the anvil-runtime source code, it looks like RowDeleted is being checked and raised before the column being missing can trigger a KeyError which gets returned/wrapped in a NoSuchColumnError.

The suboptimal workaround is to call the column as a key instead of using the .get() method, so in your clone:

  try:
    deleted_row.get("nonsense_column")  # <-----
    return_values["nonsense_column"] = "no error from get method for nonsense column"
  except RowDeleted:
    return_values["nonsense_column"] = (
      "Row deleted error from get method for nonsense column"
    )

does not work, but

  try:
    deleted_row["nonsense_column"] # <-----
    return_values["nonsense_column"] = "no error from get method for nonsense column"
  except RowDeleted:
    return_values["nonsense_column"] = (
      "Row deleted error from get method for nonsense column"
    )

does work and creates the desired outcome.

This is most likely because the __getitem__ and get methods are implemented differently. It looks like an artifact of moving to V2 tables (accelerated tables).

Yeah, I considered that, but the problem is, that that then ends up with existing rows raising the NoColumn exception. I could wrap this in another try-except, but that seems excessive. At the moment this isn’t super pressing since all the relevant tables have a “name” column, so I’ll just use the bracket notation with that column.

I do think this is a bug though, the point of get is to avoid NoColumn errors, not avoid RowDeleted Errors – if I’m wrong and it is meant to avoid these errors too, I’d really prefer a method or attribute to check if a row exists rather than try-except blocks that I can’t make fully generic for all tables.

See table function has_row() in Anvil Docs | anvil.tables

That would work on the server, but the code I’m working with is on the client side :frowning:

Client side code can’t call table.has_row(row)?

Only if it’s client readable though?
Let me go verify…

Huh, it doesn’t give an access error, go figure. :slight_smile:

In fairness, I haven’t looked at your code, but I figured this ought to be simpler than any exception-related logic I could come up with.

1 Like

Yeah, your spot on there. I’ll implement that tomorrow as it is much too late for me to bother right now at 11 PM in China, haha.

@p.colbert 's solution is probably better for your use case but you can just add another exception type to cascade in newer python:

  try:
    deleted_row["nonsense_column"] # <-----
    return_values["nonsense_column"] = "no error from get method for nonsense column"
  except RowDeleted:
    return_values["nonsense_column"] = (
      "Row deleted error from get method for nonsense column"
    )
  except NoSuchColumnError:
    pass

The question is, since you are using the client side, whether this style of exception handling is implemented in skulpt, I think its from python 3.8 or 3.9

1 Like