Rhino 8 Python Grasshopper Component.Code Property

It seems like we are unable to access the code inside of a component using the new python components:
RhinoCodePluginGH.Components.Python3Component
RhinoCodePluginGH.Components.IronPython2Component
Whereas it was previously a property in the old Python component:
GhPython.Component.ZuiPythonComponent

Is there another way to currently to access the component code? It would be awesome to have the Code property again :slight_smile:

3 Likes

It would indeed. I’m not going to drop the old GHPython components (to retain backward compatibility with Rhino 7) but the Code property is really useful to script and even automate plug-in build processes.

1 Like

I second this. It would be very helpful to have a way to programmatically update the code content of a Python 3 Script component, as was possible with the old GhPython component.

This is not equivalent to using the built-in script input, as the latter involves manually clicking on the component to make the input appear, etc.

@eirannejad any chance this could be added to the new script editor?

1 Like

I can help better if you can give me a little more context in why you are extracting the scripts. There is an API for this but it is unpublished and subject to change currently.

However, if you like to use the script somewhere else in Grasshopper you can activate the script output parameter and pass it to a Text param. This makes it easy to create and edit One script that is using many times across the grasshopper definition

Thanks @eirannejad for explaining that technique.

I think the most common use of the Code property would be in managing the build process of ghuser objects. In my scenario I’m simply trying to upgrade a lot of existing of old .ghuser legacy ghpython components. They all live in one .gh file and i’m trying to build a component to read the canvas and upgrade all of these and write new IronPython or Python3 ghuser objects.

Developer tools like the GHComponentizer are great when you have the source code component params already configured in files. But when working with existing .gh definitions that need to be upgraded the Code property becomes really useful.

I’ve seen other posts like this one from @AndersDeleuran which seem to have similar workflows that require the use of the Code property:

Thanks!

1 Like

@bfrederick You can use the unpublic API but subject to change :smiley: .Text and .LanguageSpec properties are important. I wrote a snippet in the older GHPython so it can read all the new scripting components. These properties are readonly so I have also added a YT ticket below to create an API to create a new scripting component from a script

RH-81754 Allow creating script components from code

ExtractScripts.gh (10.9 KB)

1 Like

This is great, thank you for offering a temporary solution. :clap:

Cheers.

1 Like

@eirannejad maybe I spoke too soon. Is it possible to get the .Text property of a legacy component? The components I’m trying to upgrade are legacy ghypython components. I assume these don’t have the LanguageSpec attribute? But maybe there’s another way to retrieve the code from these legacy components?

Sure. Here is an example. .Code and .ScriptSource work on legacy IronPython and C# components:

ExtractScripts.gh (11.7 KB)

1 Like

Awesome! Many thanks :pray:

Hi @eirannejad, thanks for the workaround using the Text attribute. However, as you point out, it is read-only, so it doesn’t work as a full replacement of the Code attribute of the old Gh Python script component.

Thanks also for creating an issue to plan for an API to create components from code. It may be useful, but I think having a writable attribute to programmatically modify the code of an existing script component (like with the Code attribute), rather than create a new component, would be needed as well.

Indeed, the Code property is not only helpful to automate the build process of components (as in @bfrederick 's use case) but also to allow editing script components in place with an external editor.

For instance, for ergonomics, I like to edit my code in Vim. I have made myself a little group of components (let’s call it a “snippet”) that I can insert in a definition to edit scripts in place. It works this way :

  • Provide the GUID of the script component to edit (I use Human for this)
  • Dump the code of the script component to a temporary text file (created by my “snippet”)
  • Edit the temporary text file in Vim (or for that matter any external editor)
  • Changes to this temporary text file are automatically detected by the “snippet”, and update the script component’s code immediately. So I can edit in vim and see changes in GH instantly.

What is nice about this workflow is that there is no need to modify the wiring of the existing definition (no need to add a ‘script’ input to the script component I want to edit). When I’m done editing, I simply delete my “snippet”'s components. This was inspired by the ScriptParasite plugin (https://www.food4rhino.com/en/app/scriptparasite-grasshopper), which I think used Code as well.

@eirannejad
get_python_nodes_content.gh (14.9 KB)
thanks for sharing these examples. Any expected plans to make this work for python3 and not just IronPython 2?

how to enable this feature? If i right click on the P3 component I don’t see this option (v8.8.)

Shift + Right Click

@Chris37

https://developer.rhino3d.com/guides/scripting/scripting-gh-csharp/#output-script

@crz_06

Change the Python 3 scripts to this for a workaround. I have made a ticket to look into this. Keep in mind this is undocumented API and might change:

RH-82357 Pythonnet does not return correct result on hasattr on interface objects

from RhinoCodePlatform.Rhino3D.GH import IScriptObject

doc = ghenv.Component.OnPingDocument()

scripts = []
languages = []
versions = []

for o in doc.Objects:
    if isinstance(o, IScriptObject):
        so = IScriptObject(o)
        spec = so.LanguageSpec
        scripts.append(so.Text)
        languages.append(spec.Taxon.Family)
        versions.append(spec.Version.Major)

script = scripts
language = languages
languageVersion = versions