mplang-nightly 0.1.dev271__tar.gz → 0.1.dev273__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 (211) hide show
  1. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/PKG-INFO +1 -1
  2. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/__init__.py +7 -0
  3. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/channel.py +35 -17
  4. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/simp_driver/http.py +3 -0
  5. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/simp_worker/http.py +3 -3
  6. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/spu_impl.py +3 -0
  7. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/table_impl.py +3 -0
  8. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/tensor_impl.py +3 -0
  9. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/cli.py +13 -0
  10. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/edsl/jit.py +8 -0
  11. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/edsl/primitive.py +6 -0
  12. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/edsl/tracer.py +20 -1
  13. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/device/api.py +3 -0
  14. mplang_nightly-0.1.dev273/mplang/logging_config.py +202 -0
  15. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/runtime/interpreter.py +26 -0
  16. mplang_nightly-0.1.dev273/tests/test_logging.py +273 -0
  17. mplang_nightly-0.1.dev273/tutorials/08_logging.py +620 -0
  18. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/.gitignore +0 -0
  19. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/LICENSE +0 -0
  20. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/README.md +0 -0
  21. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/examples/.gitkeep +0 -0
  22. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/hatch_build.py +0 -0
  23. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/__init__.py +0 -0
  24. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/bfv_impl.py +0 -0
  25. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/crypto_impl.py +0 -0
  26. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/field_impl.py +0 -0
  27. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/func_impl.py +0 -0
  28. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/phe_impl.py +0 -0
  29. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/simp_design.md +0 -0
  30. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/simp_driver/__init__.py +0 -0
  31. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/simp_driver/mem.py +0 -0
  32. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/simp_driver/ops.py +0 -0
  33. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/simp_driver/state.py +0 -0
  34. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/simp_driver/values.py +0 -0
  35. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/simp_worker/__init__.py +0 -0
  36. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/simp_worker/mem.py +0 -0
  37. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/simp_worker/ops.py +0 -0
  38. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/simp_worker/state.py +0 -0
  39. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/spu_state.py +0 -0
  40. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/store_impl.py +0 -0
  41. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/backends/tee_impl.py +0 -0
  42. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/cli_guide.md +0 -0
  43. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/dialects/__init__.py +0 -0
  44. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/dialects/bfv.py +0 -0
  45. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/dialects/crypto.py +0 -0
  46. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/dialects/dtypes.py +0 -0
  47. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/dialects/field.py +0 -0
  48. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/dialects/func.py +0 -0
  49. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/dialects/phe.py +0 -0
  50. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/dialects/simp.py +0 -0
  51. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/dialects/spu.py +0 -0
  52. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/dialects/store.py +0 -0
  53. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/dialects/table.py +0 -0
  54. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/dialects/tee.py +0 -0
  55. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/dialects/tensor.py +0 -0
  56. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/edsl/README.md +0 -0
  57. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/edsl/__init__.py +0 -0
  58. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/edsl/context.py +0 -0
  59. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/edsl/graph.py +0 -0
  60. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/edsl/object.py +0 -0
  61. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/edsl/printer.py +0 -0
  62. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/edsl/registry.py +0 -0
  63. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/edsl/serde.py +0 -0
  64. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/edsl/typing.py +0 -0
  65. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/kernels/Makefile +0 -0
  66. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/kernels/__init__.py +0 -0
  67. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/kernels/gf128.cpp +0 -0
  68. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/kernels/ldpc.cpp +0 -0
  69. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/kernels/okvs.cpp +0 -0
  70. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/kernels/okvs_opt.cpp +0 -0
  71. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/kernels/py_kernels.py +0 -0
  72. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/collective.py +0 -0
  73. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/device/__init__.py +0 -0
  74. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/device/cluster.py +0 -0
  75. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/ml/__init__.py +0 -0
  76. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/ml/sgb.py +0 -0
  77. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/__init__.py +0 -0
  78. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/_utils.py +0 -0
  79. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/analytics/__init__.py +0 -0
  80. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/analytics/aggregation.py +0 -0
  81. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/analytics/groupby.md +0 -0
  82. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/analytics/groupby.py +0 -0
  83. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/analytics/permutation.py +0 -0
  84. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/common/constants.py +0 -0
  85. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/ot/__init__.py +0 -0
  86. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/ot/base.py +0 -0
  87. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/ot/extension.py +0 -0
  88. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/ot/silent.py +0 -0
  89. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/psi/__init__.py +0 -0
  90. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/psi/cuckoo.py +0 -0
  91. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/psi/okvs.py +0 -0
  92. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/psi/okvs_gct.py +0 -0
  93. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/psi/oprf.py +0 -0
  94. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/psi/rr22.py +0 -0
  95. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/psi/unbalanced.py +0 -0
  96. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/vole/__init__.py +0 -0
  97. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/vole/gilboa.py +0 -0
  98. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/vole/ldpc.py +0 -0
  99. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/libs/mpc/vole/silver.py +0 -0
  100. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/py.typed +0 -0
  101. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/runtime/__init__.py +0 -0
  102. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/runtime/dialect_state.py +0 -0
  103. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/runtime/object_store.py +0 -0
  104. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/runtime/value.py +0 -0
  105. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/utils/__init__.py +0 -0
  106. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/mplang/utils/func_utils.py +0 -0
  107. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/pyproject.toml +0 -0
  108. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/__init__.py +0 -0
  109. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/__init__.py +0 -0
  110. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/simp_driver/__init__.py +0 -0
  111. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/simp_driver/test_http.py +0 -0
  112. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/simp_worker/__init__.py +0 -0
  113. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/simp_worker/test_http.py +0 -0
  114. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/simp_worker/test_mem.py +0 -0
  115. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/test_bfv_impl.py +0 -0
  116. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/test_channel.py +0 -0
  117. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/test_crypto_impl.py +0 -0
  118. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/test_okvs_binding.py +0 -0
  119. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/test_simp_integration.py +0 -0
  120. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/test_simp_object_store.py +0 -0
  121. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/test_spu_impl.py +0 -0
  122. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/test_table_impl.py +0 -0
  123. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/test_tee_impl.py +0 -0
  124. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/test_tensor_impl.py +0 -0
  125. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/backends/test_verify_clean.py +0 -0
  126. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/conftest.py +0 -0
  127. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/__init__.py +0 -0
  128. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/test_bfv.py +0 -0
  129. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/test_crypto.py +0 -0
  130. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/test_dtypes.py +0 -0
  131. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/test_field.py +0 -0
  132. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/test_func.py +0 -0
  133. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/test_okvs.py +0 -0
  134. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/test_okvs_bench.py +0 -0
  135. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/test_phe.py +0 -0
  136. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/test_simp.py +0 -0
  137. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/test_simp_comm.py +0 -0
  138. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/test_spu.py +0 -0
  139. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/test_store.py +0 -0
  140. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/test_table.py +0 -0
  141. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/test_tee.py +0 -0
  142. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/dialects/test_tensor.py +0 -0
  143. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/edsl/__init__.py +0 -0
  144. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/edsl/test_context.py +0 -0
  145. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/edsl/test_graph.py +0 -0
  146. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/edsl/test_primitive.py +0 -0
  147. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/edsl/test_primitive_multi_output.py +0 -0
  148. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/edsl/test_printer.py +0 -0
  149. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/edsl/test_serde.py +0 -0
  150. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/edsl/test_tracer.py +0 -0
  151. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/edsl/test_typing.py +0 -0
  152. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/edsl/test_typing_graph_serde.py +0 -0
  153. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/device/__init__.py +0 -0
  154. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/device/conftest.py +0 -0
  155. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/device/test_device_api_errors.py +0 -0
  156. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/device/test_device_dialects.py +0 -0
  157. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/device/test_device_layouts.py +0 -0
  158. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/device/test_device_tee.py +0 -0
  159. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/ml/__init__.py +0 -0
  160. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/ml/test_sgb.py +0 -0
  161. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/ml/test_sgb_bench.py +0 -0
  162. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/__init__.py +0 -0
  163. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/analytics/__init__.py +0 -0
  164. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/analytics/test_aggregation.py +0 -0
  165. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/analytics/test_groupby.py +0 -0
  166. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/analytics/test_permutation.py +0 -0
  167. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/ot/__init__.py +0 -0
  168. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/ot/test_ot.py +0 -0
  169. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/ot/test_ot_extension.py +0 -0
  170. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/ot/test_silent_ot.py +0 -0
  171. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/psi/__init__.py +0 -0
  172. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/psi/test_okvs_gct.py +0 -0
  173. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/psi/test_oprf.py +0 -0
  174. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/psi/test_psi.py +0 -0
  175. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/psi/test_psi_bench.py +0 -0
  176. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/psi/test_rr22.py +0 -0
  177. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/psi/verify_psi_okvs_logic.py +0 -0
  178. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/test_field_gf128.py +0 -0
  179. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/test_utils.py +0 -0
  180. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/vole/__init__.py +0 -0
  181. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/vole/test_gilboa_manual.py +0 -0
  182. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/vole/test_ldpc.py +0 -0
  183. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/vole/test_silver_vole.py +0 -0
  184. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/vole/test_vole.py +0 -0
  185. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/vole/test_vole_bench.py +0 -0
  186. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/mpc/vole/verify_vole_logic.py +0 -0
  187. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/test_collective.py +0 -0
  188. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/libs/test_simple_guide.py +0 -0
  189. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/runtime/test_interpreter_async.py +0 -0
  190. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/runtime/test_object_store.py +0 -0
  191. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/runtime/test_object_store_fs.py +0 -0
  192. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/test_fetch_semantics.py +0 -0
  193. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/test_pytree_io.py +0 -0
  194. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/utils/__init__.py +0 -0
  195. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/utils/tensor_patch.py +0 -0
  196. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tests/utils/test_func_utils.py +0 -0
  197. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tutorials/00_device_basics.py +0 -0
  198. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tutorials/01_function_decorator.py +0 -0
  199. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tutorials/02_simulation_and_driver.py +0 -0
  200. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tutorials/03_run_jax.py +0 -0
  201. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tutorials/04_ir_dump_and_analysis.py +0 -0
  202. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tutorials/05_run_sql.py +0 -0
  203. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tutorials/06_pipeline.py +0 -0
  204. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tutorials/07_stax_nn.py +0 -0
  205. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tutorials/MIGRATION.md +0 -0
  206. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tutorials/README.md +0 -0
  207. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tutorials/__init__.py +0 -0
  208. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tutorials/data/alice.csv +0 -0
  209. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tutorials/data/bob.csv +0 -0
  210. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tutorials/data/prepare_vertical_iris.py +0 -0
  211. {mplang_nightly-0.1.dev271 → mplang_nightly-0.1.dev273}/tutorials/run.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mplang-nightly
