vools 0.2.1__tar.gz → 0.2.2__tar.gz

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 (349) hide show
  1. {vools-0.2.1/vools.egg-info → vools-0.2.2}/PKG-INFO +1 -1
  2. {vools-0.2.1 → vools-0.2.2}/vools/__init__.py +1 -1
  3. {vools-0.2.1 → vools-0.2.2}/vools/bridge/_base.py +2 -2
  4. {vools-0.2.1 → vools-0.2.2}/vools/bridge/core/sigcache.py +106 -50
  5. {vools-0.2.1 → vools-0.2.2}/vools/bridge/freebasic/transport.py +6 -1
  6. {vools-0.2.1 → vools-0.2.2}/vools/bridge/manager.py +3 -1
  7. {vools-0.2.1 → vools-0.2.2}/vools/bridge/zig/compiler.py +1 -1
  8. vools-0.2.2/vools/core/asyncio_compat.py +122 -0
  9. {vools-0.2.1 → vools-0.2.2}/vools/core/dataclass_compat.py +16 -3
  10. vools-0.2.2/vools/core/datetime_compat.py +180 -0
  11. vools-0.2.2/vools/core/inspect_compat.py +50 -0
  12. {vools-0.2.1 → vools-0.2.2}/vools/datetime/__init__.py +9 -1
  13. {vools-0.2.1 → vools-0.2.2}/vools/decorators/__init__.py +9 -1
  14. {vools-0.2.1 → vools-0.2.2}/vools/reactive/core/schedulers.py +1 -1
  15. {vools-0.2.1 → vools-0.2.2}/vools/reactive/operators/extended_operators.py +7 -6
  16. {vools-0.2.1 → vools-0.2.2}/vools/reactive/operators/operators.py +3 -2
  17. {vools-0.2.1 → vools-0.2.2}/vools/security/safe_eval.py +9 -0
  18. {vools-0.2.1 → vools-0.2.2}/vools/serialize/codec.py +9 -4
  19. {vools-0.2.1 → vools-0.2.2}/vools/serialize/type_registry.py +5 -3
  20. {vools-0.2.1 → vools-0.2.2}/vools/task/core/models.py +6 -5
  21. {vools-0.2.1 → vools-0.2.2}/vools/task/core/storage.py +18 -10
  22. {vools-0.2.1 → vools-0.2.2/vools.egg-info}/PKG-INFO +1 -1
  23. {vools-0.2.1 → vools-0.2.2}/vools.egg-info/SOURCES.txt +3 -29
  24. vools-0.2.1/tests/benchmark_curry.py +0 -179
  25. vools-0.2.1/tests/benchmark_curry_optimized.py +0 -226
  26. vools-0.2.1/tests/benchmark_modules.py +0 -190
  27. vools-0.2.1/tests/benchmark_placeholder.py +0 -176
  28. vools-0.2.1/tests/benchmark_reactive.py +0 -176
  29. vools-0.2.1/tests/benchmark_signature_cache.py +0 -230
  30. vools-0.2.1/tests/compare_rxpy_vools.py +0 -190
  31. vools-0.2.1/tests/compare_with_rx_spec.py +0 -251
  32. vools-0.2.1/tests/debug_curry.py +0 -26
  33. vools-0.2.1/tests/explore_rxpy_api.py +0 -180
  34. vools-0.2.1/tests/test_box.py +0 -238
  35. vools-0.2.1/tests/test_crypto.py +0 -153
  36. vools-0.2.1/tests/test_csharp_bridge.py +0 -258
  37. vools-0.2.1/tests/test_curried_performance.py +0 -316
  38. vools-0.2.1/tests/test_do.py +0 -41
  39. vools-0.2.1/tests/test_encoding.py +0 -111
  40. vools-0.2.1/tests/test_functional.py +0 -231
  41. vools-0.2.1/tests/test_functional_simple.py +0 -231
  42. vools-0.2.1/tests/test_import.py +0 -26
  43. vools-0.2.1/tests/test_itor.py +0 -662
  44. vools-0.2.1/tests/test_main_import.py +0 -70
  45. vools-0.2.1/tests/test_new_features.py +0 -68
  46. vools-0.2.1/tests/test_r_bridge.py +0 -399
  47. vools-0.2.1/tests/test_rust_async.py +0 -146
  48. vools-0.2.1/tests/test_rust_async_quick.py +0 -139
  49. vools-0.2.1/tests/test_rust_decorator.py +0 -246
  50. vools-0.2.1/tests/test_stuff.py +0 -165
  51. vools-0.2.1/tests/test_vools.py +0 -181
  52. vools-0.2.1/vools/utils/asyncio_compat.py +0 -91
  53. {vools-0.2.1 → vools-0.2.2}/LICENSE +0 -0
  54. {vools-0.2.1 → vools-0.2.2}/NOTICE +0 -0
  55. {vools-0.2.1 → vools-0.2.2}/README.md +0 -0
  56. {vools-0.2.1 → vools-0.2.2}/autopypi/__init__.py +0 -0
  57. {vools-0.2.1 → vools-0.2.2}/autopypi/config.py +0 -0
  58. {vools-0.2.1 → vools-0.2.2}/autopypi/environment.py +0 -0
  59. {vools-0.2.1 → vools-0.2.2}/autopypi/fabfile.py +0 -0
  60. {vools-0.2.1 → vools-0.2.2}/autopypi/logger.py +0 -0
  61. {vools-0.2.1 → vools-0.2.2}/autopypi/packaging.py +0 -0
  62. {vools-0.2.1 → vools-0.2.2}/autopypi/publishing.py +0 -0
  63. {vools-0.2.1 → vools-0.2.2}/autopypi/release.py +0 -0
  64. {vools-0.2.1 → vools-0.2.2}/autopypi/versioning.py +0 -0
  65. {vools-0.2.1 → vools-0.2.2}/pyproject.toml +0 -0
  66. {vools-0.2.1 → vools-0.2.2}/setup.cfg +0 -0
  67. {vools-0.2.1 → vools-0.2.2}/tests/__init__.py +0 -0
  68. {vools-0.2.1 → vools-0.2.2}/tests/_serialize_helpers.py +0 -0
  69. {vools-0.2.1 → vools-0.2.2}/tests/conftest.py +0 -0
  70. {vools-0.2.1 → vools-0.2.2}/tests/test_functions.py +0 -0
  71. {vools-0.2.1 → vools-0.2.2}/vools/README.md +0 -0
  72. {vools-0.2.1 → vools-0.2.2}/vools/__main__.py +0 -0
  73. {vools-0.2.1 → vools-0.2.2}/vools/_logging.py +0 -0
  74. {vools-0.2.1 → vools-0.2.2}/vools/_nim_crypto.py +0 -0
  75. {vools-0.2.1 → vools-0.2.2}/vools/_nim_curried.py +0 -0
  76. {vools-0.2.1 → vools-0.2.2}/vools/_nim_datetime.py +0 -0
  77. {vools-0.2.1 → vools-0.2.2}/vools/_nim_encoding.py +0 -0
  78. {vools-0.2.1 → vools-0.2.2}/vools/_nim_loader.py +0 -0
  79. {vools-0.2.1 → vools-0.2.2}/vools/_nim_seq.py +0 -0
  80. {vools-0.2.1 → vools-0.2.2}/vools/api/__init__.py +0 -0
  81. {vools-0.2.1 → vools-0.2.2}/vools/api/curry_cmd.py +0 -0
  82. {vools-0.2.1 → vools-0.2.2}/vools/api/memoize_cmd.py +0 -0
  83. {vools-0.2.1 → vools-0.2.2}/vools/api/ops_cmd.py +0 -0
  84. {vools-0.2.1 → vools-0.2.2}/vools/api/seq_cmd.py +0 -0
  85. {vools-0.2.1 → vools-0.2.2}/vools/api/typer_app.py +0 -0
  86. {vools-0.2.1 → vools-0.2.2}/vools/bridge/__init__.py +0 -0
  87. {vools-0.2.1 → vools-0.2.2}/vools/bridge/_examples.py +0 -0
  88. {vools-0.2.1 → vools-0.2.2}/vools/bridge/c/__init__.py +0 -0
  89. {vools-0.2.1 → vools-0.2.2}/vools/bridge/cangjie/__init__.py +0 -0
  90. {vools-0.2.1 → vools-0.2.2}/vools/bridge/cangjie/compiler.py +0 -0
  91. {vools-0.2.1 → vools-0.2.2}/vools/bridge/cangjie/loader.py +0 -0
  92. {vools-0.2.1 → vools-0.2.2}/vools/bridge/cangjie/templates.py +0 -0
  93. {vools-0.2.1 → vools-0.2.2}/vools/bridge/cangjie/types.py +0 -0
  94. {vools-0.2.1 → vools-0.2.2}/vools/bridge/core/__init__.py +0 -0
  95. {vools-0.2.1 → vools-0.2.2}/vools/bridge/core/decorators.py +0 -0
  96. {vools-0.2.1 → vools-0.2.2}/vools/bridge/core/loader.py +0 -0
  97. {vools-0.2.1 → vools-0.2.2}/vools/bridge/core/serialization.py +0 -0
  98. {vools-0.2.1 → vools-0.2.2}/vools/bridge/core/types.py +0 -0
  99. {vools-0.2.1 → vools-0.2.2}/vools/bridge/cpp/__init__.py +0 -0
  100. {vools-0.2.1 → vools-0.2.2}/vools/bridge/csharp/__init__.py +0 -0
  101. {vools-0.2.1 → vools-0.2.2}/vools/bridge/csharp/compiler.py +0 -0
  102. {vools-0.2.1 → vools-0.2.2}/vools/bridge/csharp/loader.py +0 -0
  103. {vools-0.2.1 → vools-0.2.2}/vools/bridge/csharp/templates.py +0 -0
  104. {vools-0.2.1 → vools-0.2.2}/vools/bridge/csharp/types.py +0 -0
  105. {vools-0.2.1 → vools-0.2.2}/vools/bridge/dart/__init__.py +0 -0
  106. {vools-0.2.1 → vools-0.2.2}/vools/bridge/dart/compiler.py +0 -0
  107. {vools-0.2.1 → vools-0.2.2}/vools/bridge/dart/types.py +0 -0
  108. {vools-0.2.1 → vools-0.2.2}/vools/bridge/freebasic/__init__.py +0 -0
  109. {vools-0.2.1 → vools-0.2.2}/vools/bridge/freebasic/compiler.py +0 -0
  110. {vools-0.2.1 → vools-0.2.2}/vools/bridge/freebasic/loader.py +0 -0
  111. {vools-0.2.1 → vools-0.2.2}/vools/bridge/freebasic/types.py +0 -0
  112. {vools-0.2.1 → vools-0.2.2}/vools/bridge/go/__init__.py +0 -0
  113. {vools-0.2.1 → vools-0.2.2}/vools/bridge/go/compiler.py +0 -0
  114. {vools-0.2.1 → vools-0.2.2}/vools/bridge/java/__init__.py +0 -0
  115. {vools-0.2.1 → vools-0.2.2}/vools/bridge/java/compiler.py +0 -0
  116. {vools-0.2.1 → vools-0.2.2}/vools/bridge/java/decorator.py +0 -0
  117. {vools-0.2.1 → vools-0.2.2}/vools/bridge/java/loader.py +0 -0
  118. {vools-0.2.1 → vools-0.2.2}/vools/bridge/java/types.py +0 -0
  119. {vools-0.2.1 → vools-0.2.2}/vools/bridge/julia/__init__.py +0 -0
  120. {vools-0.2.1 → vools-0.2.2}/vools/bridge/julia/_loader.py +0 -0
  121. {vools-0.2.1 → vools-0.2.2}/vools/bridge/julia/compiler.py +0 -0
  122. {vools-0.2.1 → vools-0.2.2}/vools/bridge/julia/decorator.py +0 -0
  123. {vools-0.2.1 → vools-0.2.2}/vools/bridge/julia/templates.py +0 -0
  124. {vools-0.2.1 → vools-0.2.2}/vools/bridge/julia/types.py +0 -0
  125. {vools-0.2.1 → vools-0.2.2}/vools/bridge/kotlin/__init__.py +0 -0
  126. {vools-0.2.1 → vools-0.2.2}/vools/bridge/kotlin/compiler.py +0 -0
  127. {vools-0.2.1 → vools-0.2.2}/vools/bridge/kotlin/types.py +0 -0
  128. {vools-0.2.1 → vools-0.2.2}/vools/bridge/lua/__init__.py +0 -0
  129. {vools-0.2.1 → vools-0.2.2}/vools/bridge/lua/compiler.py +0 -0
  130. {vools-0.2.1 → vools-0.2.2}/vools/bridge/lua/types.py +0 -0
  131. {vools-0.2.1 → vools-0.2.2}/vools/bridge/mojo/__init__.py +0 -0
  132. {vools-0.2.1 → vools-0.2.2}/vools/bridge/mojo/compiler.py +0 -0
  133. {vools-0.2.1 → vools-0.2.2}/vools/bridge/mojo/loader.py +0 -0
  134. {vools-0.2.1 → vools-0.2.2}/vools/bridge/mojo/templates.py +0 -0
  135. {vools-0.2.1 → vools-0.2.2}/vools/bridge/mojo/transport.py +0 -0
  136. {vools-0.2.1 → vools-0.2.2}/vools/bridge/mojo/types.py +0 -0
  137. {vools-0.2.1 → vools-0.2.2}/vools/bridge/moonbit/__init__.py +0 -0
  138. {vools-0.2.1 → vools-0.2.2}/vools/bridge/moonbit/compiler.py +0 -0
  139. {vools-0.2.1 → vools-0.2.2}/vools/bridge/moonbit/types.py +0 -0
  140. {vools-0.2.1 → vools-0.2.2}/vools/bridge/nim/__init__.py +0 -0
  141. {vools-0.2.1 → vools-0.2.2}/vools/bridge/nim/_loader.py +0 -0
  142. {vools-0.2.1 → vools-0.2.2}/vools/bridge/nim/compiler.py +0 -0
  143. {vools-0.2.1 → vools-0.2.2}/vools/bridge/nim/crypto.py +0 -0
  144. {vools-0.2.1 → vools-0.2.2}/vools/bridge/nim/curried.py +0 -0
  145. {vools-0.2.1 → vools-0.2.2}/vools/bridge/nim/datetime.py +0 -0
  146. {vools-0.2.1 → vools-0.2.2}/vools/bridge/nim/encoding.py +0 -0
  147. {vools-0.2.1 → vools-0.2.2}/vools/bridge/nim/seq.py +0 -0
  148. {vools-0.2.1 → vools-0.2.2}/vools/bridge/perl/__init__.py +0 -0
  149. {vools-0.2.1 → vools-0.2.2}/vools/bridge/perl/compiler.py +0 -0
  150. {vools-0.2.1 → vools-0.2.2}/vools/bridge/perl/types.py +0 -0
  151. {vools-0.2.1 → vools-0.2.2}/vools/bridge/php/__init__.py +0 -0
  152. {vools-0.2.1 → vools-0.2.2}/vools/bridge/php/compiler.py +0 -0
  153. {vools-0.2.1 → vools-0.2.2}/vools/bridge/php/types.py +0 -0
  154. {vools-0.2.1 → vools-0.2.2}/vools/bridge/powershell/__init__.py +0 -0
  155. {vools-0.2.1 → vools-0.2.2}/vools/bridge/powershell/compiler.py +0 -0
  156. {vools-0.2.1 → vools-0.2.2}/vools/bridge/powershell/types.py +0 -0
  157. {vools-0.2.1 → vools-0.2.2}/vools/bridge/probe.py +0 -0
  158. {vools-0.2.1 → vools-0.2.2}/vools/bridge/r/__init__.py +0 -0
  159. {vools-0.2.1 → vools-0.2.2}/vools/bridge/r/compiler.py +0 -0
  160. {vools-0.2.1 → vools-0.2.2}/vools/bridge/r/loader.py +0 -0
  161. {vools-0.2.1 → vools-0.2.2}/vools/bridge/r/templates.py +0 -0
  162. {vools-0.2.1 → vools-0.2.2}/vools/bridge/r/types.py +0 -0
  163. {vools-0.2.1 → vools-0.2.2}/vools/bridge/ruby/__init__.py +0 -0
  164. {vools-0.2.1 → vools-0.2.2}/vools/bridge/ruby/compiler.py +0 -0
  165. {vools-0.2.1 → vools-0.2.2}/vools/bridge/rust/__init__.py +0 -0
  166. {vools-0.2.1 → vools-0.2.2}/vools/bridge/rust/_loader.py +0 -0
  167. {vools-0.2.1 → vools-0.2.2}/vools/bridge/rust/compiler.py +0 -0
  168. {vools-0.2.1 → vools-0.2.2}/vools/bridge/rust/decorator.py +0 -0
  169. {vools-0.2.1 → vools-0.2.2}/vools/bridge/rust/templates.py +0 -0
  170. {vools-0.2.1 → vools-0.2.2}/vools/bridge/rust/types.py +0 -0
  171. {vools-0.2.1 → vools-0.2.2}/vools/bridge/scala/__init__.py +0 -0
  172. {vools-0.2.1 → vools-0.2.2}/vools/bridge/scala/compiler.py +0 -0
  173. {vools-0.2.1 → vools-0.2.2}/vools/bridge/scala/decorator.py +0 -0
  174. {vools-0.2.1 → vools-0.2.2}/vools/bridge/scala/loader.py +0 -0
  175. {vools-0.2.1 → vools-0.2.2}/vools/bridge/scala/types.py +0 -0
  176. {vools-0.2.1 → vools-0.2.2}/vools/bridge/scala/utils.py +0 -0
  177. {vools-0.2.1 → vools-0.2.2}/vools/bridge/shell/__init__.py +0 -0
  178. {vools-0.2.1 → vools-0.2.2}/vools/bridge/shell/compiler.py +0 -0
  179. {vools-0.2.1 → vools-0.2.2}/vools/bridge/shell/types.py +0 -0
  180. {vools-0.2.1 → vools-0.2.2}/vools/bridge/swift/__init__.py +0 -0
  181. {vools-0.2.1 → vools-0.2.2}/vools/bridge/swift/compiler.py +0 -0
  182. {vools-0.2.1 → vools-0.2.2}/vools/bridge/swift/types.py +0 -0
  183. {vools-0.2.1 → vools-0.2.2}/vools/bridge/typescript/__init__.py +0 -0
  184. {vools-0.2.1 → vools-0.2.2}/vools/bridge/typescript/compiler.py +0 -0
  185. {vools-0.2.1 → vools-0.2.2}/vools/bridge/vbnet/__init__.py +0 -0
  186. {vools-0.2.1 → vools-0.2.2}/vools/bridge/vbnet/compiler.py +0 -0
  187. {vools-0.2.1 → vools-0.2.2}/vools/bridge/vbnet/templates.py +0 -0
  188. {vools-0.2.1 → vools-0.2.2}/vools/bridge/vbnet/types.py +0 -0
  189. {vools-0.2.1 → vools-0.2.2}/vools/bridge/vbscript/__init__.py +0 -0
  190. {vools-0.2.1 → vools-0.2.2}/vools/bridge/vbscript/compiler.py +0 -0
  191. {vools-0.2.1 → vools-0.2.2}/vools/bridge/vbscript/types.py +0 -0
  192. {vools-0.2.1 → vools-0.2.2}/vools/bridge/zig/__init__.py +0 -0
  193. {vools-0.2.1 → vools-0.2.2}/vools/bridge/zig/types.py +0 -0
  194. {vools-0.2.1 → vools-0.2.2}/vools/cache/__init__.py +0 -0
  195. {vools-0.2.1 → vools-0.2.2}/vools/cache/memorize.py +0 -0
  196. {vools-0.2.1 → vools-0.2.2}/vools/cache/once.py +0 -0
  197. {vools-0.2.1 → vools-0.2.2}/vools/cache/persist.py +0 -0
  198. {vools-0.2.1 → vools-0.2.2}/vools/cache/sigcache.py +0 -0
  199. {vools-0.2.1 → vools-0.2.2}/vools/config.py +0 -0
  200. {vools-0.2.1 → vools-0.2.2}/vools/config.template.py +0 -0
  201. {vools-0.2.1 → vools-0.2.2}/vools/core/__init__.py +0 -0
  202. {vools-0.2.1 → vools-0.2.2}/vools/core/base.py +0 -0
  203. {vools-0.2.1 → vools-0.2.2}/vools/core/config.py +0 -0
  204. {vools-0.2.1 → vools-0.2.2}/vools/core/exceptions.py +0 -0
  205. {vools-0.2.1 → vools-0.2.2}/vools/crypto/__init__.py +0 -0
  206. {vools-0.2.1 → vools-0.2.2}/vools/crypto/core.py +0 -0
  207. {vools-0.2.1 → vools-0.2.2}/vools/curried/__init__.py +0 -0
  208. {vools-0.2.1 → vools-0.2.2}/vools/curried/collection.py +0 -0
  209. {vools-0.2.1 → vools-0.2.2}/vools/curried/composition.py +0 -0
  210. {vools-0.2.1 → vools-0.2.2}/vools/curried/core.py +0 -0
  211. {vools-0.2.1 → vools-0.2.2}/vools/curried/iteration.py +0 -0
  212. {vools-0.2.1 → vools-0.2.2}/vools/curried/math.py +0 -0
  213. {vools-0.2.1 → vools-0.2.2}/vools/curried/predicate.py +0 -0
  214. {vools-0.2.1 → vools-0.2.2}/vools/curried/string.py +0 -0
  215. {vools-0.2.1 → vools-0.2.2}/vools/data/__init__.py +0 -0
  216. {vools-0.2.1 → vools-0.2.2}/vools/data/itor.py +0 -0
  217. {vools-0.2.1 → vools-0.2.2}/vools/data/seq.py +0 -0
  218. {vools-0.2.1 → vools-0.2.2}/vools/data/vlist.py +0 -0
  219. {vools-0.2.1 → vools-0.2.2}/vools/data/vtext.py +0 -0
  220. {vools-0.2.1 → vools-0.2.2}/vools/datetime/dates_format.py +0 -0
  221. {vools-0.2.1 → vools-0.2.2}/vools/datetime/utils.py +0 -0
  222. {vools-0.2.1 → vools-0.2.2}/vools/datetime/vdate_class.py +0 -0
  223. {vools-0.2.1 → vools-0.2.2}/vools/decorators/cache.py +0 -0
  224. {vools-0.2.1 → vools-0.2.2}/vools/decorators/control.py +0 -0
  225. {vools-0.2.1 → vools-0.2.2}/vools/decorators/curried.py +0 -0
  226. {vools-0.2.1 → vools-0.2.2}/vools/decorators/curry_core.py +0 -0
  227. {vools-0.2.1 → vools-0.2.2}/vools/decorators/curry_decorator.py +0 -0
  228. {vools-0.2.1 → vools-0.2.2}/vools/decorators/curry_delay.py +0 -0
  229. {vools-0.2.1 → vools-0.2.2}/vools/decorators/lazy.py +0 -0
  230. {vools-0.2.1 → vools-0.2.2}/vools/decorators/overcurry.py +0 -0
  231. {vools-0.2.1 → vools-0.2.2}/vools/decorators/overload.py +0 -0
  232. {vools-0.2.1 → vools-0.2.2}/vools/decorators/overloads.py +0 -0
  233. {vools-0.2.1 → vools-0.2.2}/vools/decorators/rself.py +0 -0
  234. {vools-0.2.1 → vools-0.2.2}/vools/decorators/selector.py +0 -0
  235. {vools-0.2.1 → vools-0.2.2}/vools/decorators/shotcut.py +0 -0
  236. {vools-0.2.1 → vools-0.2.2}/vools/decorators/trd.py +0 -0
  237. {vools-0.2.1 → vools-0.2.2}/vools/encoding/__init__.py +0 -0
  238. {vools-0.2.1 → vools-0.2.2}/vools/encoding/core.py +0 -0
  239. {vools-0.2.1 → vools-0.2.2}/vools/functional/__init__.py +0 -0
  240. {vools-0.2.1 → vools-0.2.2}/vools/functional/arrow_func.py +0 -0
  241. {vools-0.2.1 → vools-0.2.2}/vools/functional/box.py +0 -0
  242. {vools-0.2.1 → vools-0.2.2}/vools/functional/funcs.py +0 -0
  243. {vools-0.2.1 → vools-0.2.2}/vools/functional/iif.py +0 -0
  244. {vools-0.2.1 → vools-0.2.2}/vools/functional/pipe_ops.py +0 -0
  245. {vools-0.2.1 → vools-0.2.2}/vools/functional/placeholder.py +0 -0
  246. {vools-0.2.1 → vools-0.2.2}/vools/functional/placeholder_impl.py +0 -0
  247. {vools-0.2.1 → vools-0.2.2}/vools/functional/result.py +0 -0
  248. {vools-0.2.1 → vools-0.2.2}/vools/lib/libgcc_s_seh-1.dll +0 -0
  249. {vools-0.2.1 → vools-0.2.2}/vools/lib/libstdc++-6.dll +0 -0
  250. {vools-0.2.1 → vools-0.2.2}/vools/lib/libwinpthread-1.dll +0 -0
  251. {vools-0.2.1 → vools-0.2.2}/vools/lib/linux/libvools_crypto.so +0 -0
  252. {vools-0.2.1 → vools-0.2.2}/vools/lib/linux/libvools_curried.so +0 -0
  253. {vools-0.2.1 → vools-0.2.2}/vools/lib/linux/libvools_datetime.so +0 -0
  254. {vools-0.2.1 → vools-0.2.2}/vools/lib/linux/libvools_encoding.so +0 -0
  255. {vools-0.2.1 → vools-0.2.2}/vools/lib/linux/libvools_seq.so +0 -0
  256. {vools-0.2.1 → vools-0.2.2}/vools/lib/vools_crypto.dll +0 -0
  257. {vools-0.2.1 → vools-0.2.2}/vools/lib/vools_curried.dll +0 -0
  258. {vools-0.2.1 → vools-0.2.2}/vools/lib/vools_datetime.dll +0 -0
  259. {vools-0.2.1 → vools-0.2.2}/vools/lib/vools_encoding.dll +0 -0
  260. {vools-0.2.1 → vools-0.2.2}/vools/lib/vools_seq.dll +0 -0
  261. {vools-0.2.1 → vools-0.2.2}/vools/oop/__init__.py +0 -0
  262. {vools-0.2.1 → vools-0.2.2}/vools/oop/calltype.py +0 -0
  263. {vools-0.2.1 → vools-0.2.2}/vools/oop/extend.py +0 -0
  264. {vools-0.2.1 → vools-0.2.2}/vools/oop/fusion.py +0 -0
  265. {vools-0.2.1 → vools-0.2.2}/vools/oop/method_extend.py +0 -0
  266. {vools-0.2.1 → vools-0.2.2}/vools/oop/mixer.py +0 -0
  267. {vools-0.2.1 → vools-0.2.2}/vools/oop/selector.py +0 -0
  268. {vools-0.2.1 → vools-0.2.2}/vools/reactive/__init__.py +0 -0
  269. {vools-0.2.1 → vools-0.2.2}/vools/reactive/core/__init__.py +0 -0
  270. {vools-0.2.1 → vools-0.2.2}/vools/reactive/core/connectable.py +0 -0
  271. {vools-0.2.1 → vools-0.2.2}/vools/reactive/core/object_pool.py +0 -0
  272. {vools-0.2.1 → vools-0.2.2}/vools/reactive/core/observable.py +0 -0
  273. {vools-0.2.1 → vools-0.2.2}/vools/reactive/core/subject.py +0 -0
  274. {vools-0.2.1 → vools-0.2.2}/vools/reactive/monitoring/__init__.py +0 -0
  275. {vools-0.2.1 → vools-0.2.2}/vools/reactive/monitoring/_monitoring.py +0 -0
  276. {vools-0.2.1 → vools-0.2.2}/vools/reactive/monitoring/clipboard.py +0 -0
  277. {vools-0.2.1 → vools-0.2.2}/vools/reactive/monitoring/file_watcher.py +0 -0
  278. {vools-0.2.1 → vools-0.2.2}/vools/reactive/monitoring/folder_watcher.py +0 -0
  279. {vools-0.2.1 → vools-0.2.2}/vools/reactive/monitoring/keyboard.py +0 -0
  280. {vools-0.2.1 → vools-0.2.2}/vools/reactive/monitoring/monitor_observer.py +0 -0
  281. {vools-0.2.1 → vools-0.2.2}/vools/reactive/monitoring/monitor_subject.py +0 -0
  282. {vools-0.2.1 → vools-0.2.2}/vools/reactive/monitoring/mouse.py +0 -0
  283. {vools-0.2.1 → vools-0.2.2}/vools/reactive/operators/__init__.py +0 -0
  284. {vools-0.2.1 → vools-0.2.2}/vools/reactive/operators/monitor_operators.py +0 -0
  285. {vools-0.2.1 → vools-0.2.2}/vools/reactive/operators/stats_operators.py +0 -0
  286. {vools-0.2.1 → vools-0.2.2}/vools/security/__init__.py +0 -0
  287. {vools-0.2.1 → vools-0.2.2}/vools/security/_constants.py +0 -0
  288. {vools-0.2.1 → vools-0.2.2}/vools/security/expression_handler.py +0 -0
  289. {vools-0.2.1 → vools-0.2.2}/vools/serialize/__init__.py +0 -0
  290. {vools-0.2.1 → vools-0.2.2}/vools/serialize/backends/__init__.py +0 -0
  291. {vools-0.2.1 → vools-0.2.2}/vools/serialize/backends/base.py +0 -0
  292. {vools-0.2.1 → vools-0.2.2}/vools/serialize/backends/json_backend.py +0 -0
  293. {vools-0.2.1 → vools-0.2.2}/vools/serialize/backends/msgpack_backend.py +0 -0
  294. {vools-0.2.1 → vools-0.2.2}/vools/serialize/backends/pickle_backend.py +0 -0
  295. {vools-0.2.1 → vools-0.2.2}/vools/serialize/callable/__init__.py +0 -0
  296. {vools-0.2.1 → vools-0.2.2}/vools/serialize/callable/decorator_handler.py +0 -0
  297. {vools-0.2.1 → vools-0.2.2}/vools/serialize/callable/functional_handler.py +0 -0
  298. {vools-0.2.1 → vools-0.2.2}/vools/serialize/config.py +0 -0
  299. {vools-0.2.1 → vools-0.2.2}/vools/serialize/context.py +0 -0
  300. {vools-0.2.1 → vools-0.2.2}/vools/serialize/core.py +0 -0
  301. {vools-0.2.1 → vools-0.2.2}/vools/serialize/decorators.py +0 -0
  302. {vools-0.2.1 → vools-0.2.2}/vools/serialize/sentinel.py +0 -0
  303. {vools-0.2.1 → vools-0.2.2}/vools/sql/__init__.py +0 -0
  304. {vools-0.2.1 → vools-0.2.2}/vools/sql/core/__init__.py +0 -0
  305. {vools-0.2.1 → vools-0.2.2}/vools/sql/core/builder.py +0 -0
  306. {vools-0.2.1 → vools-0.2.2}/vools/sql/core/config.py +0 -0
  307. {vools-0.2.1 → vools-0.2.2}/vools/sql/core/connection.py +0 -0
  308. {vools-0.2.1 → vools-0.2.2}/vools/sql/core/decorators.py +0 -0
  309. {vools-0.2.1 → vools-0.2.2}/vools/sql/core/dialect.py +0 -0
  310. {vools-0.2.1 → vools-0.2.2}/vools/sql/core/result.py +0 -0
  311. {vools-0.2.1 → vools-0.2.2}/vools/sql/core/types.py +0 -0
  312. {vools-0.2.1 → vools-0.2.2}/vools/sql/manager.py +0 -0
  313. {vools-0.2.1 → vools-0.2.2}/vools/sql/postgres/__init__.py +0 -0
  314. {vools-0.2.1 → vools-0.2.2}/vools/sql/postgres/connection.py +0 -0
  315. {vools-0.2.1 → vools-0.2.2}/vools/sql/postgres/dialect.py +0 -0
  316. {vools-0.2.1 → vools-0.2.2}/vools/sql/spark/__init__.py +0 -0
  317. {vools-0.2.1 → vools-0.2.2}/vools/sql/spark/connection.py +0 -0
  318. {vools-0.2.1 → vools-0.2.2}/vools/sql/spark/dialect.py +0 -0
  319. {vools-0.2.1 → vools-0.2.2}/vools/sql/spark/scala_bridge.py +0 -0
  320. {vools-0.2.1 → vools-0.2.2}/vools/sql/sqlite/__init__.py +0 -0
  321. {vools-0.2.1 → vools-0.2.2}/vools/sql/sqlite/connection.py +0 -0
  322. {vools-0.2.1 → vools-0.2.2}/vools/sql/sqlite/dialect.py +0 -0
  323. {vools-0.2.1 → vools-0.2.2}/vools/sys/__init__.py +0 -0
  324. {vools-0.2.1 → vools-0.2.2}/vools/sys/compile_cmd.py +0 -0
  325. {vools-0.2.1 → vools-0.2.2}/vools/sys/dll.py +0 -0
  326. {vools-0.2.1 → vools-0.2.2}/vools/sys/dll_cmd.py +0 -0
  327. {vools-0.2.1 → vools-0.2.2}/vools/sys/env_cmd.py +0 -0
  328. {vools-0.2.1 → vools-0.2.2}/vools/sys/exe.py +0 -0
  329. {vools-0.2.1 → vools-0.2.2}/vools/sys/fire_app.py +0 -0
  330. {vools-0.2.1 → vools-0.2.2}/vools/sys/run_cmd.py +0 -0
  331. {vools-0.2.1 → vools-0.2.2}/vools/task/__init__.py +0 -0
  332. {vools-0.2.1 → vools-0.2.2}/vools/task/core/__init__.py +0 -0
  333. {vools-0.2.1 → vools-0.2.2}/vools/task/core/queue.py +0 -0
  334. {vools-0.2.1 → vools-0.2.2}/vools/task/core/worker.py +0 -0
  335. {vools-0.2.1 → vools-0.2.2}/vools/task/decorators/__init__.py +0 -0
  336. {vools-0.2.1 → vools-0.2.2}/vools/task/decorators/task_decorator.py +0 -0
  337. {vools-0.2.1 → vools-0.2.2}/vools/task/rules/__init__.py +0 -0
  338. {vools-0.2.1 → vools-0.2.2}/vools/task/rules/dag.py +0 -0
  339. {vools-0.2.1 → vools-0.2.2}/vools/task/rules/engine.py +0 -0
  340. {vools-0.2.1 → vools-0.2.2}/vools/task/rules/rule.py +0 -0
  341. {vools-0.2.1 → vools-0.2.2}/vools/task/utils/__init__.py +0 -0
  342. {vools-0.2.1 → vools-0.2.2}/vools/utils/__init__.py +0 -0
  343. {vools-0.2.1 → vools-0.2.2}/vools/utils/hoder.py +0 -0
  344. {vools-0.2.1 → vools-0.2.2}/vools/utils/stuff.py +0 -0
  345. {vools-0.2.1 → vools-0.2.2}/vools/utils/tools.py +0 -0
  346. {vools-0.2.1 → vools-0.2.2}/vools.egg-info/dependency_links.txt +0 -0
  347. {vools-0.2.1 → vools-0.2.2}/vools.egg-info/entry_points.txt +0 -0
  348. {vools-0.2.1 → vools-0.2.2}/vools.egg-info/requires.txt +0 -0
  349. {vools-0.2.1 → vools-0.2.2}/vools.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vools
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Python 函数式编程工具集
5
5
  Author-email: Victor <victortop921129@gmail.com>
