diff --git a/DSPythonNet3/DSPythonNet3Evaluator.cs b/DSPythonNet3/DSPythonNet3Evaluator.cs
index b35736d..9ac2292 100644
--- a/DSPythonNet3/DSPythonNet3Evaluator.cs
+++ b/DSPythonNet3/DSPythonNet3Evaluator.cs
@@ -799,6 +799,61 @@ private static bool IsMarkedToSkipConversion(PyObject pyObj)
public override event EvaluationFinishedEventHandler EvaluationFinished;
private bool registeredUnwrapMarshaler;
+ private const string ConnectionNodeCompatSentinel = "__dspynet3_connnode_compat__";
+
+ ///
+ /// Compatibility shim for "node-first" static methods exposed by some Dynamo/Revit libraries.
+ /// In older engines these could be invoked like instance methods (e.g. node.SubNodesOfSize(2)).
+ /// Python.NET 3 binds static methods strictly, so we patch a small set of known APIs to keep
+ /// existing graphs working.
+ ///
+ private static string ConnectionNodeCompatPatchCode()
+ {
+ return $@"
+import builtins as __builtins__
+try:
+ from AdvanceSteel.ConnectionAutomation.Nodes import ConnectionNode as __ConnectionNode
+except Exception:
+ __ConnectionNode = None
+if __ConnectionNode is not None:
+ if not getattr(__builtins__, '{ConnectionNodeCompatSentinel}', False):
+ def __dspynet3__patch_connnode_instance(__obj):
+ # Attach instance-callable wrappers for node-first static methods.
+ try:
+ if not isinstance(__obj, __ConnectionNode):
+ return
+ def __subnodes(__n, *args, __obj=__obj, **kwargs):
+ return __ConnectionNode.SubNodesOfSize(__obj, __n, *args, **kwargs)
+ def __existing(*args, __obj=__obj, **kwargs):
+ return __ConnectionNode.ExistingConnections(__obj, *args, **kwargs)
+ try:
+ setattr(__obj, 'SubNodesOfSize', __subnodes)
+ except Exception:
+ pass
+ try:
+ setattr(__obj, 'ExistingConnections', __existing)
+ except Exception:
+ pass
+ except Exception:
+ pass
+ def __dspynet3__walk_and_patch(__x):
+ try:
+ if isinstance(__x, (list, tuple)):
+ for __i in __x:
+ __dspynet3__walk_and_patch(__i)
+ else:
+ __dspynet3__patch_connnode_instance(__x)
+ except Exception:
+ pass
+ setattr(__builtins__, '__dspynet3__walk_and_patch_connnode', __dspynet3__walk_and_patch)
+ setattr(__builtins__, '{ConnectionNodeCompatSentinel}', True)
+ try:
+ __inp = globals().get('IN', None)
+ __builtins__.__dspynet3__walk_and_patch_connnode(__inp)
+ except Exception:
+ pass
+";
+ }
///
/// Called immediately before evaluation starts
@@ -844,6 +899,8 @@ private void OnEvaluationBegin(PyModule scope,
registeredUnwrapMarshaler = true;
}
+
+ scope.Exec(ConnectionNodeCompatPatchCode());
}
///