Skip to content
This repository was archived by the owner on Jan 6, 2021. It is now read-only.

Commit 7aabf35

Browse files
committed
added ghpython package to allow access to components.py
1 parent 2fdc8d2 commit 7aabf35

7 files changed

Lines changed: 143 additions & 59 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ GhPython.suo
99
/references/Grasshopper.xml
1010
/references/RhinoCommon.dll
1111
/references/GH_Util.dll
12-
/references/Grasshopper.pdb
12+
/references/Grasshopper.pdb
13+
/*.suo

Component/PythonEnvironment.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace GhPython.Component
1010
{
1111
public class PythonEnvironment
1212
{
13-
internal PythonEnvironment(Grasshopper.Kernel.GH_Component component, PythonScript script)
13+
internal PythonEnvironment(GH_Component component, PythonScript script)
1414
{
1515
Component = component;
1616
Script = script;
@@ -26,7 +26,7 @@ internal PythonEnvironment(Grasshopper.Kernel.GH_Component component, PythonScri
2626
}
2727

2828
var intellisenseField = scriptType.GetField("m_intellisense",
29-
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField);
29+
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField);
3030
if (intellisenseField != null)
3131
{
3232
Intellisense = intellisenseField.GetValue(script);
@@ -56,9 +56,9 @@ internal PythonEnvironment(Grasshopper.Kernel.GH_Component component, PythonScri
5656
}
5757
}
5858

59-
var scopeInfo = hostType.GetProperty("Scope", System.Reflection.BindingFlags.NonPublic |
60-
System.Reflection.BindingFlags.GetProperty |
61-
System.Reflection.BindingFlags.Static);
59+
var scopeInfo = hostType.GetProperty("Scope", BindingFlags.NonPublic |
60+
BindingFlags.GetProperty |
61+
BindingFlags.Static);
6262
if (scopeInfo != null)
6363
ScriptScope = scopeInfo.GetValue(null, null);
6464
}

Component/SafeComponent.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ protected sealed override void SolveInstance(IGH_DataAccess DA)
7979
SafeSolveInstance(DA);
8080
}
8181

82-
protected abstract void SafeSolveInstance(IGH_DataAccess DA);
82+
protected abstract void SafeSolveInstance(IGH_DataAccess da);
8383

8484
private void GrasshopperDocumentClosed(GH_DocumentServer sender, GH_Document doc)
8585
{

Component/ScriptingAncestorComponent.cs

Lines changed: 84 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace GhPython.Component
1616
{
1717
public abstract class ScriptingAncestorComponent : SafeComponent
1818
{
19+
static bool g_resources_unpacked = false;
1920
private readonly StringList m_py_output = new StringList(); // python output stream is piped here
2021
internal static GrasshopperDocument m_document = new GrasshopperDocument();
2122
internal ComponentIOMarshal m_marshal;
@@ -38,9 +39,81 @@ protected ScriptingAncestorComponent()
3839
{
3940
}
4041

41-
public override void AddRuntimeMessage(GH_RuntimeMessageLevel level, string text)
42+
private static void UnpackScriptResources()
4243
{
43-
base.AddRuntimeMessage(level, text);
44+
if (g_resources_unpacked)
45+
return;
46+
Guid python_plugin_id = new Guid("814d908a-e25c-493d-97e9-ee3861957f49");
47+
var plugin = Rhino.PlugIns.PlugIn.Find(python_plugin_id);
48+
if (plugin == null)
49+
return;
50+
51+
g_resources_unpacked = true;
52+
53+
// Unpack ghcomponents.py to the Python plug directory
54+
string settings_directory = plugin.SettingsDirectory;
55+
string marker_file = Path.Combine(settings_directory, "ghpy_version.txt");
56+
try
57+
{
58+
if (File.Exists(marker_file))
59+
{
60+
string text = File.ReadAllText(marker_file);
61+
Version markedversion = new Version(text);
62+
Version this_version = typeof(ZuiPythonComponent).Assembly.GetName().Version;
63+
if (markedversion == this_version)
64+
{
65+
#if !DEBUG
66+
// everything looks good, bail out
67+
return;
68+
#endif
69+
}
70+
}
71+
}
72+
catch (Exception ex)
73+
{
74+
HostUtils.ExceptionReport(ex);
75+
}
76+
77+
try
78+
{
79+
// if we get to here, we need to unpack the resources
80+
if (!Directory.Exists(settings_directory))
81+
Directory.CreateDirectory(settings_directory);
82+
string ghpython_package_dir = Path.Combine(settings_directory, "lib", "ghpython");
83+
if (Directory.Exists(ghpython_package_dir))
84+
Directory.Delete(ghpython_package_dir, true);
85+
Directory.CreateDirectory(ghpython_package_dir);
86+
System.Reflection.Assembly a = typeof(ZuiPythonComponent).Assembly;
87+
string[] names = a.GetManifestResourceNames();
88+
89+
const string prefix = "GhPython.package.";
90+
91+
foreach (string name in names)
92+
{
93+
if (!name.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase))
94+
continue;
95+
96+
Stream resource_stream = a.GetManifestResourceStream(name);
97+
if (resource_stream == null)
98+
continue;
99+
StreamReader stream = new StreamReader(resource_stream);
100+
string s = stream.ReadToEnd();
101+
stream.Close();
102+
string filename = name.Replace(prefix, "");
103+
string path = Path.Combine(ghpython_package_dir, filename);
104+
File.WriteAllText(path, s);
105+
}
106+
107+
// Write the marker file at the very end to ensure that we actually got to this point.
108+
// If an exception occured for some reason like a file was in use, then the plug-in
109+
// will just attempt to unpack the resources next time.
110+
string str = a.GetName().Version.ToString();
111+
File.WriteAllText(marker_file, str);
112+
}
113+
catch (Exception ex)
114+
{
115+
HostUtils.DebugString("Exception while unpacking resources: " + ex.Message);
116+
}
44117
}
45118

46119
protected override void Initialize()
@@ -53,6 +126,7 @@ protected override void Initialize()
53126
m_py = PythonScript.Create();
54127
if (m_py != null)
55128
{
129+
UnpackScriptResources();
56130
SetScriptTransientGlobals();
57131
m_py.Output = m_py_output.Write;
58132
m_py.SetVariable("__name__", "__main__");
@@ -243,16 +317,16 @@ private static Param_String ConstructOutOutputParam()
243317

244318
#region Solving
245319

246-
protected override void SafeSolveInstance(IGH_DataAccess DA)
320+
protected override void SafeSolveInstance(IGH_DataAccess da)
247321
{
248322
if (m_py == null)
249323
{
250-
DA.SetData(0, "No Python engine available. This component needs Rhino v5");
324+
da.SetData(0, "No Python engine available. This component needs Rhino v5");
251325
return;
252326
}
253327

254328
if(!HiddenOutOutput)
255-
DA.DisableGapLogic(0);
329+
da.DisableGapLogic(0);
256330

257331
m_py_output.Reset();
258332

@@ -277,7 +351,7 @@ protected override void SafeSolveInstance(IGH_DataAccess DA)
277351
for (int i = showing_code_input ? 1 : 0; i < Params.Input.Count; i++)
278352
{
279353
string varname = Params.Input[i].NickName;
280-
object o = m_marshal.GetInput(DA, i);
354+
object o = m_marshal.GetInput(da, i);
281355
m_py.SetVariable(varname, o);
282356
m_py.SetIntellisenseVariable(varname, o);
283357
}
@@ -291,7 +365,7 @@ protected override void SafeSolveInstance(IGH_DataAccess DA)
291365
else
292366
{
293367
script = null;
294-
DA.GetData(0, ref script);
368+
da.GetData(0, ref script);
295369
}
296370

297371
if (string.IsNullOrWhiteSpace(script))
@@ -325,7 +399,7 @@ protected override void SafeSolveInstance(IGH_DataAccess DA)
325399
{
326400
string varname = Params.Output[i].NickName;
327401
object o = m_py.GetVariable(varname);
328-
m_marshal.SetOutput(o, DA, i);
402+
m_marshal.SetOutput(o, da, i);
329403
}
330404
}
331405
else
@@ -336,15 +410,15 @@ protected override void SafeSolveInstance(IGH_DataAccess DA)
336410
catch (Exception ex)
337411
{
338412
AddErrorNicely(m_py_output, ex);
339-
SetFormErrorOrClearIt(DA, m_py_output);
413+
SetFormErrorOrClearIt(da, m_py_output);
340414
throw;
341415
}
342416
finally
343417
{
344418
if (rhdoc != null && prevEnabled != rhdoc.Views.RedrawEnabled)
345419
rhdoc.Views.RedrawEnabled = true;
346420
}
347-
SetFormErrorOrClearIt(DA, m_py_output);
421+
SetFormErrorOrClearIt(da, m_py_output);
348422
}
349423

350424
private bool AddLocalPath(out string location)

GhPython.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@
153153
</BootstrapperPackage>
154154
</ItemGroup>
155155
<ItemGroup>
156+
<EmbeddedResource Include="package\components.py" />
157+
<EmbeddedResource Include="package\__init__.py" />
156158
<Content Include="Samples\sampleCommon.py" />
157159
<None Include="Samples\helpText.html" />
158160
<Content Include="Samples\sampleScript.py" />

package/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# GhPython package
2+
__all__ = ["components"]
Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22
clr.AddReference("Grasshopper")
33
import Grasshopper as GH
44

5-
def __makefunc__(obj):
5+
6+
def __make_function__(obj):
67
def component_function(*args, **kwargs):
7-
""""returns dictionary of output values"""
88
comp = obj.CreateInstance()
99
comp.ClearData()
1010

1111
if args:
1212
for i, arg in enumerate(args):
13+
if arg is None:
14+
continue
1315
param = comp.Params.Input[i]
1416
param.PersistentData.Clear()
1517
if hasattr(arg, '__iter__'): #TODO deal with polyline
@@ -41,49 +43,13 @@ def component_function(*args, **kwargs):
4143
return rc
4244
return component_function
4345

46+
4447
class namespace_object(object):
4548
def __init__(self):
4649
pass
4750

48-
class __builder(object):
49-
def __init__(self):
50-
import sys, types, string
51-
core_module = sys.modules['ghcomponents']
52-
translation = string.maketrans("'()*|","_____")
53-
for obj in GH.Instances.ComponentServer.ObjectProxies:
54-
if obj.Exposure==GH.Kernel.GH_Exposure.hidden or obj.Obsolete:
55-
continue
56-
t = clr.GetClrType(GH.Kernel.IGH_Component)
57-
if not (t.IsAssignableFrom(obj.Type)):
58-
continue
59-
m = core_module
60-
library_id = obj.LibraryGuid
61-
assembly = GH.Instances.ComponentServer.FindAssembly(library_id)
62-
if not assembly.IsCoreLibrary:
63-
module_name = assembly.Assembly.GetName().Name
64-
if core_module.__dict__.has_key(module_name):
65-
m = core_module.__dict__[module_name]
66-
else:
67-
m = namespace_object()
68-
setattr(core_module, module_name, m)
69-
name = obj.Desc.Name.Replace(" ","")
70-
name = name.translate(translation)
71-
if not name[0].isalpha(): name = '_' + name
72-
73-
if m==core_module:
74-
setattr(m, name, __makefunc__(obj))
75-
comp = obj.CreateInstance()
76-
a = m.__dict__[name]
77-
a.__name__ = name
78-
params = self.param_descriptions(comp.Params)
79-
help = "\n" + obj.Desc.Description
80-
for param in params:
81-
help = help + "\n" + param
82-
a.__doc__ = help
83-
else:
84-
setattr(m, name, types.MethodType(__makefunc__(obj), m, type(m)))
85-
86-
def param_descriptions(self, params):
51+
def __build_module():
52+
def param_descriptions(params):
8753
rc = []
8854
for param in params:
8955
if param.Kind == GH.Kernel.GH_ParamKind.input:
@@ -95,6 +61,45 @@ def param_descriptions(self, params):
9561
s = "{0} (out) [{1}] - {2}"
9662
rc.append(s.format(param.NickName, param.TypeName, param.Description))
9763
return rc
64+
65+
import sys, types, string
66+
core_module = sys.modules['ghpython.components']
67+
translation = string.maketrans("'()*|", "_____")
68+
for obj in GH.Instances.ComponentServer.ObjectProxies:
69+
if obj.Exposure == GH.Kernel.GH_Exposure.hidden or obj.Obsolete:
70+
continue
71+
t = clr.GetClrType(GH.Kernel.IGH_Component)
72+
if not (t.IsAssignableFrom(obj.Type)):
73+
continue
74+
m = core_module
75+
library_id = obj.LibraryGuid
76+
assembly = GH.Instances.ComponentServer.FindAssembly(library_id)
77+
if not assembly.IsCoreLibrary:
78+
module_name = assembly.Assembly.GetName().Name
79+
if core_module.__dict__.has_key(module_name):
80+
m = core_module.__dict__[module_name]
81+
else:
82+
m = namespace_object()
83+
setattr(core_module, module_name, m)
84+
name = obj.Desc.Name.Replace(" ", "")
85+
if "LEGACY" in name:
86+
continue
87+
name = name.translate(translation)
88+
if not name[0].isalpha(): name = '_' + name
89+
90+
function = __make_function__(obj)
91+
if m == core_module:
92+
setattr(m, name, function)
93+
comp = obj.CreateInstance()
94+
a = m.__dict__[name]
95+
a.__name__ = name
96+
params = param_descriptions(comp.Params)
97+
documentation = "\n" + obj.Desc.Description
98+
for param in params:
99+
documentation = documentation + "\n" + param
100+
a.__doc__ = documentation
101+
else:
102+
setattr(m, name, types.MethodType(function, m, type(m)))
98103

99104

100-
__b = __builder()
105+
__build_module()

0 commit comments

Comments
 (0)