6
6
  License: Apache License
@@ -7,7 +7,7 @@ vools - Python 函数式编程工具集
7
7
  import importlib
8
8
  from typing import Any
9
9
 
10
- __version__ = "0.2.1"
10
+ __version__ = "0.2.2"
11
11
  __author__ = "Victor"
12
12
  __license__ = "Apache 2.0"
13
13
 
@@ -1,4 +1,4 @@
1
- """
1
+ """
2
2
  vools.bridge._base - 跨语言桥接抽象接口 (Lang Bridge)
3
3
 
4
4
  定义统一的 Lang 接口规范,所有语言桥接模块必须实现此接口。
@@ -59,7 +59,7 @@ from typing import (
59
59
  get_type_hints,
60
60
  )
61
61
  from vools.core.dataclass_compat import dataclass, field
62
- from vools.utils.asyncio_compat import run as asyncio_run
62
+ from vools.core.asyncio_compat import run as asyncio_run
63
63
 
64
64
 
65
65
  # ============================================================================
@@ -19,6 +19,7 @@ vools.bridge.core.sigcache - Bridge 子包签名缓存机制
19
19
 
20
20
  import inspect
21
21
  import logging
22
+ import weakref
22
23
  from collections import OrderedDict
23
24
  from typing import Any, Callable, Dict, Optional, List
