pynect 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +478 -2
  3. package/SECURITY.md +34 -0
  4. package/binding.gyp +60 -0
  5. package/dist/cli/codegen.d.ts +3 -0
  6. package/dist/cli/codegen.d.ts.map +1 -0
  7. package/dist/cli/codegen.js +543 -0
  8. package/dist/cli/codegen.js.map +1 -0
  9. package/dist/cli/sync.d.ts +3 -0
  10. package/dist/cli/sync.d.ts.map +1 -0
  11. package/dist/cli/sync.js +48 -0
  12. package/dist/cli/sync.js.map +1 -0
  13. package/dist/config/project.d.ts +57 -0
  14. package/dist/config/project.d.ts.map +1 -0
  15. package/dist/config/project.js +176 -0
  16. package/dist/config/project.js.map +1 -0
  17. package/dist/core/IsolatedWorker.d.ts +39 -0
  18. package/dist/core/IsolatedWorker.d.ts.map +1 -0
  19. package/dist/core/IsolatedWorker.js +178 -0
  20. package/dist/core/IsolatedWorker.js.map +1 -0
  21. package/dist/core/PyCallable.d.ts +67 -0
  22. package/dist/core/PyCallable.d.ts.map +1 -0
  23. package/dist/core/PyCallable.js +104 -0
  24. package/dist/core/PyCallable.js.map +1 -0
  25. package/dist/core/PyContext.d.ts +76 -0
  26. package/dist/core/PyContext.d.ts.map +1 -0
  27. package/dist/core/PyContext.js +239 -0
  28. package/dist/core/PyContext.js.map +1 -0
  29. package/dist/core/PyIterator.d.ts +84 -0
  30. package/dist/core/PyIterator.d.ts.map +1 -0
  31. package/dist/core/PyIterator.js +243 -0
  32. package/dist/core/PyIterator.js.map +1 -0
  33. package/dist/core/PyModule.d.ts +53 -0
  34. package/dist/core/PyModule.d.ts.map +1 -0
  35. package/dist/core/PyModule.js +162 -0
  36. package/dist/core/PyModule.js.map +1 -0
  37. package/dist/core/PyProxy.d.ts +75 -0
  38. package/dist/core/PyProxy.d.ts.map +1 -0
  39. package/dist/core/PyProxy.js +563 -0
  40. package/dist/core/PyProxy.js.map +1 -0
  41. package/dist/core/PyRuntime.d.ts +112 -0
  42. package/dist/core/PyRuntime.d.ts.map +1 -0
  43. package/dist/core/PyRuntime.js +546 -0
  44. package/dist/core/PyRuntime.js.map +1 -0
  45. package/dist/env/PackageInstaller.d.ts +232 -0
  46. package/dist/env/PackageInstaller.d.ts.map +1 -0
  47. package/dist/env/PackageInstaller.js +628 -0
  48. package/dist/env/PackageInstaller.js.map +1 -0
  49. package/dist/env/ProjectEnvironment.d.ts +63 -0
  50. package/dist/env/ProjectEnvironment.d.ts.map +1 -0
  51. package/dist/env/ProjectEnvironment.js +379 -0
  52. package/dist/env/ProjectEnvironment.js.map +1 -0
  53. package/dist/env/PyfigAdapter.d.ts +32 -0
  54. package/dist/env/PyfigAdapter.d.ts.map +1 -0
  55. package/dist/env/PyfigAdapter.js +10 -0
  56. package/dist/env/PyfigAdapter.js.map +1 -0
  57. package/dist/env/PythonDetector.d.ts +48 -0
  58. package/dist/env/PythonDetector.d.ts.map +1 -0
  59. package/dist/env/PythonDetector.js +182 -0
  60. package/dist/env/PythonDetector.js.map +1 -0
  61. package/dist/env/PythonProvisioner.d.ts +16 -0
  62. package/dist/env/PythonProvisioner.d.ts.map +1 -0
  63. package/dist/env/PythonProvisioner.js +42 -0
  64. package/dist/env/PythonProvisioner.js.map +1 -0
  65. package/dist/env/VenvManager.d.ts +55 -0
  66. package/dist/env/VenvManager.d.ts.map +1 -0
  67. package/dist/env/VenvManager.js +153 -0
  68. package/dist/env/VenvManager.js.map +1 -0
  69. package/dist/env/executables.d.ts +3 -0
  70. package/dist/env/executables.d.ts.map +1 -0
  71. package/dist/env/executables.js +14 -0
  72. package/dist/env/executables.js.map +1 -0
  73. package/dist/index.d.ts +182 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +393 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/native/NativeAddonLoader.d.ts +11 -0
  78. package/dist/native/NativeAddonLoader.d.ts.map +1 -0
  79. package/dist/native/NativeAddonLoader.js +75 -0
  80. package/dist/native/NativeAddonLoader.js.map +1 -0
  81. package/dist/plugins/Plugin.interface.d.ts +41 -0
  82. package/dist/plugins/Plugin.interface.d.ts.map +1 -0
  83. package/dist/plugins/Plugin.interface.js +12 -0
  84. package/dist/plugins/Plugin.interface.js.map +1 -0
  85. package/dist/plugins/PluginManager.d.ts +26 -0
  86. package/dist/plugins/PluginManager.d.ts.map +1 -0
  87. package/dist/plugins/PluginManager.js +174 -0
  88. package/dist/plugins/PluginManager.js.map +1 -0
  89. package/dist/plugins/builtin/NumpyPlugin.d.ts +17 -0
  90. package/dist/plugins/builtin/NumpyPlugin.d.ts.map +1 -0
  91. package/dist/plugins/builtin/NumpyPlugin.js +41 -0
  92. package/dist/plugins/builtin/NumpyPlugin.js.map +1 -0
  93. package/dist/plugins/builtin/PandasPlugin.d.ts +19 -0
  94. package/dist/plugins/builtin/PandasPlugin.d.ts.map +1 -0
  95. package/dist/plugins/builtin/PandasPlugin.js +57 -0
  96. package/dist/plugins/builtin/PandasPlugin.js.map +1 -0
  97. package/dist/plugins/builtin/TorchPlugin.d.ts +23 -0
  98. package/dist/plugins/builtin/TorchPlugin.d.ts.map +1 -0
  99. package/dist/plugins/builtin/TorchPlugin.js +50 -0
  100. package/dist/plugins/builtin/TorchPlugin.js.map +1 -0
  101. package/dist/plugins/index.d.ts +7 -0
  102. package/dist/plugins/index.d.ts.map +1 -0
  103. package/dist/plugins/index.js +12 -0
  104. package/dist/plugins/index.js.map +1 -0
  105. package/dist/serialization/DataFrameBridge.d.ts +141 -0
  106. package/dist/serialization/DataFrameBridge.d.ts.map +1 -0
  107. package/dist/serialization/DataFrameBridge.js +355 -0
  108. package/dist/serialization/DataFrameBridge.js.map +1 -0
  109. package/dist/serialization/MsgPackSerializer.d.ts +45 -0
  110. package/dist/serialization/MsgPackSerializer.d.ts.map +1 -0
  111. package/dist/serialization/MsgPackSerializer.js +242 -0
  112. package/dist/serialization/MsgPackSerializer.js.map +1 -0
  113. package/dist/serialization/NumpyBridge.d.ts +96 -0
  114. package/dist/serialization/NumpyBridge.d.ts.map +1 -0
  115. package/dist/serialization/NumpyBridge.js +323 -0
  116. package/dist/serialization/NumpyBridge.js.map +1 -0
  117. package/dist/serialization/Serializer.d.ts +78 -0
  118. package/dist/serialization/Serializer.d.ts.map +1 -0
  119. package/dist/serialization/Serializer.js +281 -0
  120. package/dist/serialization/Serializer.js.map +1 -0
  121. package/dist/types/addon.d.ts +131 -0
  122. package/dist/types/addon.d.ts.map +1 -0
  123. package/dist/types/addon.js +32 -0
  124. package/dist/types/addon.js.map +1 -0
  125. package/dist/types/config.d.ts +233 -0
  126. package/dist/types/config.d.ts.map +1 -0
  127. package/dist/types/config.js +60 -0
  128. package/dist/types/config.js.map +1 -0
  129. package/dist/types/index.d.ts +10 -0
  130. package/dist/types/index.d.ts.map +1 -0
  131. package/dist/types/index.js +12 -0
  132. package/dist/types/index.js.map +1 -0
  133. package/dist/types/python.d.ts +235 -0
  134. package/dist/types/python.d.ts.map +1 -0
  135. package/dist/types/python.js +7 -0
  136. package/dist/types/python.js.map +1 -0
  137. package/dist/utils/ErrorTranslator.d.ts +83 -0
  138. package/dist/utils/ErrorTranslator.d.ts.map +1 -0
  139. package/dist/utils/ErrorTranslator.js +210 -0
  140. package/dist/utils/ErrorTranslator.js.map +1 -0
  141. package/dist/utils/Locking.d.ts +3 -0
  142. package/dist/utils/Locking.d.ts.map +1 -0
  143. package/dist/utils/Locking.js +10 -0
  144. package/dist/utils/Locking.js.map +1 -0
  145. package/dist/utils/Logger.d.ts +27 -0
  146. package/dist/utils/Logger.d.ts.map +1 -0
  147. package/dist/utils/Logger.js +115 -0
  148. package/dist/utils/Logger.js.map +1 -0
  149. package/dist/utils/MemoryMonitor.d.ts +43 -0
  150. package/dist/utils/MemoryMonitor.d.ts.map +1 -0
  151. package/dist/utils/MemoryMonitor.js +143 -0
  152. package/dist/utils/MemoryMonitor.js.map +1 -0
  153. package/package.json +114 -4
  154. package/python/ast_inspector.py +248 -0
  155. package/python/error_handler.py +432 -0
  156. package/python/isolated_worker.py +94 -0
  157. package/python/pynect_dispatcher.py +382 -0
  158. package/python/pynect_runtime.py +574 -0
  159. package/python/serializer.py +373 -0
  160. package/python/type_inspector.py +315 -0
  161. package/scripts/build-native.js +50 -0
  162. package/scripts/cli.js +21 -0
  163. package/scripts/ensure-native.js +85 -0
  164. package/scripts/postinstall.js +40 -0
  165. package/scripts/pyfig.js +113 -0
  166. package/scripts/python-provisioner.js +23 -0
  167. package/scripts/smoke-python-boundary.js +103 -0
  168. package/src/native/NativeAddonLoader.ts +98 -0
  169. package/src/native/gil_guard.cpp +25 -0
  170. package/src/native/gil_guard.h +174 -0
  171. package/src/native/pynect_addon.cpp +942 -0
  172. package/src/native/python_bridge.cpp +904 -0
  173. package/src/native/python_bridge.h +263 -0
  174. package/src/native/thread_pool.cpp +375 -0
  175. package/src/native/thread_pool.h +185 -0
  176. package/src/native/type_converter.cpp +906 -0
  177. package/src/native/type_converter.h +271 -0
