GHPython Default Type Hint

That’s a really good idea.

And I can certainly understand not wanting to break things or cause confusion. That said, I also don’t believe adding functionality (or even fiddling with an xml) for setting the default type hint locally on one’s system would do that.

Again, I’m not asking that you change the default type hint for everyone. I’m just asking for the option to set it locally to my personal preference. Everybody wins :raised_hands:

This was earlier translated to a too drastic move: https://mcneel.myjetbrains.com/youtrack/issue/RH-46635

I think you lost me. I agree that changing the default type hint is too drastic. But surely adding functionality that enables one to change it on a per user basis to ones preference isn’t?

1 Like

Any option added has an implicit high cost of testing and maintaining it with any other option. (What happens if the name of hints changes, if we need to move hints, how do we keep track of the hints that you have to set in the option editor and what is the 1-to-1 reference with the list, for example if you write giuds, what will the editor do… etc etc). All this costs really a lot of time.

I think this particular one will be best solved with the copying strategy for now. With that change, we will see if it is enough or it will need more tweaks.

I can appreciate that. But I guess I just don’t see how adding an option to set a default type hint locally by user preference would have such severe implications/high cost.

That sounds good. I’ll take it :beers:

On a side note (might help others), I added this function to my GHPython development utility functions module. Which I sometimes use to turn type hints off locally within one component, especially if I’m adding multiple inputs straight off the bat:

import GhPython

def setNoTypeHint(ghenv):
    
    """ Set all input parameters to No Type Hint, might throw expired during solution when first ran """
    
    for v in ghenv.Component.Params.Input:
        v.TypeHint = GhPython.Component.NoChangeHint()
    ghenv.Component.ExpireSolution(False)
1 Like

Hi @AndersDeleuran,

As a newcomer to Python scripting in Grasshopper, may I ask you for an example of what you put in your scripts to replace the functionality provided by the type hinting? So far I’m using the hinting but would prefer not to…

Thanks
Jeremy

Most objects will pass along as exactly what they are (use type() inside the script to check). But some might surprise you (for instance an integer will pass as a float, and a polyline will pass as a polylinecurve etc). In such cases I simply cast them to whatever the code expects (typically in the outer scope of the code) when they are first called. For primitive data types you can use for instance int(nameOfVariable) to cast to an integer. For RhinoCommon types you’ll need to use whatever the relevant case is, for instance somePolylineCurve.TryGetPolyline().

To document this I’ve iteratively developed this structure over the years, which makes explicit within the code what input parameters are expected, their Access type, and the object type:

I automate the generation of these docstrings using this function:

import Rhino as rc
from datetime import date

def buildDocString(ghenv):
    
    """ Builds a documentation string by iterating the component
    (i.e. ghenv.Component) input and outputs parameters """
    
    ds = "Write main component documentation here.\n"
    ds += "    Inputs:\n"
    for v in ghenv.Component.Params.Input:
        ds += "        " + v.Name + ": {" + str(v.Access).lower() + "," + str(v.TypeHint.TypeName).lower() + "}\n"
    ds += "    Outputs:\n"
    for v in ghenv.Component.Params.Output:
        ds += "        " + v.Name + ": \n"
    ds += "    Remarks:\n"
    ds += "        Author: Anders Holden Deleuran (BIG IDEAS)\n"
    ds += "        Project:\n"
    ds += "        License:\n"
    ds += "        Rhino: " + str(rc.RhinoApp.Version) + "\n"
    ds += "        Version: " + str(date.today()).replace("-","")[2:] + "\n"
    
    print ds
    return ds

Note that it currently doesn’t fill out the object type (but it should, and probably will at some point). Edit: oh wait, I actually did add this. But using the type hint to document the type. So without type hint, this will simply be set to system.object.

4 Likes

Hi Anders,

Thanks for the generous, speedy and helpful reply.

Jeremy

1 Like

This is actually not correct. Only floats-that-look-like-integers will pass as floats, which is what they are. Just like strings-that-look-like-numbers will pass as str. Except if you set a specific Hint.

This is also not entirely true.

image
Grasshopper generally returns Polylines as curves, and therefore PolylineCurves, but strictly speaking it would not be obliged to. It’s a decision by David to make geometry always derive from GeometryBase for particular needs.

It’s just much easier to use TypeHint => Polyline, and all the Grasshopper-specific conversions that are required to work to make your script fully compatible with Grasshopper will be given to you, free of charge. It’s actually not sufficient to call PolylineCurve.TryGetPolyline() to fully support all polyline conversions.

Somebody might come up with some geometry type that has no Rhino.Geometry.Curve representation, but that might have a good polyline counterpart. For example, some type of Graph. In that case, their underlying type might not have a TryGetPolyline() method, but would still be convertible if you just used the correct Hint.