24
25
 
@@ -32,6 +33,7 @@ class BridgeSigCache:
32
33
  """Bridge 签名缓存类,每种语言桥接可以有自己的缓存实例。
33
34
 
34
35
  使用 OrderedDict 实现 LRU 淘汰策略,按语言命名空间隔离缓存。
36
+ 使用 weakref 跟踪函数对象生命周期,避免 id 复用导致的缓存错误命中。
35
37
 
36
38
  Attributes:
37
39
  lang: 语言名称,用于标识缓存命名空间。
@@ -51,9 +53,61 @@ class BridgeSigCache:
51
53
  self._annotations_cache: OrderedDict = OrderedDict()
52
54
  self._body_cache: OrderedDict = OrderedDict()
53
55
  self._spec_cache: OrderedDict = OrderedDict()
56
+ self._weak_refs: Dict[int, weakref.ref] = {}
54
57
  self._hits = 0
55
58
  self._misses = 0
56
59
 
60
+ def _on_object_dead(self, ref: weakref.ref) -> None:
61
+ """弱引用回调:当被引用的函数对象被回收时,清理对应缓存。
62
+
63
+ Args:
64
+ ref: 已失效的弱引用对象。
65
+ """
66
+ dead_id = None
67
+ for obj_id, r in list(self._weak_refs.items()):
68
+ if r is ref:
69
+ dead_id = obj_id
70
+ break
71
+ if dead_id is not None:
72
+ self._weak_refs.pop(dead_id, None)
73
+ self._sig_cache.pop(dead_id, None)
74
+ self._annotations_cache.pop(dead_id, None)
75
+ for key in list(self._body_cache.keys()):
76
+ if isinstance(key, tuple) and key[0] == dead_id:
77
+ self._body_cache.pop(key, None)
78
+ for key in list(self._spec_cache.keys()):
79
+ if isinstance(key, tuple) and key[0] == dead_id:
80
+ self._spec_cache.pop(key, None)
81
+
82
+ def _register_weakref(self, func: Callable) -> None:
83
+ """注册函数对象的弱引用,用于检测对象回收。
84
+
85
+ Args:
86
+ func: 要跟踪的函数对象。
87
+ """
88
+ obj_id = id(func)
89
+ if obj_id not in self._weak_refs:
90
+ try:
91
+ ref = weakref.ref(func, self._on_object_dead)
92
+ self._weak_refs[obj_id] = ref
93
+ except TypeError:
94
+ pass
95
+
96
+ def _is_valid(self, func: Callable, obj_id: int) -> bool:
97
+ """检查缓存键对应的对象是否仍然有效。
98
+
99
+ Args:
100
+ func: 当前函数对象(用于验证)。
101
+ obj_id: 缓存键(id)。
102
+
103
+ Returns:
104
+ True 如果缓存有效,False 如果已失效。
105
+ """
106
+ if obj_id not in self._weak_refs:
107
+ return False
108
+ ref = self._weak_refs[obj_id]
109
+ return ref() is func
110
+
57
111
  def _cache_get(self, cache: OrderedDict, key: int) -> Any:
58
112
  """从 OrderedDict 缓存中获取值并更新 LRU 顺序。
