Output of Fx not correct - Rhino bug or script bug?

One of the options in the attached Python script is to output a column showing ‘Other Attributes’, which my script gets from Attribute User Text. This works great, unless the Value is a function, in which case it doesn’t work at all.

Here are steps to repeat the issue:
Make an sphere.
Select sphere and go to the Attribute User Text panel.
Click on Fx.
Pick something, like ModelUnits.
Run my script.
From the command line, select Columns.
Change OtherAttributes to Yes.
Click enter, and finish the script.
The output should go to the history window, but the ModelUnits will be incorrect.

In contrast, if you manually enter a value in AttributeUserText, it will show up on the BOM correctly.

BOM.py (19.6 KB)

To clarify:
When I use a script to get Attribute User Text, the value returned in the script is sometimes a formula, not the result of the formula. So, instead of getting ‘Inches’ for ModelUnits, the script returns ‘%<ModelUnits()>%’.

Here’s a Rhinoscript example: if I create a sphere, open Attribute User Text panel, and click on Fx and pick ModelUnits, then run the following, the output is ‘%<ModelUnits()>%’ instead of what I see in the Attribute User Text panel, which is ‘Inches’. Is there a way to return ‘Inches’ instead? ModelUnits isn’t the best example b/c I can get that other ways, but…I just want to be able to retrieve the values of UserText.

Dim strObject

strObject = Rhino.GetObject("Select object")

If VarType(strObject) = vbString Then

	Rhino.Print Rhino.GetUserText(strObject, "ModelUnits")

End If

Hi Peter - I don’t yet see how to get the evaluated formula…
@phcreates - the bigger brain (Dale Fugier) pointed out Rhino.RhinoApp.ParseTextField():

For a curve with CurveLength applied:

filter = Rhino.DocObjects.ObjectType.Curve
rc, objref = Rhino.Input.RhinoGet.GetOneObject("Select curve", False, filter)
if rc == Rhino.Commands.Result.Success:
    obj = objref.Object()
    if obj:
        formula = obj.Attributes.GetUserString("CurveLength")
        print(formula)
        value = Rhino.RhinoApp.ParseTextField(formula, obj, None)
        print("{0}".format(value))

-Pascal

Tried Dale Fugier’s but got result of None. Did I miss something?

@dale - I’m still not getting this to output the result of the fx. Any suggestions?

Hi @phcreates,

Seems to work here. So does this:

import Rhino
import System

def _IsFormula(str):
    if str and str.startswith("%<") and str.endswith(">%"):
        return True
    return False
    
def TestPrintFormula():
    filter = Rhino.DocObjects.ObjectType.Curve
    rc, objref = Rhino.Input.RhinoGet.GetOneObject("Select curve", False, filter)
    if rc != Rhino.Commands.Result.Success:
        return
        
    obj = objref.Object()
    if not obj:
        return
        
    coll = obj.Attributes.GetUserStrings()
    print("KEY, VALUE")
    for i in range(coll.Count):
        if obj:
            key = coll.GetKey(i)
            value = coll.Get(i)
            if _IsFormula(value):
                value = Rhino.RhinoApp.ParseTextField(value, obj, None)
                if not value:
                    value = "####"
            print("{0}, {1}".format(key, value))

if __name__ == "__main__":
    TestPrintFormula()

– Dale

Hi @dale neither of those scripts work here. As you can see in the command line and in debug window, the results are nothing. What am I missing?

@dale - any help would be appreciated.

Hi @phcreates,

Running the above script on the attached file produces this in V7:

image

TestPrintFormula.py (911 Bytes)
Circle.3dm (29.3 KB)

If you are getting something else, you might want to post your 3dm file or script (or both).

– dale

Hi @dale,

apologize but i do not see this (and all other above examples) working here too. It seems the only thing your script prints is:

KEY, VALUE

After trying to debug this i’ve found that anything after calling the ParseTextField method seems to fail to print. Eg. if i run this code:

if _IsFormula(value):
    print "IsFormula returned True"
    value = Rhino.RhinoApp.ParseTextField(value, obj, None)
    if not value: value = "####"
    print "Hello ?"
    print("{0}, {1}".format(key, value))

the script prints this:

KEY, VALUE
IsFormula returned True

I do get the same either using V7 or V8 most recent versions. Rhino running in english language on a Win10 running in german.

_
c.

Hi @clement,

Replace print with Rhino.RhinoApp.WriteLine.

Work any better?

– Dale

Hi @dale, sorry no. Same result as written above.

_
c.

@clement - can I assume your V7 is up-to-date SR wise? If you trace through the code, do you see valid key and value strings?

Hi @dale, my V7 was updated yesterday it is (7.33.23213.13001, 2023-08-01)

If i remove ParseTextField from your code, keys and values are printed:

KEY, VALUE
ObjectName, %<ObjectName(“9e77ea9c-548d-435b-a8a2-5b0c271a547e”)>%
ObjectLayer, %<ObjectLayer(“9e77ea9c-548d-435b-a8a2-5b0c271a547e”)>%
CurveLength, %<CurveLength(“9e77ea9c-548d-435b-a8a2-5b0c271a547e”)>%
Area, %<Area(“9e77ea9c-548d-435b-a8a2-5b0c271a547e”)>%

_
c.

Hi @clement,

I am not able to repeat this running German Rhino on English Windows.

ParseTextField does use Python to evaluate the text field.

I’ve logged the issue.

https://mcneel.myjetbrains.com/youtrack/issue/RH-76271

– Dale

Hi Dale,

I’m running English Rhino with English Windows.

Here is a specific script (exactly what Pascal posted). Result is a ‘return’ on the command line (no text, just a blank line). It sounds like Pascal is getting the same result that I am. I’ll attach the Rhino file. I don’t think this is the same bug that Clement is seeing (if I put a print command after the ParseTextField line, it does print.) I’ve tried your exact script too, and the result on the command line is “Select curve” then “KEY, VALUE”, then “0”

import Rhino

def main():
filter = Rhino.DocObjects.ObjectType.Curve
rc, objref = Rhino.Input.RhinoGet.GetOneObject(“Select curve”, False, filter)
if rc == Rhino.Commands.Result.Success:
obj = objref.Object()
if obj:
formula = obj.Attributes.GetUserString(“CurveLength”)
print(formula)
value = Rhino.RhinoApp.ParseTextField(formula, obj, None)
print(“{0}”.format(value))

if( name == “main” ):
#call function defined above
main()

curve.3dm (146.4 KB)

Hi @phcreates,

The curve in your file doesn’t contain any attribute user text.

– Dale

Oh, crap - my mistake. ParseTextField does do what I need. Thank you.