No announcement yet.

The truth about truth values

  • Filter
  • Time
  • Show
Clear All
new posts

  • The truth about truth values

    Hopefully this tale will save somebody else some time...

    A previous version of a script I now maintain had a really dumb bug in it: saveNvParam() was being called with only one parameter. I wouldn't expect that to do anything consistent, but in fact the results were entirely repeatable: the new route timeout (a parameter the script wasn't even trying to set) was always set to 1, as shown in Portal's node configuration dialog. That certainly didn't help mesh routing... I fixed the bug as soon as I found it, and put some code in the startup function to fix the corrupted NV parameter, along the lines of:
    if loadNvParam(NV_MESH_ROUTE_NEW_TIMEOUT_ID) != 5000:
        saveNvParam(NV_MESH_ROUTE_NEW_TIMEOUT_ID, 5000)
        rebootNeeded = True
    I then forgot all about it, assuming that everything was taken care of.

    A few months later I discover that the bad parameter was still bad, no matter how many times the units had been restarted. Changing the parameter in Portal caused the correct value to be set on the next restart, no matter what I changed it to, but the bad value of 1 was somehow not triggering my fix code. There's no telling how many hours I wasted staring at those few lines of code, trying to figure out how 1 could equal 5000 (the only possible condition that could prevent the fix from executing).

    Well, it turns out that in SNAPpy, 1 can equal 5000... if the 1 isn't an integer, but is actually the boolean value True. Portal apparently coerces this NV parameter to an int before displaying it; I had to manually do a loadNvParam() to see the actual value. SNAPpy equality comparisons involving booleans are bizarre: True appears to be equal to ANYTHING that isn't false in a boolean context (False, None, 0, empty string), which is not at all how real Python behaves. It is basically unsafe to compare arbitrary values in SNAPpy, if there's any possibility that one of them is a boolean.

    Changing my saveNvParam() call to be unconditionally executed fixed the problem. The internal check to avoid unnecessary NV writes, when the new value is the same as the old value, apparently uses a more reasonable definition of equality.

  • #2
    Your post inspired me to write some type checking routines which I've posted here As I have an almost identical start-up check in my scripts, but do some additional work before passing on, so I need to know in my script if the change is being performed.


    • #3
      A little background as I understand it:

      I'd suggest an improvement to Jason's statement of "1 can equal 5000" might be:
      "5000 is True"

      IE, a number other than 0 should be interpreted as "not 0" or "not False", which is therefore "True".

      Similar to C or C++, anything "not 0" that he is requesting to compare in his logic check would be returned as "True" if any number other than 0 were stored there.

      Part of the problem is that Portal is "helping out" and confusing things slightly.
      Given that you want to reset an NV Param to the Core Default, here's one line that won't work using the Node's built-in from within Portal, but will work from the command line within Portal:

      saveNvParam(n, None)
      If you click on this function in that node's builtin using Portal, and you pass "None" as the parameter, it will be stored as a string "None", rather than interpreted to mean the "null" value should be stored. (Why? because some NVParams can be strings and some must be integers. Portal doesn't try to do any intelligent filtering by NVParam number, therefore it will store the None string into an Integer type field...which could be valid for another NVParam.

      However, if you run this same function using an rpc method from the command line, it will reset the NV Param to the "Core default" as known by Snap:
      rpc('/xAB/xCD/xEF','saveNvParam', n, None)

      Why? "None" will be correctly interrupted by SNAP as literally "None", which is not allowed to be set by design. If this is attempted, SNAP will instead look up the default and load that into the "n" NV Param.

      So in summary, from the command line in Portal:
      >>> a = 5000
      >>> if a:
      >>> print "hi"
      (Result will be "True" and therefore print "hi")

      >>> b = None
      >>> if b:
      >>> print "hello"
      (Result will be "Null" or False and therefore will NOT print "hello")