59
113
 
@@ -100,13 +154,13 @@ class BridgeSigCache:
100
154
  inspect.Signature 对象。
101
155
  """
102
156
  key = id(func)
103
- try:
157
+ if key in self._sig_cache and self._is_valid(func, key):
104
158
  return self._cache_get(self._sig_cache, key)
105
- except KeyError:
106
- self._misses += 1
107
- sig = inspect.signature(func)
108
- self._cache_set(self._sig_cache, key, sig)
109
- return sig
159
+ self._misses += 1
160
+ self._register_weakref(func)
161
+ sig = inspect.signature(func)
162
+ self._cache_set(self._sig_cache, key, sig)
163
+ return sig
110
164
 
111
165
  def has_signature(self, func: Callable[..., Any]) -> bool:
112
166
  """检查函数签名是否已缓存。
@@ -117,7 +171,8 @@ class BridgeSigCache:
117
171
  Returns:
118
172
  True 如果已缓存,否则 False。
119
173
  """
120
- return id(func) in self._sig_cache
174
+ key = id(func)
175
+ return key in self._sig_cache and self._is_valid(func, key)
121
176
 
122
177
  # ------------------------------------------------------------------
123
178
  # 类型注解缓存
@@ -137,16 +192,16 @@ class BridgeSigCache:
137
192
  from typing import get_type_hints
138
193
 
139
194
  key = id(func)
140
- try:
195
+ if key in self._annotations_cache and self._is_valid(func, key):
141
196
  return self._cache_get(self._annotations_cache, key)
142
- except KeyError:
143
- self._misses += 1
144
- try:
145
- annotations = get_type_hints(func)
146
- except Exception:
147
- annotations = getattr(func, '__annotations__', {}) or {}
148
- self._cache_set(self._annotations_cache, key, annotations)
149
- return annotations
197
+ self._misses += 1
198
+ self._register_weakref(func)
199
+ try:
200
+ annotations = get_type_hints(func)
201
+ except Exception:
202
+ annotations = getattr(func, '__annotations__', {}) or {}
203
+ self._cache_set(self._annotations_cache, key, annotations)
204
+ return annotations
150
205
 
151
206
  def has_annotations(self, func: Callable[..., Any]) -> bool:
152
207
  """检查函数类型注解是否已缓存。
