How to import package nodes into a python script

Hi,
I’m trying to use in a python script the nodes of a package I loaded, but it seems like the package functions doesn’t exist. The name of the package is JsonData and I am trying to use the node “GetValueByKey”. The following message is showed: NameError: name ‘JsonObject’ is not defined.
Is there a way to use this package in my python script?

Why not use the custom node outside the Python and feed it in as an input?

@Marco_Brasiel

In theory you need to add the path to the dll and then load the assembly as shown below

import clr
import sys
pyt_path = r'C:\Users\USER\AppData\Roaming\Dynamo\Dynamo Revit\1.3\packages\JsonData\bin'
sys.path.append(pyt_path)

clr.AddReference('JsonData')
import JsonData

OUT = JsonData 

I haven’t figured out how to actually use the methods though

image

<member name="M:JsonElements.JsonObject.ValueByKey(System.Object)">
    <summary>
    Returns the value associated with the given key from the jsonObject.
    </summary>
    <param name="key">Attribute's key</param>
    <returns name="value">Value returned</returns>
    <search>
    json, jsonobject, search, bykey
    </search> 
</member>

Thanks.
@jacob.small, I am not using nodes outside because I need to solve an imperative block. In addiction, I can’t create a design script node because I need to use the “All Elements of Category” node, which is not available to design script.
@salvatoredragotta, Your solution seems to be what I was looking for, but now I am receiving the following error: “AttributeError: attribute ‘GetValueByKey’ of ‘namespace#’ object is read-only”. Any suggestion?

Sure it is:

ElementQueries.OfCategory(category);

A perhaps more useful nested example which gets all Views in the Revit model:
ElementQueries.OfCategory(Category.ByName("Views"));

Basically ANY zero touch node can be called via design script once loaded by Dynamo. They don’t all have smartsense, autofill, or other benefits. You may have to do some guessing. Some require additional tinkering use them well. And others have components which would make it so you really wouldn’t want to use them (ie: dropdown nodes), but that doesn’t mean you can not do it.

This topic has some goodies from @Vikram_Subbaiah, @Kulkul and @Dimitar_Venkov down at the end.

2 Likes

There’s three types of nodes in Dynamo:

  • Custom Nodes, saved by the user as *.dyf files. They can be a collection of any other nodes
  • ZeroTouch nodes, written in c# and imported as shared libraries, which just expose the public methods of those libraries as nodes.
  • NodeModel nodes, written in c# and XAML, which provide a custom user interface that can call other c# methods from other shared libraries.

You can’t use custom nodes (*.dyf files) directly in python unfortunately, because their execution process is very complicated. They have to be converted to DesignScript calls, after which a DS AST has to be generated, after which that AST has to be traversed and processed by the DS VM, which finally associatively has to replicate the input data and automatically pass it to the underlying C# methods as arguments. I’m sure someone on the core dev team can probably give a more correct and detailed description of the above process, but as you can see, there’s a lot of steps that need to happen in the correct order and as of now there just doesn’t seem to be an easy way to expose that.

ZeroTouch nodes are relatively straight forward - you have to find their namespace, import that namespace in your python code and then call the method you’re interested in. One gotcha, is that when you import a c# shared library, it’s possible to override a method’s name through custom attributes.

NodeModel nodes are the hardest, you first have to find the underlying ZT method(s) they’re using and then call them using the steps for ZT above. This is what Jacob was showing you above - when the All Elements of Category node gets executed, it simply passes the selected category to the ElementQueries.OfCategory c# method.

For all built in nodes, you can always check the Dynamo and DynamoRevit repositories on GitHub. If you don’t have the source code of the ZT and NodeModel nodes, it can be quite tricky finding out their namespaces and underlying method names…

From the description above, you can deduct that DesignScript is a Very-High-Level programming language (it does a lot of the cognitive work automatically for you, through abstraction and wrappers), where as Python is generally considered as a High-Level programming language. Since you’ve already gone a step down and are using python, it might be worth it for you to learn the native Revit API calls and directly create a FilteredElementCollector. That way you can skip all of the abstractions associated with Dynamo nodes.

5 Likes

It works perfectly!

@Dimitar_Venkov, your explanations are very useful. Thank you so much.

I should have take a look there before, but I was sure of that node was unavailable for DS (fortunately I was wrong).

It was my intention to use them.

Thanks!