@@ -0,0 +1,174 @@
1
+ /**
2
+ * pynect - GIL Guard Header
3
+ * RAII wrappers for the Python Global Interpreter Lock (GIL).
4
+ *
5
+ * The GIL ensures only one thread executes Python bytecode at a time.
6
+ * These guards make GIL management safe via RAII idiom.
7
+ */
8
+
9
+ #pragma once
10
+
11
+ #include <Python.h>
12
+ #include <stdexcept>
13
+
14
+ namespace pynect {
15
+
16
+ /**
17
+ * GILAcquire - RAII guard that acquires the GIL on construction
18
+ * and releases it on destruction.
19
+ *
20
+ * Use when Python code needs to run in a non-Python thread (e.g. a worker thread).
21
+ * The calling thread must NOT already hold the GIL.
22
+ *
23
+ * @example
24
+ * ```cpp
25
+ * void worker_thread_func() {
26
+ * GILAcquire gil; // GIL acquired
27
+ * PyObject* result = PyEval_EvalCode(...);
28
+ * // GIL released when gil goes out of scope
29
+ * }
30
+ * ```
31
+ */
32
+ class GILAcquire {
33
+ public:
34
+ GILAcquire() noexcept : _state(PyGILState_Ensure()) {}
35
+ ~GILAcquire() noexcept { PyGILState_Release(_state); }
36
+
37
+ // Non-copyable, non-movable
38
+ GILAcquire(const GILAcquire&) = delete;
39
+ GILAcquire& operator=(const GILAcquire&) = delete;
40
+ GILAcquire(GILAcquire&&) = delete;
41
+ GILAcquire& operator=(GILAcquire&&) = delete;
42
+
43
+ private:
44
+ PyGILState_STATE _state;
45
+ };
46
+
47
+ /**
48
+ * GILRelease - RAII guard that releases the GIL on construction
49
+ * and re-acquires it on destruction.
50
+ *
51
+ * Use to temporarily release the GIL while performing blocking I/O or
52
+ * other operations that don't need Python, allowing other Python threads to run.
53
+ * The calling thread MUST already hold the GIL.
54
+ *
55
+ * @example
56
+ * ```cpp
57
+ * // Inside Python-holding code:
58
+ * {
59
+ * GILRelease release; // GIL released - other Python threads can run
60
+ * perform_blocking_io();
61
+ * } // GIL re-acquired here
62
+ * ```
63
+ */
64
+ class GILRelease {
65
+ public:
66
+ GILRelease() noexcept : _state(PyEval_SaveThread()) {}
67
+ ~GILRelease() noexcept { PyEval_RestoreThread(_state); }
68
+
69
+ // Non-copyable, non-movable
70
+ GILRelease(const GILRelease&) = delete;
71
+ GILRelease& operator=(const GILRelease&) = delete;
72
+ GILRelease(GILRelease&&) = delete;
73
+ GILRelease& operator=(GILRelease&&) = delete;
74
+
75
+ private:
76
+ PyThreadState* _state;
77
+ };
78
+
79
+ /**
80
+ * PyRef - RAII wrapper for PyObject* reference counting.
81
+ *
82
+ * Automatically calls Py_XDECREF on destruction.
83
+ * Use steal() for objects returned from Python C API with new references.
84
+ * Use borrow() for borrowed references (won't decref).
85
+ */
86
+ class PyRef {
87
+ public:
88
+ PyRef() noexcept : _obj(nullptr), _owned(false) {}
89
+
90
+ ~PyRef() noexcept {
91
+ reset();
92
+ }
93
+
94
+ /** Take ownership of an object (new reference from Python API) */
95
+ static PyRef steal(PyObject* obj) noexcept {
96
+ PyRef ref;
97
+ ref._obj = obj;
98
+ ref._owned = true;
99
+ return ref;
100
+ }
101
+
102
+ /** Borrow a reference (will Py_INCREF and Py_DECREF) */
103
+ static PyRef borrow(PyObject* obj) noexcept {
104
+ PyRef ref;
105
+ ref._obj = obj;
106
+ ref._owned = false;
107
+ if (obj) {
108
+ Py_INCREF(obj);
109
+ ref._owned = true;
110
+ }
111
+ return ref;
112
+ }
113
+
114
+ /** Increment reference count and get raw pointer */
115
+ PyObject* incref() const noexcept {
116
+ Py_XINCREF(_obj);
117
+ return _obj;
118
+ }
119
+
120
+ /** Get raw pointer without changing reference count */
121
+ PyObject* get() const noexcept { return _obj; }
122
+
123
+ /** Release ownership without decrementing ref count */
124
+ PyObject* release() noexcept {
125
+ PyObject* obj = _obj;
126
+ _obj = nullptr;
127
+ _owned = false;
128
+ return obj;
129
+ }
130
+
131
+ /** Reset - decrements ref count if owned */
132
+ void reset() noexcept {
133
+ if (_owned && _obj) {
134
+ Py_DECREF(_obj);
135
+ }
136
+ _obj = nullptr;
137
+ _owned = false;
138
+ }
139
+
140
+ /** Check if the object is valid (non-null) */
141
+ explicit operator bool() const noexcept { return _obj != nullptr; }
142
+
143
+ /** Check for Python exception state */
144
+ bool hasException() const noexcept {
145
+ return _obj == nullptr && PyErr_Occurred() != nullptr;
146
+ }
147
+
148
+ // Non-copyable
149
+ PyRef(const PyRef&) = delete;
150
+ PyRef& operator=(const PyRef&) = delete;
151
+
152
+ // Movable
153
+ PyRef(PyRef&& other) noexcept : _obj(other._obj), _owned(other._owned) {
154
+ other._obj = nullptr;
155
+ other._owned = false;
156
+ }
157
+
158
+ PyRef& operator=(PyRef&& other) noexcept {
159
+ if (this != &other) {
160
+ reset();
161
+ _obj = other._obj;
162
+ _owned = other._owned;
163
+ other._obj = nullptr;
164
+ other._owned = false;
165
+ }
166
+ return *this;
167
+ }
168
+
169
+ private:
170
+ PyObject* _obj;
171
+ bool _owned;
172
+ };
173
+
174
+ } // namespace pynect