@@ -157,7 +212,8 @@ class BridgeSigCache:
157
212
  Returns:
158
213
  True 如果已缓存,否则 False。
159
214
  """
160
- return id(func) in self._annotations_cache
215
+ key = id(func)
216
+ return key in self._annotations_cache and self._is_valid(func, key)
161
217
 
162
218
  # ------------------------------------------------------------------
163
219
  # 函数体缓存
@@ -182,13 +238,13 @@ class BridgeSigCache:
182
238
 
183
239
  cache_key = (id(func), _hash_args(args, kwargs))
184
240
 
185
- try:
241
+ if cache_key in self._body_cache and self._is_valid(func, id(func)):
186
242
  return self._cache_get(self._body_cache, cache_key)
187
- except KeyError:
188
- self._misses += 1
189
- body = _extract_body(func, args, kwargs)
190
- self._cache_set(self._body_cache, cache_key, body)
191
- return body
243
+ self._misses += 1
244
+ self._register_weakref(func)
245
+ body = _extract_body(func, args, kwargs)
246
+ self._cache_set(self._body_cache, cache_key, body)
247
+ return body
192
248
 
193
249
  def has_body(self, func: Callable[..., Any], args: tuple = (), kwargs: Optional[Dict[str, Any]] = None) -> bool:
194
250
  """检查函数体是否已缓存。
