Best-practice how to use UserWarnings?

I’d like to learn for to use UserWarning properly. Implementations in official modules - which I took as an example - use quite different approaches, the documentation shows yet another approach.

My questions are:

  • It is required or recommended to define a custom sub-class of UserWarning?

  • How to form the warning_name (aka key)? Which values should go into the key? Quite different forms used in the code:

    key = Warning.format('post no shipment', [shipment_cost])
    key = '%s post no move' % landed_cost
    key = 'party.replace name %s %s' % (source.id, destination.id)
    key = 'check_request_warehouse_%s_%s_%s' % (
                      self.id, self.warehouse.id, request.warehouse.id)
    key = str(payment)   # account_payment/payment.py
    key = Warning.format('%s:%s' % (reverse[kind], party), lines)  # account_payment/account.py

Yes, so you will be able to catch such specific warning from the calling code

The key is used to identify the warning. It depends a little bit on the kind of warning and if it’s releated to some records but it should be used to identify the warning from the user prespective.

For example, if the warning is related to some wrong data on some records the key should be unique per set of records. This way the warning is raised for each records that do not satifsty the condition.

On the other hand, if the warning is generic, you can include just a name to it’s key.

The main idea here is that each unique key can be skipped by the user in case the warning is reraised.

Hello,

The thing to be wary about for the key is that the transaction which initiated the warning will be rollbacked, and re-executed “from scratch” if the user clicks “Yes”.

So any id that was allocated will be lost, and new ids will be used.

Bottom line is, if you use an id in your warning key, make sure it refers a record that existed before the current transaction, or else you will be stuck in a loop.

1 Like

Thanks so far.

So the key would be e.g.

key = Warning.format('mymodule.check_conflict',
          [record, conflicting_data_1, conflicting_data_2])

or:

key = 'mymodule.check_conflict,%s,%s,%s' % (
          (record, conflicting_data_1, conflicting_data_2)

Right? Which one is to prefer?

For my use-case I decided to use a readable key, so in the future the database could be cleaned up if the warnings are not longer relevant (e.g. since the record is “closed”, “stopped”, “paid”)

key = 'mymodule.check_conflict,%s,%s,%s' % (
          (record, conflicting_data_1, conflicting_data_2)

The warning records are automatically deleted after usage so there is no point to clean them.
But using Warning.format ensure a standardization and a reproducibility of warning names across systems.

Thanks. I didn’t know (obviously ;-). This is good news.