3
- Version: 0.1.dev271
3
+ Version: 0.1.dev273
4
4
  Summary: Multi-Party Programming Language
5
5
  Author-email: SecretFlow Team <secretflow-contact@service.alipay.com>
6
6
  License: Apache License
@@ -91,6 +91,9 @@ from mplang.libs.device import (
91
91
  set_dev_attr,
92
92
  )
93
93
  from mplang.libs.device import fetch as device_fetch
94
+
95
+ # Logging configuration
96
+ from mplang.logging_config import disable_logging, get_logger, setup_logging
94
97
  from mplang.runtime.interpreter import Interpreter
95
98
 
96
99
  # =============================================================================
@@ -359,6 +362,10 @@ def compile(
359
362
  __all__ = [ # noqa: RUF022
360
363
  # Version
361
364
  "__version__",
365
+ # Logging
366
+ "disable_logging",
367
+ "setup_logging",
368
+ "get_logger",
362
369
  # Device API
363
370
  "ClusterSpec",
364
371
  "Device",
@@ -21,11 +21,14 @@ infrastructure instead of creating separate BRPC connections.
21
21
 
22
22
  from __future__ import annotations
23
23
 
24
- import logging
25
24
  from typing import Protocol
26
25
 
27
26
  import spu.libspu as libspu
28
27
 
28
+ from mplang.logging_config import get_logger
29
+
30
+ logger = get_logger(__name__)
31
+
29
32
 
30
33
  class CommunicatorProtocol(Protocol):
31
34
  """Protocol for v2 communicators (duck typing).
@@ -73,9 +76,11 @@ class BaseChannel(libspu.link.IChannel):
73
76
  self._peer_rank = peer_rank
74
77
  self._tag_prefix = tag_prefix
75
78
 
76
- logging.debug(
77
- f"BaseChannel initialized: local_rank={local_rank}, "
78
- f"peer_rank={peer_rank}, tag_prefix={tag_prefix}"
79
+ logger.debug(
80
+ "BaseChannel initialized: local_rank=%d, peer_rank=%d, tag_prefix=%s",
81
+ local_rank,
82
+ peer_rank,
83
+ tag_prefix,
79
84
  )
80
85
 
81
86
  def _make_key(self, tag: str) -> str:
@@ -97,9 +102,13 @@ class BaseChannel(libspu.link.IChannel):
97
102
  data: Raw bytes to send
98
103
  """
99
104
  key = self._make_key(tag)
100
- logging.debug(
101
- f"BaseChannel.Send: {self._local_rank} -> {self._peer_rank}, "
102
- f"tag={tag}, key={key}, size={len(data)}"
105
+ logger.debug(
106
+ "BaseChannel.Send: %d -> %d, tag=%s, key=%s, size=%d",
107
+ self._local_rank,
108
+ self._peer_rank,
109
+ tag,
110
+ key,
111
+ len(data),
103
112
  )
104
113
 
105
114
  # Send raw bytes directly
@@ -119,9 +128,12 @@ class BaseChannel(libspu.link.IChannel):
119
128
  TypeError: If received data is not bytes
120
129
  """
121
130
  key = self._make_key(tag)
122
- logging.debug(
123
- f"BaseChannel.Recv: {self._local_rank} <- {self._peer_rank}, "
124
- f"tag={tag}, key={key}"
131
+ logger.debug(
132
+ "BaseChannel.Recv: %d <- %d, tag=%s, key=%s",
133
+ self._local_rank,
134
+ self._peer_rank,
135
+ tag,
136
+ key,
125
137
  )
126
138
 
127
139
  # Receive data (should be bytes)
@@ -134,9 +146,12 @@ class BaseChannel(libspu.link.IChannel):
134
146
  f"Communicator must support raw bytes transmission for SPU channels."
135
147
  )
136
148
 
137
- logging.debug(
138
- f"BaseChannel.Recv complete: {self._local_rank} <- {self._peer_rank}, "
139
- f"tag={tag}, size={len(data)}"
149
+ logger.debug(
150
+ "BaseChannel.Recv complete: %d <- %d, tag=%s, size=%d",
151
+ self._local_rank,
152
+ self._peer_rank,
153
+ tag,
154
+ len(data),
140
155
  )
141
156
  return data
142
157
 
@@ -184,9 +199,10 @@ class BaseChannel(libspu.link.IChannel):
184
199
  """
185
200
  test_data = self.Recv("__test__")
186
201
  if test_data != b"\x00":
187
- logging.warning(
188
- f"TestRecv: unexpected handshake from {self._peer_rank}, "
189
- f"expected b'\\x00', got {test_data!r}"
202
+ logger.warning(
203
+ "TestRecv: unexpected handshake from %d, expected b'\\x00', got %r",
204
+ self._peer_rank,
205
+ test_data,
190
206
  )
191
207
 
192
208
  def WaitLinkTaskFinish(self) -> None:
@@ -200,7 +216,9 @@ class BaseChannel(libspu.link.IChannel):
200
216
 
201
217
  Currently a no-op. Could be extended for resource cleanup.
202
218
  """
203
- logging.warning(f"BaseChannel.Abort: {self._local_rank} <-> {self._peer_rank}")
219
+ logger.warning(
220
+ "BaseChannel.Abort: %d <-> %d", self._local_rank, self._peer_rank
221
+ )
204
222
 
205
223
  def SetThrottleWindowSize(self, size: int) -> None:
206
224
  """Set throttle window size (no-op).
@@ -25,9 +25,12 @@ import httpx
25
25
 
26
26
  from mplang.backends.simp_driver.state import SimpDriver
27
27
  from mplang.edsl import serde
28
+ from mplang.logging_config import get_logger
28
29
  from mplang.runtime.interpreter import Interpreter
29
30
  from mplang.runtime.object_store import ObjectStore
30
31
 
32
+ logger = get_logger(__name__)
33
+
31
34
  if TYPE_CHECKING:
32
35
  from concurrent.futures import Future
33
36
 
@@ -36,7 +36,6 @@ Security:
36
36
  from __future__ import annotations
37
37
 
38
38
  import concurrent.futures
39
- import logging
40
39
  import os
41
40
  import pathlib
42
41
  import threading
@@ -55,10 +54,11 @@ from mplang.backends.simp_worker import SimpWorker
55
54
  from mplang.backends.simp_worker import ops as _simp_worker_ops # noqa: F401
56
55
  from mplang.edsl import serde
57
56
  from mplang.edsl.graph import Graph
57
+ from mplang.logging_config import get_logger
58
58
  from mplang.runtime.interpreter import ExecutionTracer, Interpreter
59
59
  from mplang.runtime.object_store import ObjectStore
60
60
 
61
- logger = logging.getLogger(__name__)
61
+ logger = get_logger(__name__)
62
62
 
63
63
 
64
64
  class HttpCommunicator:
@@ -99,7 +99,7 @@ class HttpCommunicator:
99
99
  def _do_send(self, to: int, key: str, data: Any) -> None:
100
100
  """Perform the HTTP send."""
101
101
  url = f"{self.endpoints[to]}/comm/{key}"
102
- logger.debug(f"Rank {self.rank} sending to {to} key={key}")
102
+ logger.debug(f"Rank {self.rank} sending to {to} key={key}, url={url}")
103
103
 
104
104
  # Detect SPU channel (tag prefix "spu:") and handle bytes
105
105
  if key.startswith("spu:") and isinstance(data, bytes):
@@ -31,9 +31,12 @@ from mplang.backends.tensor_impl import TensorValue
31
31
  from mplang.dialects import spu
32
32
  from mplang.edsl import serde
33
33
  from mplang.edsl.graph import Operation
34
+ from mplang.logging_config import get_logger
34
35
  from mplang.runtime.interpreter import Interpreter
35
36
  from mplang.runtime.value import WrapValue
36
37
 
38
+ logger = get_logger(__name__)
39
+
37
40
  # =============================================================================
38
41
  # SPU Share Wrapper
39
42
  # =============================================================================
@@ -33,9 +33,12 @@ from mplang.backends.tensor_impl import TensorValue
33
33
  from mplang.dialects import table
34
34
  from mplang.edsl import serde
35
35
  from mplang.edsl.graph import Operation
36
+ from mplang.logging_config import get_logger
36
37
  from mplang.runtime.interpreter import Interpreter
37
38
  from mplang.runtime.value import WrapValue
38
39
 
40
+ logger = get_logger(__name__)
41
+
39
42
 
40
43
  class BatchReader(ABC):
41
44
  @property
@@ -36,9 +36,12 @@ import mplang.edsl.typing as elt
36
36
  from mplang.dialects import dtypes, tensor
37
37
  from mplang.edsl import serde
38
38
  from mplang.edsl.graph import Operation
39
+ from mplang.logging_config import get_logger
39
40
  from mplang.runtime.interpreter import Interpreter
40
41
  from mplang.runtime.value import Value, WrapValue
41
42
 
43
+ logger = get_logger(__name__)
44
+
42
45
  # =============================================================================
43
46
  # TensorValue Wrapper
44
47
  # =============================================================================
@@ -49,6 +49,10 @@ from typing import Any, cast
49
49
  import uvicorn
50
50
  import yaml
51
51
 
52
+ from mplang.logging_config import get_logger
53
+
54
+ logger = get_logger(__name__)
55
+
52
56
 
53
57
  def run_worker(
54
58
  rank: int,
@@ -287,26 +291,33 @@ def cmd_status(args: argparse.Namespace) -> None:
287
291
  resp.raise_for_status()
288
292
  print(f"OK {url} -> {resp.json()}")
289
293
  except Exception as exc:
294
+ logger.warning("Health check failed for %s: %s", url, exc)
290
295
  print(f"ERR {url} -> {exc}")
291
296
 
292
297
 
293
298
  def load_user_module(path: str) -> ModuleType:
294
299
  """Load a Python module from file path."""
300
+ logger.debug("Loading user module from %s", path)
295
301
  if not os.path.exists(path):
302
+ logger.error("Module file not found: %s", path)
296
303
  raise FileNotFoundError(path)
297
304
  spec = importlib.util.spec_from_file_location("mp_user_module", path)
298
305
  if spec is None or spec.loader is None:
306
+ logger.error("Cannot import module from %s", path)
299
307
  raise ImportError(f"Cannot import module from {path}")
300
308
  module = importlib.util.module_from_spec(spec)
301
309
  sys.modules[spec.name] = module
302
310
  spec.loader.exec_module(module)
311
+ logger.debug("Successfully loaded module: %s", path)
303
312
  return module
304
313
 
305
314
 
306
315
  def resolve_entry(module: ModuleType, name: str) -> Callable[..., Any]:
307
316
  entry = getattr(module, name, None)
308
317
  if entry is None or not callable(entry):
318
+ logger.error("Entry function '%s' not found or not callable in module", name)
309
319
  raise AttributeError(f"Entry function '{name}' not found or not callable")
320
+ logger.debug("Resolved entry function: %s", name)
310
321
  return cast(Callable[..., Any], entry)
311
322
 
312
323
 
@@ -421,6 +432,7 @@ def cmd_trace_merge(args: argparse.Namespace) -> None:
421
432
  merged_events.append(event)
422
433
 
423
434
  except Exception as e:
435
+ logger.error("Error processing trace file %s: %s", fname, e, exc_info=True)
424
436
  print(f"Error processing {fname}: {e}")
425
437
 
426
438
  # Write merged file
@@ -458,6 +470,7 @@ def cmd_objects(args: argparse.Namespace) -> None:
458
470
  f"{rank:<6} | {endpoints[rank]:<25} | {'Err':<6} | Status {resp.status_code}"
459
471
  )
460
472
  except Exception as e:
473
+ logger.warning("Failed to list objects on rank %d: %s", rank, e)
461
474
  print(f"{rank:<6} | {endpoints[rank]:<25} | {'Err':<6} | {e}")
462
475
 
463
476
 
@@ -25,6 +25,9 @@ from mplang.edsl.context import (
25
25
  get_default_context,
26
26
  )
27
27
  from mplang.edsl.tracer import Tracer
28
+ from mplang.logging_config import get_logger
29
+
30
+ logger = get_logger(__name__)
28
31
 
29
32
 
30
33
  def jit(fn: Callable) -> Callable:
@@ -42,13 +45,17 @@ def jit(fn: Callable) -> Callable:
42
45
  """
43
46
 
44
47
  def wrapper(*args: Any, **kwargs: Any) -> Any:
48
+ fn_name = getattr(fn, "__name__", "anonymous")
49
+
45
50
  # If we are already inside a Tracer (e.g. pcall_static), just inline
46
51
  # the function to trace it into the current graph.
47
52
  cur_ctx = get_current_context()
48
53
  if isinstance(cur_ctx, Tracer):
54
+ logger.debug("JIT: inlining '%s' into current trace context", fn_name)
49
55
  return fn(*args, **kwargs)
50
56
 
51
57
  # otherwise trace for JIT compilation
58
+ logger.debug("JIT: compiling '%s'", fn_name)
52
59
  with Tracer():
53
60
  result = fn(*args, **kwargs)
54
61
 
@@ -57,6 +64,7 @@ def jit(fn: Callable) -> Callable:
57
64
  assert isinstance(cur_ctx, AbstractInterpreter), (
58
65
  "JIT execution requires Interpreter context"
59
66
  )
67
+ logger.debug("JIT: executing compiled '%s'", fn_name)
60
68
  return tree_map(cur_ctx.lift, result)
61
69
 
62
70
  return wrapper
@@ -29,12 +29,15 @@ from jax.tree_util import tree_map
29
29
 
30
30
  from mplang.edsl.context import get_current_context, get_default_context
31
31
  from mplang.edsl.object import Object
32
+ from mplang.logging_config import get_logger
32
33
 
33
34
  if TYPE_CHECKING:
34
35
  from mplang.edsl.typing import BaseType
35
36
 
36
37
  T_Ret = TypeVar("T_Ret")
37
38
 
39
+ logger = get_logger(__name__)
40
+
38
41
 
39
42
  class Primitive(Generic[T_Ret]):
40
43
  """Atomic operation definition (similar to JAX Primitive).
@@ -89,6 +92,7 @@ class Primitive(Generic[T_Ret]):
89
92
  Returns:
90
93
  The same function (for decorator pattern)
91
94
  """
95
+ logger.debug("Registering impl for primitive '%s'", self.name)
92
96
  self._impl = fn
93
97
  # Register with the global interpreter registry
94
98
  from mplang.edsl.registry import register_impl
@@ -140,6 +144,7 @@ class Primitive(Generic[T_Ret]):
140
144
  >>> # Variable number of inputs
141
145
  >>> return in_types[0] # Concatenated type
142
146
  """
147
+ logger.debug("Registering abstract_eval for primitive '%s'", self.name)
143
148
  self._abstract_eval = fn
144
149
  return fn
145
150
 
@@ -187,6 +192,7 @@ class Primitive(Generic[T_Ret]):
187
192
  >>> parts = [slice_p.bind(x, i) for i in range(num_splits)]
188
193
  >>> return parts # Returns list of Objects
189
194
  """
195
+ logger.debug("Registering trace for primitive '%s'", self.name)
190
196
  self._trace = fn
191
197
  return fn
192
198
 
@@ -1,4 +1,4 @@
1
- # Copyright 2025 Ant Group Co., Ltd.
1
+ # Copyright 2026 Ant Group Co., Ltd.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -36,10 +36,13 @@ from mplang.edsl.graph import Graph
36
36
  from mplang.edsl.graph import Value as GraphValue
37
37
  from mplang.edsl.object import Object
38
38
  from mplang.edsl.typing import BaseType
39
+ from mplang.logging_config import get_logger
39
40
 
40
41
  if TYPE_CHECKING:
41
42
  from mplang.edsl.primitive import Primitive
42
43
 
44
+ logger = get_logger(__name__)
45
+
43
46
 
44
47
  class TraceObject(Object):
45
48
  """Trace-time object (during JIT tracing).
@@ -121,6 +124,12 @@ class Tracer(Context):
121
124
  Raises:
122
125
  RuntimeError: If primitive has neither trace nor abstract_eval defined
123
126
  """
127
+ logger.debug(
128
+ "Binding primitive '%s' in trace mode (args=%d, kwargs=%s)",
129
+ primitive.name,
130
+ len(args),
131
+ list(kwargs.keys()),
132
+ )
124
133
  if primitive._trace is not None:
125
134
  return primitive._trace(*args, **kwargs)
126
135
 
@@ -298,6 +307,7 @@ class Tracer(Context):
298
307
  raise TypeError(f"fn must be callable, got {type(fn)}")
299
308
 
300
309
  fn_name = getattr(fn, "__name__", "anonymous")
310
+ logger.debug("Starting trace of function: %s", fn_name)
301
311
  in_flat, in_treedef = tree_flatten((args, kwargs))
302
312
  in_imms, in_var_pos, in_vars = _separate_vars_and_imms(in_flat)
303
313
 
@@ -329,6 +339,15 @@ class Tracer(Context):
329
339
  obj for obj, _ in self._captured_vars.values()
330
340
  ]
331
341
 
342
+ logger.debug(
343
+ "Trace completed: %s - %d inputs, %d outputs, %d ops, %d captured vars",
344
+ fn_name,
345
+ len(graph.inputs),
346
+ len(graph.outputs),
347
+ len(graph.operations),
348
+ len(captured_objects),
349
+ )
350
+
332
351
  return TracedFunction(
333
352
  name=fn_name,
334
353
  graph=graph,
@@ -32,9 +32,12 @@ from mplang.backends import load_builtins
32
32
  from mplang.dialects import crypto, simp, spu, tee
33
33
  from mplang.edsl.object import Object
34
34
  from mplang.libs.device.cluster import Device
35
+ from mplang.logging_config import get_logger
35
36
 
36
37
  load_builtins()
37
38
 
39
+ logger = get_logger(__name__)
40
+
38
41
 
39
42
  def _resolve_cluster() -> Any:
40
43
  """Resolve the active ClusterSpec by traversing the context stack.
@@ -0,0 +1,202 @@
1
+ # Copyright 2026 Ant Group Co., Ltd.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """
16
+ Logging configuration for MPLang.
17
+
18
+ This module provides a unified logging setup for the MPLang library.
19
+ When MPLang is used as a library, logging is disabled by default (NullHandler),
20
+ allowing applications to configure logging as needed.
21
+
22
+ Example usage:
23
+ >>> import mplang as mp
24
+ >>> # Enable logging with INFO level
25
+ >>> mp.setup_logging(level="INFO")
26
+ >>> # Enable logging with DEBUG level and write to file
27
+ >>> mp.setup_logging(level="DEBUG", filename="mplang.log")
28
+ >>> # Customize format
29
+ >>> mp.setup_logging(
30
+ ... level="DEBUG", format="%(asctime)s [%(name)s] %(levelname)s: %(message)s"
31
+ ... )
32
+ """
33
+
34
+ import logging
35
+ import sys
36
+ from typing import Any, Literal
37
+
38
+ # Root logger for all MPLang components
39
+ MPLANG_LOGGER_NAME = "mplang"
40
+
41
+ # Default format for log messages
42
+ DEFAULT_FORMAT = "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
43
+ DEFAULT_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
44
+
45
+
46
+ def setup_logging(
47
+ level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] = "INFO",
48
+ format: str | None = None,
49
+ date_format: str | None = None,
50
+ filename: str | None = None,
51
+ stream: Any = None, # type: ignore[type-arg]
52
+ force: bool = False,
53
+ propagate: bool = False,
54
+ ) -> None:
55
+ """
56
+ Configure logging for MPLang.
57
+
58
+ This function sets up a logger for all MPLang components. By default,
59
+ MPLang uses a NullHandler to suppress log output when used as a library.
60
+ Call this function to enable logging with custom settings.
61
+
62
+ For unified application logging (application + mplang logs in same file):
63
+ - Option 1: Configure Python's root logger, then call setup_logging(propagate=True)
64
+ - Option 2: Just call setup_logging(filename="app.log") to add mplang logs to that file
65
+
66
+ Args:
67
+ level: Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL). Default is INFO.
68
+ format: Custom log format string. If None, uses default format.
69
+ date_format: Custom date format string. If None, uses default format.
70
+ filename: If provided, log to this file in addition to stream output.
71
+ stream: Stream to log to (e.g., sys.stdout, sys.stderr). Default is sys.stderr.
72
+ Set to False to disable stream output (only use file or propagation).
73
+ force: If True, remove existing handlers before adding new ones.
74
+ propagate: If True, allow logs to propagate to parent loggers (useful for
75
+ unified application logging). If False (default), mplang manages
76
+ its own handlers independently.
77
+
78
+ Example:
79
+ >>> import mplang as mp
80
+ >>> # Enable debug logging to stderr
81
+ >>> mp.setup_logging(level="DEBUG")
82
+ >>> # Log mplang to file only
83
+ >>> mp.setup_logging(level="INFO", filename="mplang.log", stream=False)
84
+ >>>
85
+ >>> # Unified application logging (recommended for applications)
86
+ >>> import logging
87
+ >>> logging.basicConfig(
88
+ ... level=logging.INFO,
89
+ ... filename="app.log",
90
+ ... format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
91
+ ... )
92
+ >>> mp.setup_logging(level="INFO", propagate=True) # Inherits app config
93
+ """
94
+ # Get the root logger for mplang
95
+ logger = logging.getLogger(MPLANG_LOGGER_NAME)
96
+
97
+ # Set log level
98
+ log_level = getattr(logging, level.upper())
99
+ logger.setLevel(log_level)
100
+
101
+ # If propagate=True, automatically remove NullHandler to avoid confusion
102
+ # (NullHandler doesn't prevent propagation, but its presence is confusing)
103
+ if propagate and not force:
104
+ # Check if there's only a NullHandler
105
+ if len(logger.handlers) == 1 and isinstance(
106
+ logger.handlers[0], logging.NullHandler
107
+ ):
108
+ force = True # Auto-enable force to remove NullHandler
109
+
110
+ # Remove existing handlers if force=True
111
+ if force:
112
+ for handler in logger.handlers[:]:
113
+ logger.removeHandler(handler)
114
+
115
+ # Set propagation behavior
116
+ logger.propagate = propagate
117
+
118
+ # If propagate is True and no handlers specified, just set level and propagate
119
+ # This allows mplang logs to use the application's logging configuration
120
+ if propagate and not filename and stream is None:
121
+ return
122
+
123
+ # Use default format if not provided
124
+ log_format = format or DEFAULT_FORMAT
125
+ log_date_format = date_format or DEFAULT_DATE_FORMAT
126
+ formatter = logging.Formatter(log_format, datefmt=log_date_format)
127
+
128
+ # Add stream handler (default to stderr, or skip if stream=False)
129
+ if stream is not False:
130
+ if stream is None:
131
+ stream = sys.stderr
132
+ stream_handler = logging.StreamHandler(stream)
133
+ stream_handler.setLevel(log_level)
134
+ stream_handler.setFormatter(formatter)
135
+ logger.addHandler(stream_handler)
136
+
137
+ # Add file handler if filename is provided
138
+ if filename:
139
+ file_handler = logging.FileHandler(filename)
140
+ file_handler.setLevel(log_level)
141
+ file_handler.setFormatter(formatter)
142
+ logger.addHandler(file_handler)
143
+
144
+
145
+ def disable_logging() -> None:
146
+ """
147
+ Disable all MPLang logging by adding a NullHandler.
148
+
149
+ This is useful for testing or when you want to completely suppress
150
+ MPLang log output.
151
+
152
+ Example:
153
+ >>> import mplang as mp
154
+ >>> mp.disable_logging()
155
+ """
156
+ logger = logging.getLogger(MPLANG_LOGGER_NAME)
157
+ # Remove all existing handlers
158
+ for handler in logger.handlers[:]:
159
+ logger.removeHandler(handler)
160
+ # Add NullHandler to suppress all output
161
+ logger.addHandler(logging.NullHandler())
162
+ logger.propagate = False
163
+
164
+
165
+ def get_logger(name: str) -> logging.Logger:
166
+ """
167
+ Get a logger for a specific MPLang module.
168
+
169
+ This function should be used by all MPLang modules to create their loggers.
170
+ The logger name will be prefixed with 'mplang' automatically if not already.
171
+
172
+ Args:
173
+ name: Module name, typically __name__ from the calling module.
174
+
175
+ Returns:
176
+ A logger instance for the specified module.
177
+
178
+ Example:
179
+ >>> # In mplang/edsl/tracer.py
180
+ >>> logger = get_logger(__name__) # Creates 'mplang.edsl.tracer' logger
181
+ """
182
+ # Ensure the logger name is under mplang hierarchy
183
+ if not name.startswith(MPLANG_LOGGER_NAME):
184
+ # Handle cases where __name__ might be a relative module name
185
+ if name.startswith("mplang."):
186
+ pass # Already correct
187
+ elif "." in name:
188
+ # It's a submodule, but not under mplang, so prefix it.
189
+ name = f"{MPLANG_LOGGER_NAME}.{name}"
190
+ else:
191
+ # Relative module name, prefix with mplang
192
+ name = f"{MPLANG_LOGGER_NAME}.{name}"
193
+
194
+ return logging.getLogger(name)
195
+
196
+
197
+ # Initialize with NullHandler by default (library mode)
198
+ # Applications using MPLang should call setup_logging() to enable logging
199
+ _root_logger = logging.getLogger(MPLANG_LOGGER_NAME)
200
+ if not _root_logger.handlers:
201
+ _root_logger.addHandler(logging.NullHandler())
202
+ _root_logger.propagate = False