@@ -204,7 +260,7 @@ class BridgeSigCache:
204
260
  if kwargs is None:
205
261
  kwargs = {}
206
262
  cache_key = (id(func), _hash_args(args, kwargs))
207
- return cache_key in self._body_cache
263
+ return cache_key in self._body_cache and self._is_valid(func, id(func))
208
264
 
209
265
  # ------------------------------------------------------------------
210
266
  # FunctionSpec 缓存
@@ -228,32 +284,32 @@ class BridgeSigCache:
228
284
 
229
285
  cache_key = (id(func), _hash_args(args, kwargs))
230
286
 
231
- try:
287
+ if cache_key in self._spec_cache and self._is_valid(func, id(func)):
232
288
  return self._cache_get(self._spec_cache, cache_key)
233
- except KeyError:
234
- self._misses += 1
235
- from .._base import FunctionSpec
236
-
237
- name = func.__name__
238
- annotations = self.get_annotations(func)
239
- sig = self.get_signature(func)
240
-
241
- defaults = {}
242
- for param_name, param in sig.parameters.items():
243
- if param.default is not inspect.Parameter.empty:
244
- defaults[param_name] = param.default
245
-
246
- body = self.get_body(func, args, kwargs)
247
-
248
- spec = FunctionSpec(
249
- name=name,
250
- annotations=annotations,
251
- args=args,
252
- defaults=defaults,
253
- body=body,
254
- )
255
- self._cache_set(self._spec_cache, cache_key, spec)
256
- return spec
289
+ self._misses += 1
290
+ self._register_weakref(func)
291
+ from .._base import FunctionSpec
292
+
293
+ name = func.__name__
294
+ annotations = self.get_annotations(func)
295
+ sig = self.get_signature(func)
296
+
297
+ defaults = {}
298
+ for param_name, param in sig.parameters.items():
299
+ if param.default is not inspect.Parameter.empty:
300
+ defaults[param_name] = param.default
301
+
302
+ body = self.get_body(func, args, kwargs)
303
+
304
+ spec = FunctionSpec(
305
+ name=name,
306
+ annotations=annotations,
307
+ args=args,
308
+ defaults=defaults,
309
+ body=body,
310
+ )
311
+ self._cache_set(self._spec_cache, cache_key, spec)
312
+ return spec
257
313
 
258
314
  def has_spec(self, func: Callable[..., Any], args: tuple = (), kwargs: Optional[Dict[str, Any]] = None) -> bool:
259
315
  """检查 FunctionSpec 是否已缓存。
@@ -269,7 +325,7 @@ class BridgeSigCache:
269
325
  if kwargs is None:
270
326
  kwargs = {}
271
327
  cache_key = (id(func), _hash_args(args, kwargs))
272
- return cache_key in self._spec_cache
328
+ return cache_key in self._spec_cache and self._is_valid(func, id(func))
273
329
 
274
330
  # ------------------------------------------------------------------
275
331
  # 缓存管理
@@ -11,12 +11,17 @@ vools.bridge.freebasic.transport - 免序列化 Transport 抽象
11
11
  - 本模块让 list 直接以 POINTER(c_long) 形式传入,跳过 CSV 中转
12
12
  """
