Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add pysetargv #347

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion src/embed_tests/InitializeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,29 @@ namespace Python.EmbeddingTest
public class InitializeTest
{
[Test]
public static void Test()
public static void LoadSpecificArgs()
{
var args = new[] { "test1", "test2" };
using (new PythonEngine(args))
using (var argv = new PyList(Runtime.Runtime.PySys_GetObject("argv")))
{
Assert.That(argv[0].ToString() == args[0]);
Assert.That(argv[1].ToString() == args[1]);
}
}

[Test]
public static void LoadDefaultArgs()
{
using (new PythonEngine())
using (var argv = new PyList(Runtime.Runtime.PySys_GetObject("argv")))
{
Assert.That(argv.Length() != 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

first need to check that it is not null

Copy link
Member Author

@filmor filmor Jan 31, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? If it is null, this will fail with a NullReferenceException, perfectly fine. This PR is supposed to ensure that sys.argv is always initialised.

}
}

[Test]
public static void StartAndStopTwice()
{
PythonEngine.Initialize();
PythonEngine.Shutdown();
Expand Down
108 changes: 84 additions & 24 deletions src/runtime/pythonengine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,39 @@
using System.IO;
using System.Threading;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;

namespace Python.Runtime
{
/// <summary>
/// This class provides the public interface of the Python runtime.
/// </summary>
public class PythonEngine
public class PythonEngine : IDisposable
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this now IDisposable?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because that's easier to use correctly than Initialize and Shutdown.

{
private static DelegateManager delegateManager;
private static bool initialized;

public PythonEngine()
{
Initialize();
}

public PythonEngine(params string[] args)
{
Initialize(args);
}

public PythonEngine(IEnumerable<string> args)
{
Initialize(args);
}

public void Dispose()
{
Shutdown();
}

#region Properties

public static bool IsInitialized
Expand Down Expand Up @@ -102,6 +124,11 @@ public static int RunSimpleString(string code)

#endregion

public static void Initialize()
{
Initialize(Enumerable.Empty<string>());
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we need to check if sys.argv is non-empty in the case of extending with import clr? @filmor @vmuriart anyway let's see if this passes my tests

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i did not click submit review few weeks ago

/// <summary>
/// Initialize Method
/// </summary>
Expand All @@ -112,7 +139,7 @@ public static int RunSimpleString(string code)
/// first call. It is *not* necessary to hold the Python global
/// interpreter lock (GIL) to call this method.
/// </remarks>
public static void Initialize()
public static void Initialize(IEnumerable<string> args)
{
if (!initialized)
{
Expand All @@ -126,6 +153,8 @@ public static void Initialize()
initialized = true;
Exceptions.Clear();

Py.SetArgv(args);

// register the atexit callback (this doesn't use Py_AtExit as the C atexit
// callbacks are called after python is fully finalized but the python ones
// are called while the python engine is still running).
Expand Down Expand Up @@ -187,7 +216,8 @@ public static void Initialize()
// when it is imported by the CLR extension module.
//====================================================================
#if PYTHON3
public static IntPtr InitExt() {
public static IntPtr InitExt()
{
#elif PYTHON2
public static void InitExt()
{
Expand Down Expand Up @@ -351,10 +381,7 @@ public static void EndAllowThreads(IntPtr ts)
public static PyObject ImportModule(string name)
{
IntPtr op = Runtime.PyImport_ImportModule(name);
if (op == IntPtr.Zero)
{
return null;
}
Py.Throw();
return new PyObject(op);
}

Expand All @@ -370,10 +397,7 @@ public static PyObject ImportModule(string name)
public static PyObject ReloadModule(PyObject module)
{
IntPtr op = Runtime.PyImport_ReloadModule(module.Handle);
if (op == IntPtr.Zero)
{
throw new PythonException();
}
Py.Throw();
return new PyObject(op);
}

Expand All @@ -389,15 +413,9 @@ public static PyObject ReloadModule(PyObject module)
public static PyObject ModuleFromString(string name, string code)
{
IntPtr c = Runtime.Py_CompileString(code, "none", (IntPtr)257);
if (c == IntPtr.Zero)
{
throw new PythonException();
}
Py.Throw();
IntPtr m = Runtime.PyImport_ExecCodeModule(name, c);
if (m == IntPtr.Zero)
{
throw new PythonException();
}
Py.Throw();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not also check for IntPtr.Zero?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this function either returns null and sets an exception, or it returns a module.

return new PyObject(m);
}

Expand Down Expand Up @@ -445,10 +463,7 @@ public static PyObject RunString(
code, flag, globals.Value, locals.Value
);

if (Runtime.PyErr_Occurred() != 0)
{
throw new PythonException();
}
Py.Throw();

return new PyObject(result);
}
Expand Down Expand Up @@ -500,7 +515,7 @@ public class KeywordArguments : PyDict
public static KeywordArguments kw(params object[] kv)
{
var dict = new KeywordArguments();
if (kv.Length%2 != 0)
if (kv.Length % 2 != 0)
throw new ArgumentException("Must have an equal number of keys and values");
for (int i = 0; i < kv.Length; i += 2)
{
Expand All @@ -521,5 +536,50 @@ public static PyObject Import(string name)
{
return PythonEngine.ImportModule(name);
}

public static void SetArgv()
{
IEnumerable<string> args;
try
{
args = Environment.GetCommandLineArgs();
}
catch (NotSupportedException)
{
args = Enumerable.Empty<string>();
}

SetArgv(
new[] { "" }.Concat(
Environment.GetCommandLineArgs().Skip(1)
)
);
}

public static void SetArgv(params string[] argv)
{
SetArgv(argv as IEnumerable<string>);
}

public static void SetArgv(IEnumerable<string> argv)
{
using (GIL())
{
var arr = argv.ToArray();
Runtime.PySys_SetArgvEx(arr.Length, arr, 0);
Py.Throw();
}
}

internal static void Throw()
{
using (GIL())
{
if (Runtime.PyErr_Occurred() != 0)
{
throw new PythonException();
}
}
}
}
}
19 changes: 17 additions & 2 deletions src/runtime/runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2027,11 +2027,26 @@ internal unsafe static extern IntPtr
internal unsafe static extern IntPtr
PyImport_GetModuleDict();


#if PYTHON3
[DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl,
ExactSpelling = true, CharSet = CharSet.Ansi)]
internal unsafe static extern void
PySys_SetArgv(int argc, IntPtr argv);
PySys_SetArgvEx(
int argc,
[MarshalAsAttribute(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)]
string[] argv,
int updatepath
);
#elif PYTHON2
[DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl,
ExactSpelling = true, CharSet = CharSet.Ansi)]
internal unsafe static extern void
PySys_SetArgvEx(
int argc,
string[] argv,
int updatepath
);
#endif

[DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl,
ExactSpelling = true, CharSet = CharSet.Ansi)]
Expand Down