This being said, I think this conversation has already lasted overly long. Many more times than you think, scripts with No type Hint are not fully compatible with Grasshopper and become somehow impaired versions of normal components. For example, try inputting a Polyline where a No type Hint script expects a float. Does it work, by computing the curve length? If not, the No type Hint strategy will make your script not on-par with the general Grasshopper standard and, if the script is not only meant for you, it will make it just less robust.

You mention you are a newcomer to Python scripting in Grasshopper. As explained above, this is only sometimes a great decision. Please analyze case-by-case if this strategy is best suiting all your needs, including especially compatibility with the generous Grasshopper automatic conversion system.

Sorry, I should have said some integers (like the ones from an integer slider), and some polylines (like the ones from the PolyLine component).

Right, this whole what-type-is-thing-when/type conversion hoopla I personally find frustrating and needlessly complex. What does “look-like” even mean? It doesn’t seem very explicit nor beginner-friendly IMO. I prefer to simply pass things, check their type() and act accordingly. That might not make for the most robust/generic Grasshopper components (but hey, at least they’ll be very explicitly documented in terms of what inputs expect to be passed), but that’s not my intention. It’s to solve design problems as fast and agile as I can. If my intention was to write “real” components I’d be in Visual Studio, following the standards devised by David.

My point is that these pipelines ARE precisely meant for me and my organisation. And as such follows the development standards I’ve been using over the years. Which would benefit from not using type hints. As a customer and longtime user I’m honestly a bit bummed that this doesn’t appear to carry much weight. It’s starting to feel like there’s only one sanctioned McNeel way of using GHPython (i.e. using rhinoscriptsyntax with type hints). Which is a real shame, considering precisely how flexible and agile it in fact is. like, I freaking love the thing right!

4 Likes

They are not integers… This is exactly why Hints exist. Maybe you just do not like the name. In fact, it should rather be “Automatic conversion to”, probably.

I hear you, but welcome to computing.

We try to accommodate new users of GhPython who come from Rhino, and those who never scripted, and also long-standing users. Not always the three groups have a lot in common. At best, all of them would feel at ease writing great scripts with minimal effort.

Exactly, an admirable goal to which adding the option to set default type hint would help greatly :raising_hand_man:

If I may weigh in, as I kinda fit in all groups of users.

What about leave the hints as they are, making a checkbox somewhere to keep the set hint as default and put it somewhere inside guid-named xml file in an undisclosed location? Reading the setting upon launch of Grasshopper, to reduce slowdown in performance. Respectively if you set a new default hint a Rhino restart to be required.

As for the part of me that is still quite noobish in programming. How difficult would it be, or how much slowdown in performance could be expected, if you using reflection and (for the most inexperienced) set the type depending on whatever comes in with the wire? Another check box somewhere in the menu, a “Noob mode” if you will?

1 Like

We will probably go with something in this direction after all. A per-component default Hint, that can be saved and loaded. This way, I think we will cover more ground with less confusion.

This might not be necessary, we will see.

This has a lot of “what ifs” associated with it. What if some numbers are ints, some are floats? What if some text looks like number (but is still text)? This might be a playground for some users who want to write some special-purpose plug-in, but generally I think that the user can just demonstrate design intention and pick the right Hint. It’s not that bad.

2 Likes

I doubt noobs will try to implement “special” stuff. :slight_smile:
As for the “what ifs”. To me an integer is an integer if you pass 1 from a panel then it’s “1” and it should be considered as a string.

image
image
image


That’s mathematically an integer but type-wise it’s a float. For Grasshopper. “Rounding” affects the rounding, not the type. I am not sure why it was chosen this way, but such is @DavidRutten’s design.

Yes, but not everyone would agree I think. Especially the “noob” you wish to help. If you pick the right Hint, it will be just converted to the right type and passed to you in the right form. For the computation-time savvy guys: this costs in terms of computation if the conversion happens, if it doesn’t need to happen, then it’s just a quick type check.

That would disregard a widely used precedent, since panel values are treated as numbers when used as inputs to most standard components.

We’re talking about GhPython only @Joseph_Oster.

I’m not, and I’ve followed this thread from the beginning, thank you very much.

The thing is “noobs” rarely change the Type Hint of GhPython, if it has to be adjusted for them without thinking about it they hook up a wire to GhPython and don’t ever consider changing the type hint. Then there has to be some rules these users must follow.

“1” is a string - is one of those supposed rules.

Also there are, even now, issues that arise from using numbers passed directly from panel. This is something that is mentioned in many tutorials and courses. One should use number slider, digital scroller, etc. or must pass the wire through one of these:

image

If the proposed “noob mode” is unchecked pass whatever you like and be sure to set the proper Type Hint.