13
13
 
14
- from typing import Any, Tuple, Protocol
14
+ from typing import Any, Tuple
15
15
 
16
16
  import ctypes
17
17
 
18
18
  from .types import FB_TO_CTYPES, is_array_type
19
19
 
20
+ try:
21
+ from typing import Protocol
22
+ except ImportError:
23
+ Protocol = object
24
+
20
25
 
21
26
  class Transport(object):
22
27
  """
@@ -1,4 +1,4 @@
1
- """
1
+ """
2
2
  vools.bridge.manager - 跨语言桥接统一管理器
3
3
 
4
4
  提供各种外部语言编译器和运行时环境的统一配置、管理和查询。
@@ -98,6 +98,8 @@ class LanguageConfig:
98
98
  elif _IS_MACOS and self.library_suffix == '':
99
99
  self.library_suffix = '.dylib'
100
100
 
101
+ __attrs_post_init__ = __post_init__
102
+
101
103
 
102
104
  @dataclass
103
105
  class LanguageStatus:
@@ -17,7 +17,7 @@ import shutil
17
17
  from typing import Optional, Any, Dict, List
18
18
 
19
19
  from vools.bridge._base import LangBridge, FunctionSpec
20
- from vools.utils.asyncio_compat import run as asyncio_run
20
+ from vools.core.asyncio_compat import run as asyncio_run
21
21
  from .types import PY_TO_ZIG_TYPE, ZIG_TO_CTYPES, get_zig_type, get_zig_ctype
22
22
 
23
23
 
@@ -0,0 +1,122 @@
1
+ """
2
+ asyncio 兼容层 — 统一处理 Python 不同版本的 asyncio 接口
3
+
4
+ 在高版本 Python 使用标准库 asyncio 的原生接口,
5
+ 在低版本(<3.7)提供手动实现的兼容版本。
6
+
7
+ 提供与标准库一致的接口:
8
+ - get_running_loop() → 获取当前运行的事件循环
9
+ - run(coro, *, debug=False) → 运行协程并返回结果
10
+ - create_task(coro, *, name=None) → 创建任务
11
+ """
12
+
13
+ __all__ = ['get_running_loop', 'run', 'create_task']
14
+
15
+ import asyncio
16
+ import sys
17
+
18
+ # ================================================================
19
+ # 检测运行环境
20
+ # ================================================================
21
+
22
+ _HAS_GET_RUNNING_LOOP = sys.version_info >= (3, 7)
23
+ _HAS_ASYNCIO_RUN = sys.version_info >= (3, 7)
24
+ _HAS_CREATE_TASK = sys.version_info >= (3, 7)
25
+
26
+ if _HAS_GET_RUNNING_LOOP and _HAS_ASYNCIO_RUN and _HAS_CREATE_TASK:
27
+ # ── 标准库 asyncio(3.7+) ──
28
+ get_running_loop = asyncio.get_running_loop
29
+ run = asyncio.run
30
+ create_task = asyncio.create_task
31
+
32
+ else:
33
+ # ── Python 3.6 兼容实现 ──
34
+
35
+ def get_running_loop():
36
+ """
37
+ 获取当前运行的事件循环。
38
+
39
+ Python 3.7+ 有 asyncio.get_running_loop(),
40
+ Python 3.6 使用 asyncio._get_running_loop() 作为替代。
41
+
42
+ Returns:
43
+ 当前运行的事件循环。
44
+
45
+ Raises:
46
+ RuntimeError: 如果没有正在运行的事件循环。
47
+ """
48
+ loop = asyncio._get_running_loop()
49
+ if loop is None:
50
+ raise RuntimeError('no running event loop')
51
+ return loop
52
+
53
+ def run(coro, *, debug=False):
54
+ """
55
+ 运行一个协程并返回结果。
56
+
57
+ Python 3.7+ 有 asyncio.run(),
58
+ Python 3.6 手动实现。
59
+
60
+ Args:
61
+ coro: 要运行的协程。
62
+ debug: 是否启用调试模式。
63
+
64
+ Returns:
65
+ 协程的返回值。
66
+ """
67
+ loop = asyncio.new_event_loop()
68
+ try:
69
+ asyncio.set_event_loop(loop)
70
+ loop.set_debug(debug)
71
+ return loop.run_until_complete(coro)
72
+ finally:
73
+ try:
74
+ _cancel_all_tasks(loop)
75
+ if hasattr(loop, 'shutdown_asyncgens'):
76
+ loop.run_until_complete(loop.shutdown_asyncgens())
77
+ finally:
78
+ asyncio.set_event_loop(None)
79
+ loop.close()
80
+
81
+ def create_task(coro, *, name=None):
82
+ """
83
+ 创建一个任务。
84
+
85
+ Python 3.7+ 有 asyncio.create_task(),
86
+ Python 3.6 使用 asyncio.ensure_future() 作为替代。
87
+
88
+ Args:
89
+ coro: 协程对象。
90
+ name: 任务名称(3.6 忽略)。
91
+
92
+ Returns:
93
+ Task 对象。
94
+ """
95
+ return asyncio.ensure_future(coro)
96
+
97
+ def _cancel_all_tasks(loop):
98
+ """取消所有任务(Python 3.6 兼容)"""
99
+ if hasattr(asyncio, 'all_tasks'):
100
+ to_cancel = asyncio.all_tasks(loop)
101
+ else:
102
+ to_cancel = asyncio.Task.all_tasks(loop)
103
+
104
+ if not to_cancel:
105
+ return
106
+
107
+ for task in to_cancel:
108
+ task.cancel()
109
+
110
+ loop.run_until_complete(
111
+ asyncio.gather(*to_cancel, loop=loop, return_exceptions=True)
112
+ )
113
+
114
+ for task in to_cancel:
115
+ if task.cancelled():
116
+ continue
117
+ if task.exception() is not None:
118
+ loop.call_exception_handler({
119
+ 'message': 'unhandled exception during asyncio.run() shutdown',
120
+ 'exception': task.exception(),
121
+ 'task': task,
122
+ })
@@ -11,7 +11,7 @@ dataclass 兼容层 — 统一处理 Python 不同版本的 dataclass 导入
11
11
  - is_dataclass(obj) → 判断
12
12
  """
13
13
 
14
- __all__ = ['dataclass', 'field', 'asdict', 'is_dataclass', 'MISSING']
14
+ __all__ = ['dataclass', 'field', 'asdict', 'is_dataclass', 'MISSING', 'FrozenInstanceError']
15
15
 
16
16
  from typing import Any, Dict, Callable, TypeVar, Optional
17
17
  import sys
@@ -31,6 +31,7 @@ if _HAS_DATACLASSES:
31
31
  from dataclasses import asdict as _std_asdict
32
32
  from dataclasses import is_dataclass as _std_is_dataclass
33
33
  from dataclasses import MISSING as _std_MISSING
34
+ from dataclasses import FrozenInstanceError as _std_FrozenInstanceError
34
35
 
35
36
  def dataclass(cls: Optional[_T] = None, **kwargs) -> _T:
36
37
  """dataclass 装饰器(标准库模式)"""
@@ -42,12 +43,14 @@ if _HAS_DATACLASSES:
42
43
  asdict = _std_asdict
43
44
  is_dataclass = _std_is_dataclass
44
45
  MISSING = _std_MISSING
46
+ FrozenInstanceError = _std_FrozenInstanceError
45
47
 
46
48
  else:
47
49
  # ── attrs 降级模式 ──
48
50
  try:
49
51
  from attr import attrs, attrib, asdict as _attr_asdict
50
52
  from attr import has as _attr_has
53
+ from attr.exceptions import FrozenInstanceError as _attr_FrozenInstanceError
51
54
  except ImportError:
52
55
  msg = (
53
56
  "Python < 3.7 detected but 'attrs' package is not installed. "
@@ -92,11 +95,19 @@ else:
92
95
  - order: bool → 忽略(attrs 不支持自动排序)
93
96
  """
94
97
  frozen = kwargs.pop('frozen', False)
98
+
99
+ def _wrap(c):
100
+ wrapped = attrs(c, frozen=frozen, auto_attribs=True)
101
+ # 兼容 __post_init__: attrs 用 __attrs_post_init__
102
+ if hasattr(wrapped, '__post_init__') and not hasattr(wrapped, '__attrs_post_init__'):
103
+ wrapped.__attrs_post_init__ = wrapped.__post_init__
104
+ return wrapped
105
+
95
106
  # attrs 的 frozen 默认是 False,等价
96
107
  if cls is not None:
97
- return attrs(cls, frozen=frozen, auto_attribs=True)
108
+ return _wrap(cls)
98
109
  # 带参装饰器模式: @dataclass(frozen=True)
99
- return lambda c: attrs(c, frozen=frozen, auto_attribs=True)
110
+ return _wrap
100
111
 
101
112
  def field(*, default=MISSING, default_factory=MISSING, **kwargs) -> Any:
102
113
  """
@@ -123,3 +134,5 @@ else:
123
134
  def is_dataclass(obj) -> bool:
124
135
  """判断是否为 dataclass/attrs 实例"""
125
136
  return _attr_has(obj)
137
+
138
+ FrozenInstanceError = _attr_FrozenInstanceError
@@ -0,0 +1,180 @@
1
+ """
2
+ datetime 兼容层 — 统一处理 Python 不同版本的 datetime 接口
3
+
4
+ 在高版本 Python 使用标准库 datetime 的原生接口,
5
+ 在低版本(<3.7)提供兼容实现。
6
+
7
+ 提供的兼容接口:
8
+ - datetime_fromisoformat(date_string) → datetime.fromisoformat
9
+ - date_fromisoformat(date_string) → date.fromisoformat
10
+ - time_fromisoformat(time_string) → time.fromisoformat
11
+ """
12
+
13
+ __all__ = [
14
+ 'datetime_fromisoformat',
15
+ 'date_fromisoformat',
16
+ 'time_fromisoformat',
17
+ ]
18
+
19
+ import sys
20
+ import datetime
21
+
22
+ _HAS_FROMISOFORMAT = sys.version_info >= (3, 7)
23
+
24
+
25
+ if _HAS_FROMISOFORMAT:
26
+ # ── 标准库 datetime(3.7+) ──
27
+
28
+ def datetime_fromisoformat(date_string):
29
+ """Python 3.7+ 的 datetime.fromisoformat"""
30
+ return datetime.datetime.fromisoformat(date_string)
31
+
32
+ def date_fromisoformat(date_string):
33
+ """Python 3.7+ 的 date.fromisoformat"""
34
+ return datetime.date.fromisoformat(date_string)
35
+
36
+ def time_fromisoformat(time_string):
37
+ """Python 3.7+ 的 time.fromisoformat"""
38
+ return datetime.time.fromisoformat(time_string)
39
+
40
+ else:
41
+ # ── Python 3.6 兼容实现 ──
42
+ # 使用 strptime 解析常见的 ISO 格式
43
+
44
+ import re
45
+
46
+ _DATETIME_RE = re.compile(
47
+ r'^(\d{4})-(\d{1,2})-(\d{1,2})'
48
+ r'[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d{1,6}))?)?'
49
+ r'(?:Z|[+-]\d{2}:?\d{2})?$'
50
+ )
51
+
52
+ _DATE_RE = re.compile(r'^(\d{4})-(\d{1,2})-(\d{1,2})$')
53
+
54
+ _TIME_RE = re.compile(
55
+ r'^(\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d{1,6}))?)?$'
56
+ )
57
+
58
+ def datetime_fromisoformat(date_string):
59
+ """
60
+ 兼容版 datetime.fromisoformat(Python 3.6)。
61
+
62
+ 支持常见的 ISO 8601 格式:
63
+ - YYYY-MM-DDTHH:MM:SS
64
+ - YYYY-MM-DD HH:MM:SS
65
+ - 带微秒、不带秒等变体
66
+
67
+ Args:
68
+ date_string: ISO 格式的日期时间字符串。
69
+
70
+ Returns:
71
+ datetime.datetime 对象。
72
+
73
+ Raises:
74
+ ValueError: 如果字符串格式不支持。
75
+ """
76
+ if isinstance(date_string, datetime.datetime):
77
+ return date_string
78
+
79
+ s = str(date_string).strip()
80
+
81
+ # 先尝试用 strptime 解析常见格式
82
+ formats = [
83
+ '%Y-%m-%dT%H:%M:%S.%f',
84
+ '%Y-%m-%d %H:%M:%S.%f',
85
+ '%Y-%m-%dT%H:%M:%S',
86
+ '%Y-%m-%d %H:%M:%S',
87
+ '%Y-%m-%dT%H:%M',
88
+ '%Y-%m-%d %H:%M',
89
+ ]
90
+ for fmt in formats:
91
+ try:
92
+ return datetime.datetime.strptime(s, fmt)
93
+ except ValueError:
94
+ continue
95
+
96
+ # 尝试用正则解析
97
+ m = _DATETIME_RE.match(s)
98
+ if m:
99
+ year, month, day = int(m.group(1)), int(m.group(2)), int(m.group(3))
100
+ hour, minute = int(m.group(4)), int(m.group(5))
101
+ second = int(m.group(6)) if m.group(6) else 0
102
+ microsecond = 0
103
+ if m.group(7):
104
+ micro_str = m.group(7).ljust(6, '0')
105
+ microsecond = int(micro_str)
106
+ return datetime.datetime(
107
+ year, month, day, hour, minute, second, microsecond
108
+ )
109
+
110
+ raise ValueError(
111
+ 'Invalid isoformat string: %r' % date_string
112
+ )
113
+
114
+ def date_fromisoformat(date_string):
115
+ """
116
+ 兼容版 date.fromisoformat(Python 3.6)。
117
+
118
+ Args:
119
+ date_string: ISO 格式的日期字符串。
120
+
121
+ Returns:
122
+ datetime.date 对象。
123
+ """
124
+ if isinstance(date_string, datetime.date):
125
+ return date_string
126
+
127
+ s = str(date_string).strip()
128
+
129
+ try:
130
+ return datetime.datetime.strptime(s, '%Y-%m-%d').date()
131
+ except ValueError:
132
+ pass
133
+
134
+ m = _DATE_RE.match(s)
135
+ if m:
136
+ return datetime.date(int(m.group(1)), int(m.group(2)), int(m.group(3)))
137
+
138
+ raise ValueError(
139
+ 'Invalid isoformat string: %r' % date_string
140
+ )
141
+
142
+ def time_fromisoformat(time_string):
143
+ """
144
+ 兼容版 time.fromisoformat(Python 3.6)。
145
+
146
+ Args:
147
+ time_string: ISO 格式的时间字符串。
148
+
149
+ Returns:
150
+ datetime.time 对象。
151
+ """
152
+ if isinstance(time_string, datetime.time):
153
+ return time_string
154
+
155
+ s = str(time_string).strip()
156
+
157
+ formats = [
158
+ '%H:%M:%S.%f',
159
+ '%H:%M:%S',
160
+ '%H:%M',
161
+ ]
162
+ for fmt in formats:
163
+ try:
164
+ return datetime.datetime.strptime(s, fmt).time()
165
+ except ValueError:
166
+ continue
167
+
168
+ m = _TIME_RE.match(s)
169
+ if m:
170
+ hour, minute = int(m.group(1)), int(m.group(2))
171
+ second = int(m.group(3)) if m.group(3) else 0
172
+ microsecond = 0
173
+ if m.group(4):
174
+ micro_str = m.group(4).ljust(6, '0')
175
+ microsecond = int(micro_str)
176
+ return datetime.time(hour, minute, second, microsecond)
177
+
178
+ raise ValueError(
179
+ 'Invalid isoformat string: %r' % time_string
180
+ )