11using System ;
22using System . IO ;
3+ using System . Reflection ;
34using System . Reactive . Concurrency ;
45using System . Reactive . Linq ;
56using Python . Runtime ;
7+ using SystemPath = System . IO . Path ;
68
79namespace Bonsai . Scripting . Python
810{
@@ -13,6 +15,7 @@ namespace Bonsai.Scripting.Python
1315 /// </summary>
1416 public class RuntimeManager : IDisposable
1517 {
18+ const char AssemblySeparator = ':' ;
1619 readonly EventLoopScheduler runtimeScheduler ;
1720 readonly IObserver < RuntimeManager > runtimeObserver ;
1821 IntPtr threadState ;
@@ -40,6 +43,36 @@ internal RuntimeManager(string pythonHome, string scriptPath, IObserver<RuntimeM
4043 disposable => disposable . Subject )
4144 . Take ( 1 ) ;
4245
46+ internal static bool IsEmbeddedResourcePath ( string path )
47+ {
48+ var separatorIndex = path . IndexOf ( AssemblySeparator ) ;
49+ return separatorIndex >= 0 && ! SystemPath . IsPathRooted ( path ) ;
50+ }
51+
52+ internal static string GetEmbeddedPythonCode ( string path )
53+ {
54+ var nameElements = path . Split ( new [ ] { AssemblySeparator } , 2 ) ;
55+ if ( string . IsNullOrEmpty ( nameElements [ 0 ] ) )
56+ {
57+ throw new InvalidOperationException (
58+ "The embedded resource path \" " + path +
59+ "\" must be qualified with a valid assembly name." ) ;
60+ }
61+
62+ var assembly = Assembly . Load ( nameElements [ 0 ] ) ;
63+ var resourceName = string . Join ( ExpressionHelper . MemberSeparator , nameElements ) ;
64+ using var resourceStream = assembly . GetManifestResourceStream ( resourceName ) ;
65+ if ( resourceStream == null )
66+ {
67+ throw new InvalidOperationException (
68+ "The specified embedded resource \" " + nameElements [ 1 ] +
69+ "\" was not found in assembly \" " + nameElements [ 0 ] + "\" " ) ;
70+ }
71+ using var reader = new StreamReader ( resourceStream ) ;
72+ var code = reader . ReadToEnd ( ) ;
73+ return code ;
74+ }
75+
4376 internal static DynamicModule CreateModule ( string name = "" , string scriptPath = "" )
4477 {
4578 using ( Py . GIL ( ) )
@@ -49,7 +82,7 @@ internal static DynamicModule CreateModule(string name = "", string scriptPath =
4982 {
5083 try
5184 {
52- var code = File . ReadAllText ( scriptPath ) ;
85+ var code = IsEmbeddedResourcePath ( scriptPath ) ? GetEmbeddedPythonCode ( scriptPath ) : File . ReadAllText ( scriptPath ) ;
5386 module . Exec ( code ) ;
5487 }
5588 catch ( Exception )
0 commit comments