| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 8d61215 commit cc72be4
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,197 @@ | |||
| 1 | + namespace Python.Runtime; | ||
| 2 | + | ||
| 3 | + using System; | ||
| 4 | + using System.Collections.Generic; | ||
| 5 | + using System.Linq; | ||
| 6 | + using System.Runtime.Serialization; | ||
| 7 | + using System.Threading; | ||
| 8 | + | ||
| 9 | + using Python.Runtime.Native; | ||
| 10 | + | ||
| 11 | + public static class Py | ||
| 12 | + { | ||
| 13 | + public static GILState GIL() | ||
| 14 | + { | ||
| 15 | + if (!PythonEngine.IsInitialized) | ||
| 16 | + { | ||
| 17 | + PythonEngine.Initialize(); | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + return PythonEngine.DebugGIL ? new DebugGILState() : new GILState(); | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + public static PyModule CreateScope() => new(); | ||
| 24 | + public static PyModule CreateScope(string name) | ||
| 25 | + => new(name ?? throw new ArgumentNullException(nameof(name))); | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + public class GILState : IDisposable | ||
| 29 | + { | ||
| 30 | + private readonly PyGILState state; | ||
| 31 | + private bool isDisposed; | ||
| 32 | + | ||
| 33 | + internal GILState() | ||
| 34 | + { | ||
| 35 | + state = PythonEngine.AcquireLock(); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + public virtual void Dispose() | ||
| 39 | + { | ||
| 40 | + if (this.isDisposed) return; | ||
| 41 | + | ||
| 42 | + PythonEngine.ReleaseLock(state); | ||
| 43 | + GC.SuppressFinalize(this); | ||
| 44 | + this.isDisposed = true; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + ~GILState() | ||
| 48 | + { | ||
| 49 | + throw new InvalidOperationException("GIL must always be released, and it must be released from the same thread that acquired it."); | ||
| 50 | + } | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + public class DebugGILState : GILState | ||
| 54 | + { | ||
| 55 | + readonly Thread owner; | ||
| 56 | + internal DebugGILState() : base() | ||
| 57 | + { | ||
| 58 | + this.owner = Thread.CurrentThread; | ||
| 59 | + } | ||
| 60 | + public override void Dispose() | ||
| 61 | + { | ||
| 62 | + if (this.owner != Thread.CurrentThread) | ||
| 63 | + throw new InvalidOperationException("GIL must always be released from the same thread, that acquired it"); | ||
| 64 | + | ||
| 65 | + base.Dispose(); | ||
| 66 | + } | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + public class KeywordArguments : PyDict | ||
| 70 | + { | ||
| 71 | + public KeywordArguments() : base() | ||
| 72 | + { | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + protected KeywordArguments(SerializationInfo info, StreamingContext context) | ||
| 76 | + : base(info, context) { } | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + public static KeywordArguments kw(params object?[] kv) | ||
| 80 | + { | ||
| 81 | + var dict = new KeywordArguments(); | ||
| 82 | + if (kv.Length % 2 != 0) | ||
| 83 | + { | ||
| 84 | + throw new ArgumentException("Must have an equal number of keys and values"); | ||
| 85 | + } | ||
| 86 | + for (var i = 0; i < kv.Length; i += 2) | ||
| 87 | + { | ||
| 88 | + var key = kv[i] as string; | ||
| 89 | + if (key is null) | ||
| 90 | + throw new ArgumentException("Keys must be non-null strings"); | ||
| 91 | + | ||
| 92 | + BorrowedReference value; | ||
| 93 | + NewReference temp = default; | ||
| 94 | + if (kv[i + 1] is PyObject pyObj) | ||
| 95 | + { | ||
| 96 | + value = pyObj; | ||
| 97 | + } | ||
| 98 | + else | ||
| 99 | + { | ||
| 100 | + temp = Converter.ToPythonDetectType(kv[i + 1]); | ||
| 101 | + value = temp.Borrow(); | ||
| 102 | + } | ||
| 103 | + using (temp) | ||
| 104 | + { | ||
| 105 | + if (Runtime.PyDict_SetItemString(dict, key, value) != 0) | ||
| 106 | + { | ||
| 107 | + throw new ArgumentException( | ||
| 108 | + string.Format("Cannot add key '{0}' to dictionary.", key), | ||
| 109 | + innerException: PythonException.FetchCurrent()); | ||
| 110 | + } | ||
| 111 | + } | ||
| 112 | + } | ||
| 113 | + return dict; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + /// <summary> | ||
| 117 | + /// Given a module or package name, import the module and return the resulting object. | ||
| 118 | + /// </summary> | ||
| 119 | + /// <param name="name">Fully-qualified module or package name</param> | ||
| 120 | + public static PyObject Import(string name) => PyModule.Import(name); | ||
| 121 | + | ||
| 122 | + public static void SetArgv() | ||
| 123 | + { | ||
| 124 | + IEnumerable<string> args; | ||
| 125 | + try | ||
| 126 | + { | ||
| 127 | + args = Environment.GetCommandLineArgs(); | ||
| 128 | + } | ||
| 129 | + catch (NotSupportedException) | ||
| 130 | + { | ||
| 131 | + args = Enumerable.Empty<string>(); | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + SetArgv( | ||
| 135 | + new[] { "" }.Concat( | ||
| 136 | + Environment.GetCommandLineArgs().Skip(1) | ||
| 137 | + ) | ||
| 138 | + ); | ||
| 139 | + } | ||
| 140 | + | ||
| 141 | + public static void SetArgv(params string[] argv) | ||
| 142 | + { | ||
| 143 | + SetArgv(argv as IEnumerable<string>); | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + public static void SetArgv(IEnumerable<string> argv) | ||
| 147 | + { | ||
| 148 | + if (argv is null) throw new ArgumentNullException(nameof(argv)); | ||
| 149 | + | ||
| 150 | + using (GIL()) | ||
| 151 | + { | ||
| 152 | + string[] arr = argv.ToArray(); | ||
| 153 | + Runtime.PySys_SetArgvEx(arr.Length, arr, 0); | ||
| 154 | + Runtime.CheckExceptionOccurred(); | ||
| 155 | + } | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + public static void With(PyObject obj, Action<PyObject> Body) | ||
| 159 | + { | ||
| 160 | + if (obj is null) throw new ArgumentNullException(nameof(obj)); | ||
| 161 | + if (Body is null) throw new ArgumentNullException(nameof(Body)); | ||
| 162 | + | ||
| 163 | + // Behavior described here: | ||
| 164 | + // https://docs.python.org/2/reference/datamodel.html#with-statement-context-managers | ||
| 165 | + | ||
| 166 | + Exception? ex = null; | ||
| 167 | + PythonException? pyError = null; | ||
| 168 | + | ||
| 169 | + try | ||
| 170 | + { | ||
| 171 | + PyObject enterResult = obj.InvokeMethod("__enter__"); | ||
| 172 | + | ||
| 173 | + Body(enterResult); | ||
| 174 | + } | ||
| 175 | + catch (PythonException e) | ||
| 176 | + { | ||
| 177 | + ex = pyError = e; | ||
| 178 | + } | ||
| 179 | + catch (Exception e) | ||
| 180 | + { | ||
| 181 | + ex = e; | ||
| 182 | + Exceptions.SetError(e); | ||
| 183 | + pyError = PythonException.FetchCurrentRaw(); | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + PyObject type = pyError?.Type ?? PyObject.None; | ||
| 187 | + PyObject val = pyError?.Value ?? PyObject.None; | ||
| 188 | + PyObject traceBack = pyError?.Traceback ?? PyObject.None; | ||
| 189 | + | ||
| 190 | + var exitResult = obj.InvokeMethod("__exit__", type, val, traceBack); | ||
| 191 | + | ||
| 192 | + if (ex != null && !exitResult.IsTrue()) throw ex; | ||
| 193 | + } | ||
| 194 | + | ||
| 195 | + public static void With(PyObject obj, Action<dynamic> Body) | ||
| 196 | + => With(obj, (PyObject context) => Body(context)); | ||
| 197 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,8 +5,6 @@ | |||
| 5 | 5 | using System.Linq; | |
| 6 | 6 | using System.Reflection; | |
| 7 | 7 | using System.Runtime.InteropServices; | |
| 8 | - using System.Runtime.Serialization; | ||
| 9 | - using System.Threading; | ||
| 10 | 8 | ||
| 11 | 9 | using Python.Runtime.Native; | |
| 12 | 10 | ||
@@ -671,189 +669,4 @@ public enum RunFlagType : int | |||
| 671 | 669 | File = 257, /* Py_file_input */ | |
| 672 | 670 | Eval = 258 | |
| 673 | 671 | } | |
| 674 | - | ||
| 675 | - public static class Py | ||
| 676 | - { | ||
| 677 | - public static GILState GIL() | ||
| 678 | - { | ||
| 679 | - if (!PythonEngine.IsInitialized) | ||
| 680 | - { | ||
| 681 | - PythonEngine.Initialize(); | ||
| 682 | - } | ||
| 683 | - | ||
| 684 | - return PythonEngine.DebugGIL ? new DebugGILState() : new GILState(); | ||
| 685 | - } | ||
| 686 | - | ||
| 687 | - public static PyModule CreateScope() => new(); | ||
| 688 | - public static PyModule CreateScope(string name) | ||
| 689 | - => new(name ?? throw new ArgumentNullException(nameof(name))); | ||
| 690 | - | ||
| 691 | - | ||
| 692 | - public class GILState : IDisposable | ||
| 693 | - { | ||
| 694 | - private readonly PyGILState state; | ||
| 695 | - private bool isDisposed; | ||
| 696 | - | ||
| 697 | - internal GILState() | ||
| 698 | - { | ||
| 699 | - state = PythonEngine.AcquireLock(); | ||
| 700 | - } | ||
| 701 | - | ||
| 702 | - public virtual void Dispose() | ||
| 703 | - { | ||
| 704 | - if (this.isDisposed) return; | ||
| 705 | - | ||
| 706 | - PythonEngine.ReleaseLock(state); | ||
| 707 | - GC.SuppressFinalize(this); | ||
| 708 | - this.isDisposed = true; | ||
| 709 | - } | ||
| 710 | - | ||
| 711 | - ~GILState() | ||
| 712 | - { | ||
| 713 | - throw new InvalidOperationException("GIL must always be released, and it must be released from the same thread that acquired it."); | ||
| 714 | - } | ||
| 715 | - } | ||
| 716 | - | ||
| 717 | - public class DebugGILState : GILState | ||
| 718 | - { | ||
| 719 | - readonly Thread owner; | ||
| 720 | - internal DebugGILState() : base() | ||
| 721 | - { | ||
| 722 | - this.owner = Thread.CurrentThread; | ||
| 723 | - } | ||
| 724 | - public override void Dispose() | ||
| 725 | - { | ||
| 726 | - if (this.owner != Thread.CurrentThread) | ||
| 727 | - throw new InvalidOperationException("GIL must always be released from the same thread, that acquired it"); | ||
| 728 | - | ||
| 729 | - base.Dispose(); | ||
| 730 | - } | ||
| 731 | - } | ||
| 732 | - | ||
| 733 | - public class KeywordArguments : PyDict | ||
| 734 | - { | ||
| 735 | - public KeywordArguments() : base() | ||
| 736 | - { | ||
| 737 | - } | ||
| 738 | - | ||
| 739 | - protected KeywordArguments(SerializationInfo info, StreamingContext context) | ||
| 740 | - : base(info, context) { } | ||
| 741 | - } | ||
| 742 | - | ||
| 743 | - public static KeywordArguments kw(params object?[] kv) | ||
| 744 | - { | ||
| 745 | - var dict = new KeywordArguments(); | ||
| 746 | - if (kv.Length % 2 != 0) | ||
| 747 | - { | ||
| 748 | - throw new ArgumentException("Must have an equal number of keys and values"); | ||
| 749 | - } | ||
| 750 | - for (var i = 0; i < kv.Length; i += 2) | ||
| 751 | - { | ||
| 752 | - var key = kv[i] as string; | ||
| 753 | - if (key is null) | ||
| 754 | - throw new ArgumentException("Keys must be non-null strings"); | ||
| 755 | - | ||
| 756 | - BorrowedReference value; | ||
| 757 | - NewReference temp = default; | ||
| 758 | - if (kv[i + 1] is PyObject pyObj) | ||
| 759 | - { | ||
| 760 | - value = pyObj; | ||
| 761 | - } | ||
| 762 | - else | ||
| 763 | - { | ||
| 764 | - temp = Converter.ToPythonDetectType(kv[i + 1]); | ||
| 765 | - value = temp.Borrow(); | ||
| 766 | - } | ||
| 767 | - using (temp) | ||
| 768 | - { | ||
| 769 | - if (Runtime.PyDict_SetItemString(dict, key, value) != 0) | ||
| 770 | - { | ||
| 771 | - throw new ArgumentException( | ||
| 772 | - string.Format("Cannot add key '{0}' to dictionary.", key), | ||
| 773 | - innerException: PythonException.FetchCurrent()); | ||
| 774 | - } | ||
| 775 | - } | ||
| 776 | - } | ||
| 777 | - return dict; | ||
| 778 | - } | ||
| 779 | - | ||
| 780 | - /// <summary> | ||
| 781 | - /// Given a module or package name, import the module and return the resulting object. | ||
| 782 | - /// </summary> | ||
| 783 | - /// <param name="name">Fully-qualified module or package name</param> | ||
| 784 | - public static PyObject Import(string name) => PyModule.Import(name); | ||
| 785 | - | ||
| 786 | - public static void SetArgv() | ||
| 787 | - { | ||
| 788 | - IEnumerable<string> args; | ||
| 789 | - try | ||
| 790 | - { | ||
| 791 | - args = Environment.GetCommandLineArgs(); | ||
| 792 | - } | ||
| 793 | - catch (NotSupportedException) | ||
| 794 | - { | ||
| 795 | - args = Enumerable.Empty<string>(); | ||
| 796 | - } | ||
| 797 | - | ||
| 798 | - SetArgv( | ||
| 799 | - new[] { "" }.Concat( | ||
| 800 | - Environment.GetCommandLineArgs().Skip(1) | ||
| 801 | - ) | ||
| 802 | - ); | ||
| 803 | - } | ||
| 804 | - | ||
| 805 | - public static void SetArgv(params string[] argv) | ||
| 806 | - { | ||
| 807 | - SetArgv(argv as IEnumerable<string>); | ||
| 808 | - } | ||
| 809 | - | ||
| 810 | - public static void SetArgv(IEnumerable<string> argv) | ||
| 811 | - { | ||
| 812 | - if (argv is null) throw new ArgumentNullException(nameof(argv)); | ||
| 813 | - | ||
| 814 | - using (GIL()) | ||
| 815 | - { | ||
| 816 | - string[] arr = argv.ToArray(); | ||
| 817 | - Runtime.PySys_SetArgvEx(arr.Length, arr, 0); | ||
| 818 | - Runtime.CheckExceptionOccurred(); | ||
| 819 | - } | ||
| 820 | - } | ||
| 821 | - | ||
| 822 | - public static void With(PyObject obj, Action<dynamic> Body) | ||
| 823 | - { | ||
| 824 | - if (obj is null) throw new ArgumentNullException(nameof(obj)); | ||
| 825 | - if (Body is null) throw new ArgumentNullException(nameof(Body)); | ||
| 826 | - | ||
| 827 | - // Behavior described here: | ||
| 828 | - // https://docs.python.org/2/reference/datamodel.html#with-statement-context-managers | ||
| 829 | - | ||
| 830 | - Exception? ex = null; | ||
| 831 | - PythonException? pyError = null; | ||
| 832 | - | ||
| 833 | - try | ||
| 834 | - { | ||
| 835 | - PyObject enterResult = obj.InvokeMethod("__enter__"); | ||
| 836 | - | ||
| 837 | - Body(enterResult); | ||
| 838 | - } | ||
| 839 | - catch (PythonException e) | ||
| 840 | - { | ||
| 841 | - ex = pyError = e; | ||
| 842 | - } | ||
| 843 | - catch (Exception e) | ||
| 844 | - { | ||
| 845 | - ex = e; | ||
| 846 | - Exceptions.SetError(e); | ||
| 847 | - pyError = PythonException.FetchCurrentRaw(); | ||
| 848 | - } | ||
| 849 | - | ||
| 850 | - PyObject type = pyError?.Type ?? PyObject.None; | ||
| 851 | - PyObject val = pyError?.Value ?? PyObject.None; | ||
| 852 | - PyObject traceBack = pyError?.Traceback ?? PyObject.None; | ||
| 853 | - | ||
| 854 | - var exitResult = obj.InvokeMethod("__exit__", type, val, traceBack); | ||
| 855 | - | ||
| 856 | - if (ex != null && !exitResult.IsTrue()) throw ex; | ||
| 857 | - } | ||
| 858 | - } | ||
| 859 | 672 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments