naeural-client 3.2.0__tar.gz → 3.2.3__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 (181) hide show
  1. {naeural_client-3.2.0 → naeural_client-3.2.3}/PKG-INFO +1 -1
  2. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/_ver.py +1 -1
  3. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/base/generic_session.py +108 -30
  4. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/bc/__init__.py +1 -1
  5. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/bc/base.py +7 -7
  6. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/const/environment.py +3 -0
  7. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/logger_mixins/utils_mixin.py +78 -0
  8. {naeural_client-3.2.0 → naeural_client-3.2.3}/pyproject.toml +1 -1
  9. naeural_client-3.2.3/template.env +23 -0
  10. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/_checks/session_check.py +0 -1
  11. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/_checks/workload_check.py +3 -3
  12. naeural_client-3.2.3/xperimental/test.py +74 -0
  13. {naeural_client-3.2.0 → naeural_client-3.2.3}/.devcontainer/Dockerfile +0 -0
  14. {naeural_client-3.2.0 → naeural_client-3.2.3}/.devcontainer/devcontainer.json +0 -0
  15. {naeural_client-3.2.0 → naeural_client-3.2.3}/.gitattributes +0 -0
  16. {naeural_client-3.2.0 → naeural_client-3.2.3}/.github/workflows/python-publish.yml +0 -0
  17. {naeural_client-3.2.0 → naeural_client-3.2.3}/.gitignore +0 -0
  18. {naeural_client-3.2.0 → naeural_client-3.2.3}/.vscode/launch.json +0 -0
  19. {naeural_client-3.2.0 → naeural_client-3.2.3}/LICENSE +0 -0
  20. {naeural_client-3.2.0 → naeural_client-3.2.3}/README.md +0 -0
  21. {naeural_client-3.2.0 → naeural_client-3.2.3}/TODOs.md +0 -0
  22. {naeural_client-3.2.0 → naeural_client-3.2.3}/__init__.py +0 -0
  23. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/__init__.py +0 -0
  24. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/base/__init__.py +0 -0
  25. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/base/distributed_custom_code_presets.py +0 -0
  26. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/base/instance.py +0 -0
  27. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/base/payload/__init__.py +0 -0
  28. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/base/payload/payload.py +0 -0
  29. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/base/pipeline.py +0 -0
  30. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/base/plugin_template.py +0 -0
  31. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/base/responses.py +0 -0
  32. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/base/transaction.py +0 -0
  33. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/base/webapp_pipeline.py +0 -0
  34. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/base_decentra_object.py +0 -0
  35. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/bc/chain.py +0 -0
  36. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/bc/ec.py +0 -0
  37. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/bc/evm.py +0 -0
  38. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/certs/__init__.py +0 -0
  39. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/certs/a0d9818f.ala.eu-central-1.emqxsl.com.crt +0 -0
  40. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/certs/r9092118.ala.eu-central-1.emqxsl.com.crt +0 -0
  41. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/certs/s624dbd4.ala.us-east-1.emqxsl.com.crt +0 -0
  42. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/cli/README.md +0 -0
  43. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/cli/cli.py +0 -0
  44. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/cli/cli_commands.py +0 -0
  45. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/cli/nodes.py +0 -0
  46. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/cli/oracles.py +0 -0
  47. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/code_cheker/__init__.py +0 -0
  48. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/code_cheker/base.py +0 -0
  49. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/code_cheker/checker.py +0 -0
  50. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/comm/__init__.py +0 -0
  51. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/comm/amqp_wrapper.py +0 -0
  52. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/comm/mqtt_wrapper.py +0 -0
  53. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/const/README.md +0 -0
  54. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/const/__init__.py +0 -0
  55. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/const/apps.py +0 -0
  56. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/const/base.py +0 -0
  57. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/const/comms.py +0 -0
  58. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/const/evm_net.py +0 -0
  59. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/const/formatter.py +0 -0
  60. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/const/heartbeat.py +0 -0
  61. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/const/misc.py +0 -0
  62. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/const/payload.py +0 -0
  63. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/default/__init__.py +0 -0
  64. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/default/instance/__init__.py +0 -0
  65. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/default/instance/chain_dist_custom_job_01_plugin.py +0 -0
  66. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/default/instance/custom_webapi_01_plugin.py +0 -0
  67. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/default/instance/net_mon_01_plugin.py +0 -0
  68. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/default/instance/telegram_basic_bot_01_plugin.py +0 -0
  69. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/default/instance/telegram_conversational_bot_01_plugin.py +0 -0
  70. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/default/instance/view_scene_01_plugin.py +0 -0
  71. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/default/session/mqtt_session.py +0 -0
  72. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/io_formatter/__init__.py +0 -0
  73. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/io_formatter/base/__init__.py +0 -0
  74. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/io_formatter/base/base_formatter.py +0 -0
  75. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/io_formatter/default/__init__.py +0 -0
  76. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/io_formatter/default/a_dummy.py +0 -0
  77. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/io_formatter/default/aixp1.py +0 -0
  78. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/io_formatter/default/default.py +0 -0
  79. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/io_formatter/io_formatter_manager.py +0 -0
  80. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/ipfs/__init__.py +0 -0
  81. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/ipfs/ifps_keygen +0 -0
  82. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/ipfs/ipfs_setup/ipfs.service +0 -0
  83. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/ipfs/ipfs_setup/launch_service.sh +0 -0
  84. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/ipfs/ipfs_setup/restart.sh +0 -0
  85. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/ipfs/ipfs_setup/run.sh +0 -0
  86. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/ipfs/ipfs_setup/setup.sh +0 -0
  87. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/ipfs/ipfs_setup/show.sh +0 -0
  88. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/ipfs/ipfs_setup/write_key.sh +0 -0
  89. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/ipfs/r1fs.py +0 -0
  90. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/__init__.py +0 -0
  91. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/base_logger.py +0 -0
  92. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/logger_mixins/__init__.py +0 -0
  93. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/logger_mixins/class_instance_mixin.py +0 -0
  94. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/logger_mixins/computer_vision_mixin.py +0 -0
  95. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/logger_mixins/datetime_mixin.py +0 -0
  96. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/logger_mixins/download_mixin.py +0 -0
  97. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/logger_mixins/general_serialization_mixin.py +0 -0
  98. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/logger_mixins/json_serialization_mixin.py +0 -0
  99. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/logger_mixins/pickle_serialization_mixin.py +0 -0
  100. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/logger_mixins/process_mixin.py +0 -0
  101. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/logger_mixins/resource_size_mixin.py +0 -0
  102. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/logger_mixins/timers_mixin.py +0 -0
  103. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/logger_mixins/upload_mixin.py +0 -0
  104. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/small_logger.py +0 -0
  105. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/tzlocal/__init__.py +0 -0
  106. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/tzlocal/unix.py +0 -0
  107. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/tzlocal/utils.py +0 -0
  108. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/tzlocal/win32.py +0 -0
  109. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/logging/tzlocal/windows_tz.py +0 -0
  110. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/plugins_manager_mixin.py +0 -0
  111. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/utils/__init__.py +0 -0
  112. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/utils/comm_utils.py +0 -0
  113. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/utils/config.py +0 -0
  114. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/utils/dotenv.py +0 -0
  115. {naeural_client-3.2.0 → naeural_client-3.2.3}/naeural_client/utils/oracle_sync/oracle_tester.py +0 -0
  116. {naeural_client-3.2.0 → naeural_client-3.2.3}/r1ctl.MD +0 -0
  117. {naeural_client-3.2.0 → naeural_client-3.2.3}/requirements.txt +0 -0
  118. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/.example_env +0 -0
  119. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/8. custom_code_fastapi_assets/index.html +0 -0
  120. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/9. code_sandbox_from_scratch_assets/index.html +0 -0
  121. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/_example_pk_sdk.pem +0 -0
  122. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex01_part1_connect.py +0 -0
  123. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex01_part2_filter.py +0 -0
  124. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex01_part3_adv_filter.py +0 -0
  125. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex02_part1_deploy_webapi.py +0 -0
  126. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex02_part2_deploy_plugin.py +0 -0
  127. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex02_part3_deploy_r1fs_test.py +0 -0
  128. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex03_custom_code_on_one_remote__example_1.py +0 -0
  129. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex04_custom_code_on_one_remote__example_2.py +0 -0
  130. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex05_custom_code_on_one_remote__example_3.py +0 -0
  131. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex06_custom_code_on_multiple_remotes__example_1.py +0 -0
  132. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex07_custom_code_on_multiple_remotes__example_2.py +0 -0
  133. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex08_custom_webapi.py +0 -0
  134. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex09_code_sandbox_from_scratch.py +0 -0
  135. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex10_telegram_echo_bot.py +0 -0
  136. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex11_telegram_blackjack_bot.py +0 -0
  137. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex12_telegram_smart_bot.py +0 -0
  138. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex13_launch_repo_based_webapp.py +0 -0
  139. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/ex14_wallets.py +0 -0
  140. {naeural_client-3.2.0 → naeural_client-3.2.3}/tutorials/video_presentation/1. hello_world.ipynb +0 -0
  141. {naeural_client-3.2.0 → naeural_client-3.2.3}/winrun.bat +0 -0
  142. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/README.md +0 -0
  143. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/_checks/cstore_check.py +0 -0
  144. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/_checks/dauth_check.py +0 -0
  145. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/_checks/keys_check.py +0 -0
  146. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/_checks/ora_check.py +0 -0
  147. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/_checks/ora_sign_check.py +0 -0
  148. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/_checks/owner_check.py +0 -0
  149. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/_checks/payload_check.py +0 -0
  150. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/_checks/w3_auth_check.py +0 -0
  151. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/_checks/w3_oracles_check.py +0 -0
  152. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/dates/check_date.py +0 -0
  153. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/debug/close_pipeline.py +0 -0
  154. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/decentralized/chain_dist_example.py +0 -0
  155. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/decentralized/chain_dist_example_initiator.py +0 -0
  156. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/decentralized/chain_dist_example_worker.py +0 -0
  157. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/enc_dec/enc_dec_test.py +0 -0
  158. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/eth/balance.py +0 -0
  159. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/eth/eth_sign.py +0 -0
  160. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/eth/info.md +0 -0
  161. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/eth/send.py +0 -0
  162. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/eth/send_many.py +0 -0
  163. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/eth/sign.py +0 -0
  164. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/multi-enc-dec/multi_test1.py +0 -0
  165. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/multi-enc-dec/multi_test2.py +0 -0
  166. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/pipelines/start.py +0 -0
  167. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/pipelines/stop.py +0 -0
  168. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/sign/simple_payload_checker.py +0 -0
  169. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/sign/test_sign1.py +0 -0
  170. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/sign/test_sign2.py +0 -0
  171. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/utils/get_documentation.py +0 -0
  172. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/various/attach_example.py +0 -0
  173. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/various/ex1.py +0 -0
  174. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/various/hello.py +0 -0
  175. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/various/remote_exec.py +0 -0
  176. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/various/save_images.py +0 -0
  177. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/wl/wl_add.py +0 -0
  178. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/xarchive/_tutorials/3. simple_real_time_custom_code.py +0 -0
  179. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/xarchive/_tutorials/4. real_time_custom_code_2.py +0 -0
  180. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/xarchive/_tutorials/8. chatbot.py +0 -0
  181. {naeural_client-3.2.0 → naeural_client-3.2.3}/xperimental/xarchive/test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: naeural_client
3
- Version: 3.2.0
3
+ Version: 3.2.3
4
4
  Summary: `naeural_client` is the Python SDK required for client app development for the Naeural Edge Protocol Edge Protocol framework
5
5
  Project-URL: Homepage, https://github.com/NaeuralEdgeProtocol/naeural_client
6
6
  Project-URL: Bug Tracker, https://github.com/NaeuralEdgeProtocol/naeural_client/issues
@@ -1,4 +1,4 @@
1
- __VER__ = "3.2.0"
1
+ __VER__ = "3.2.3"
2
2
 
3
3
  if __name__ == "__main__":
4
4
  with open("pyproject.toml", "rt") as fd:
@@ -19,7 +19,7 @@ from time import sleep
19
19
  from time import time as tm
20
20
 
21
21
  from ..base_decentra_object import BaseDecentrAIObject
22
- from ..bc import DefaultBlockEngine, _DotDict
22
+ from ..bc import DefaultBlockEngine, _DotDict, EE_VPN_IMPL
23
23
  from ..const import (
24
24
  COMMANDS, ENVIRONMENT, HB, PAYLOAD_DATA, STATUS_TYPE,
25
25
  PLUGIN_SIGNATURES, DEFAULT_PIPELINES,
@@ -45,7 +45,7 @@ from ..utils.config import (
45
45
 
46
46
  DEBUG_MQTT_SERVER = "r9092118.ala.eu-central-1.emqxsl.com"
47
47
  SDK_NETCONFIG_REQUEST_DELAY = 300
48
-
48
+ SHOW_PENDING_THRESHOLD = 3600
49
49
 
50
50
 
51
51
 
@@ -229,14 +229,10 @@ class GenericSession(BaseDecentrAIObject):
229
229
 
230
230
  # TODO: maybe read config from file?
231
231
  self._config = {**self.default_config, **config}
232
-
233
- if root_topic is not None:
234
- for key in self._config.keys():
235
- if isinstance(self._config[key], dict) and 'TOPIC' in self._config[key]:
236
- if isinstance(self._config[key]["TOPIC"], str) and self._config[key]["TOPIC"].startswith("{}"):
237
- nr_empty = self._config[key]["TOPIC"].count("{}")
238
- self._config[key]["TOPIC"] = self._config[key]["TOPIC"].format(root_topic, *(["{}"] * (nr_empty - 1)))
239
- # end if root_topic
232
+
233
+
234
+
235
+ self.comms_root_topic = root_topic
240
236
 
241
237
  self.__auto_configuration = auto_configuration
242
238
 
@@ -245,8 +241,8 @@ class GenericSession(BaseDecentrAIObject):
245
241
 
246
242
  self.name = name
247
243
  self.silent = silent
248
-
249
- self.__eth_enabled = eth_enabled
244
+
245
+ self._eth_enabled = eth_enabled
250
246
 
251
247
  self.encrypt_comms = encrypt_comms
252
248
 
@@ -354,6 +350,22 @@ class GenericSession(BaseDecentrAIObject):
354
350
  # end bc_engine
355
351
  # END TODO
356
352
 
353
+
354
+ str_topic = os.environ.get(ENVIRONMENT.EE_ROOT_TOPIC_ENV_KEY, self.comms_root_topic)
355
+
356
+ if str_topic != self.comms_root_topic:
357
+ self.P(f"Changing root topic from '{self.comms_root_topic}' to '{str_topic}'", color='y')
358
+ self.comms_root_topic = str_topic
359
+
360
+ if self.comms_root_topic is not None:
361
+ for key in self._config.keys():
362
+ if isinstance(self._config[key], dict) and 'TOPIC' in self._config[key]:
363
+ if isinstance(self._config[key]["TOPIC"], str) and self._config[key]["TOPIC"].startswith("{}"):
364
+ nr_empty = self._config[key]["TOPIC"].count("{}")
365
+ self._config[key]["TOPIC"] = self._config[key]["TOPIC"].format(self.comms_root_topic, *(["{}"] * (nr_empty - 1)))
366
+ # end if root_topic
367
+
368
+
357
369
  ## last config step
358
370
  self.__fill_config(
359
371
  host=self.__host,
@@ -830,8 +842,12 @@ class GenericSession(BaseDecentrAIObject):
830
842
  # this is for legacy and custom implementation where heartbeats still contain
831
843
  # the pipeline configuration.
832
844
  pipeline_names = [x.get(PAYLOAD_DATA.NAME, None) for x in msg_active_configs]
845
+ received_plugins = dict_msg.get(HB.ACTIVE_PLUGINS, [])
833
846
  self.D(f'<HB> Processing pipelines from <{short_addr}>:{pipeline_names}', color='y')
834
- self.__process_node_pipelines(msg_node_addr, msg_active_configs)
847
+ new_pipeliens = self.__process_node_pipelines(
848
+ node_addr=msg_node_addr, pipelines=msg_active_configs,
849
+ plugins_statuses=received_plugins,
850
+ )
835
851
 
836
852
  # TODO: move this call in `__on_message_default_callback`
837
853
  if self.__maybe_ignore_message(msg_node_addr):
@@ -1113,19 +1129,23 @@ class GenericSession(BaseDecentrAIObject):
1113
1129
  return
1114
1130
 
1115
1131
  try:
1132
+ if EE_VPN_IMPL and self._eth_enabled:
1133
+ self.P("Disabling ETH for VPN implementation", color='r')
1134
+ self._eth_enabled = False
1135
+
1116
1136
  self.bc_engine = DefaultBlockEngine(
1117
1137
  log=self.log,
1118
1138
  name=self.name,
1119
1139
  config=blockchain_config,
1120
1140
  verbosity=self._verbosity,
1121
1141
  user_config=user_config,
1122
- eth_enabled=self.__eth_enabled,
1142
+ eth_enabled=self._eth_enabled,
1123
1143
  )
1124
1144
  except:
1125
1145
  raise ValueError("Failure in private blockchain setup:\n{}".format(traceback.format_exc()))
1126
1146
 
1127
1147
  # extra setup flag for re-connections with same multiton instance
1128
- self.bc_engine.set_eth_flag(self.__eth_enabled)
1148
+ self.bc_engine.set_eth_flag(self._eth_enabled)
1129
1149
  return
1130
1150
 
1131
1151
  def __start_main_loop_thread(self):
@@ -2868,8 +2888,8 @@ class GenericSession(BaseDecentrAIObject):
2868
2888
  telegram_bot_token=None,
2869
2889
  telegram_bot_token_env_key=ENVIRONMENT.TELEGRAM_BOT_TOKEN_ENV_KEY,
2870
2890
  telegram_bot_name=None,
2871
- telegram_bot_name_env_key=ENVIRONMENT.TELEGRAM_BOT_NAME_ENV_KEY,
2872
-
2891
+ telegram_bot_name_env_key=ENVIRONMENT.TELEGRAM_BOT_NAME_ENV_KEY,
2892
+ processor_handler=None,
2873
2893
  system_prompt=None,
2874
2894
  agent_type="API",
2875
2895
  api_token_env_key=ENVIRONMENT.TELEGRAM_API_AGENT_TOKEN_ENV_KEY,
@@ -2943,6 +2963,7 @@ class GenericSession(BaseDecentrAIObject):
2943
2963
  if telegram_bot_name is None:
2944
2964
  message = f"Warning! No Telegram bot name provided as via env {ENVIRONMENT.TELEGRAM_BOT_NAME_ENV_KEY} or explicitly as `telegram_bot_name` param."
2945
2965
  raise ValueError(message)
2966
+
2946
2967
 
2947
2968
 
2948
2969
  pipeline: Pipeline = self.create_pipeline(
@@ -2950,6 +2971,10 @@ class GenericSession(BaseDecentrAIObject):
2950
2971
  name=name,
2951
2972
  # default TYPE is "Void"
2952
2973
  )
2974
+
2975
+ proc_func_args, proc_func_base64_code =[], None
2976
+ if processor_handler is not None:
2977
+ _, proc_func_args, proc_func_base64_code = pipeline._get_method_data(processor_handler)
2953
2978
 
2954
2979
 
2955
2980
  obfuscated_token = telegram_bot_token[:4] + "*" * (len(telegram_bot_token) - 4)
@@ -2957,8 +2982,13 @@ class GenericSession(BaseDecentrAIObject):
2957
2982
  instance = pipeline.create_plugin_instance(
2958
2983
  signature=signature,
2959
2984
  instance_id=self.log.get_unique_id(),
2985
+
2960
2986
  telegram_bot_token=telegram_bot_token,
2961
2987
  telegram_bot_name=telegram_bot_name,
2988
+
2989
+ processor_handler=proc_func_base64_code, # not mandatory
2990
+ processor_handler_args=proc_func_args, # not mandatory
2991
+
2962
2992
  system_prompt=system_prompt,
2963
2993
  agent_type=agent_type,
2964
2994
  api_token=api_token,
@@ -3289,6 +3319,50 @@ class GenericSession(BaseDecentrAIObject):
3289
3319
  return dct_result
3290
3320
 
3291
3321
 
3322
+ def date_to_readable(self, date, check_none=False, start_time=None, pending_threshold=SHOW_PENDING_THRESHOLD):
3323
+ """
3324
+ Convert a date to a human-readable format.
3325
+
3326
+ Parameters
3327
+ ----------
3328
+
3329
+ date : str
3330
+ The date to convert.
3331
+ check_none : bool, optional
3332
+ If True, and the date is None it will check if too much time passed from the start time.
3333
+ If too much time passed, it will return 'Error!', otherwise, it will return 'Pending'.
3334
+ If False, it will return 'Never' if the date is None.
3335
+ Defaults to False.
3336
+ start_time : str, optional
3337
+ The start time to compare with the date in case it is None. Defaults to None.
3338
+ pending_threshold : int, optional
3339
+ The threshold in seconds to consider a date as pending. Defaults to SHOW_PENDING_THRESHOLD.
3340
+ If the time passed since start_time is greater than pending_threshold and
3341
+ check_none is set to True, it will return 'Error!'.
3342
+
3343
+ Returns
3344
+ -------
3345
+
3346
+ str
3347
+ The human-readable date.
3348
+ """
3349
+ if date is None:
3350
+ if not check_none or start_time is None:
3351
+ return 'Never'
3352
+ # endif not check_none
3353
+ start_dt = self.log.str_to_date(start_time, fmt='%Y-%m-%d %H:%M:%S.%f')
3354
+ since_start = (dt.now() - start_dt).total_seconds()
3355
+ if since_start > pending_threshold:
3356
+ return 'Error!'
3357
+ return 'Pending'
3358
+ # endif date is None
3359
+ if date.startswith('1970'):
3360
+ return 'Never'
3361
+ if '.' in date:
3362
+ date = date.split('.')[0]
3363
+ return date
3364
+
3365
+
3292
3366
  def get_nodes_apps(
3293
3367
  self,
3294
3368
  node=None,
@@ -3379,16 +3453,18 @@ class GenericSession(BaseDecentrAIObject):
3379
3453
  if len(instance_status) == 0:
3380
3454
  # this instance is only present in config but is NOT loaded so ignore it
3381
3455
  continue
3382
- start_time = instance_status.get('INIT_TIMESTAMP')
3383
- last_probe = instance_status.get('EXEC_TIMESTAMP')
3384
- last_data = instance_status.get('LAST_PAYLOAD_TIME')
3385
- dates = [start_time, last_probe, last_data]
3386
- for i in range(len(dates)):
3387
- if isinstance(dates[i], str):
3388
- if dates[i].startswith('1970'):
3389
- dates[i] = 'Never'
3390
- elif '.' in dates[i]:
3391
- dates[i] = dates[i].split('.')[0]
3456
+ start_time = instance_status.get(HB.ACTIVE_PLUGINS_INFO.INIT_TIMESTAMP)
3457
+ last_probe = instance_status.get(HB.ACTIVE_PLUGINS_INFO.EXEC_TIMESTAMP)
3458
+ last_data = instance_status.get(HB.ACTIVE_PLUGINS_INFO.LAST_PAYLOAD_TIME)
3459
+ dates = [start_time, last_data]
3460
+ error_dates = [
3461
+ instance_status.get(HB.ACTIVE_PLUGINS_INFO.FIRST_ERROR_TIME),
3462
+ instance_status.get(HB.ACTIVE_PLUGINS_INFO.LAST_ERROR_TIME),
3463
+ ]
3464
+ dates = [self.date_to_readable(x, check_none=False) for x in dates]
3465
+ error_dates = [self.date_to_readable(x, check_none=False) for x in error_dates]
3466
+ last_probe = self.date_to_readable(last_probe, check_none=True, start_time=start_time)
3467
+
3392
3468
  lst_plugin_instance_data.append({
3393
3469
  'Node' : node,
3394
3470
  'Owner' : pipeline_owner,
@@ -3397,8 +3473,9 @@ class GenericSession(BaseDecentrAIObject):
3397
3473
  'Plugin': instance.signature,
3398
3474
  'Id': instance.instance_id,
3399
3475
  'Start' : dates[0],
3400
- 'Probe' : dates[1],
3401
- 'Data' : dates[2],
3476
+ 'Probe' : last_probe,
3477
+ 'Data' : dates[1],
3478
+ 'LastError': error_dates[1],
3402
3479
  })
3403
3480
  # endfor instances in app
3404
3481
  # endfor apps
@@ -3408,7 +3485,8 @@ class GenericSession(BaseDecentrAIObject):
3408
3485
  log_with_color(f'Node(s) {nodes} not found. Please check the configuration.', color='r')
3409
3486
  return
3410
3487
  if as_df:
3411
- df = pd.DataFrame(lst_plugin_instance_data)
3488
+ color_condition = lambda x: (x['LastError'] != 'Never' or x['Probe'] == 'Error!')
3489
+ df = self.log.colored_dataframe(lst_plugin_instance_data, color_condition=color_condition)
3412
3490
  if not (df.empty or df.shape[0] == 0):
3413
3491
  df['Node'] = df['Node'].apply(lambda x: self._shorten_addr(x))
3414
3492
  df['Owner'] = df['Owner'].apply(lambda x: self._shorten_addr(x))
@@ -1,3 +1,3 @@
1
1
  from .ec import BaseBCEllipticCurveEngine
2
- from .base import BCct, _DotDict, _ComplexJsonEncoder, VerifyMessage
2
+ from .base import BCct, _DotDict, _ComplexJsonEncoder, VerifyMessage, EE_VPN_IMPL
3
3
  DefaultBlockEngine = BaseBCEllipticCurveEngine
@@ -319,7 +319,7 @@ class BaseBlockEngine(_EVMMixin):
319
319
  self.__config = config
320
320
  self.__ensure_ascii_payloads = ensure_ascii_payloads
321
321
 
322
- self.__eth_enabled = eth_enabled
322
+ self._eth_enabled = eth_enabled
323
323
 
324
324
  if user_config:
325
325
  user_folder = get_user_folder()
@@ -350,12 +350,12 @@ class BaseBlockEngine(_EVMMixin):
350
350
 
351
351
  @property
352
352
  def eth_enabled(self):
353
- return self.__eth_enabled
353
+ return self._eth_enabled
354
354
 
355
355
 
356
356
  def set_eth_flag(self, value):
357
- if value != self.__eth_enabled:
358
- self.__eth_enabled = value
357
+ if value != self._eth_enabled:
358
+ self._eth_enabled = value
359
359
  self.log.P("Changed eth_enabled to {}".format(value), color='d')
360
360
  return
361
361
 
@@ -377,7 +377,7 @@ class BaseBlockEngine(_EVMMixin):
377
377
 
378
378
  def _init(self):
379
379
  self.P(
380
- f"Initializing BC-engine (ETH_ENABLED={self.__eth_enabled})...", verbosity=1
380
+ f"Initializing BC-engine (ETH_ENABLED={self._eth_enabled})...", verbosity=1
381
381
  )
382
382
 
383
383
  if True:
@@ -414,7 +414,7 @@ class BaseBlockEngine(_EVMMixin):
414
414
  self.__eth_address = self._get_eth_address()
415
415
  self.__eth_account = self._get_eth_account()
416
416
  ### end Ethereum
417
- if self.__eth_enabled:
417
+ if self._eth_enabled:
418
418
  self.P(
419
419
  "{} / ETH: {} ({})".format(self.address, self.eth_address, self.evm_network), boxed=True, verbosity=1,
420
420
  color='g'
@@ -1212,7 +1212,7 @@ class BaseBlockEngine(_EVMMixin):
1212
1212
  dct_data[BCct.SIGN] = result
1213
1213
  dct_data[BCct.SENDER] = self.address
1214
1214
 
1215
- if self.__eth_enabled:
1215
+ if self._eth_enabled:
1216
1216
  dct_data[BCct.ETH_SENDER] = self.eth_address
1217
1217
  ### add eth signature
1218
1218
  dct_data[BCct.ETH_SIGN] = "0xBEEF"
@@ -28,8 +28,11 @@ class ENVIRONMENT:
28
28
 
29
29
  EE_SECURED = 'EE_SECURED'
30
30
  AIXP_SECURED = 'AIXP_SECURED'
31
+ EE_MQTT_SECURED = 'EE_MQTT_SECURED'
31
32
 
32
33
  TELEGRAM_BOT_TOKEN_ENV_KEY = 'EE_TELEGRAM_BOT_TOKEN'
33
34
  TELEGRAM_BOT_NAME_ENV_KEY = 'EE_TELEGRAM_BOT_NAME'
34
35
 
35
36
  TELEGRAM_API_AGENT_TOKEN_ENV_KEY = 'EE_TELEGRAM_API_AGENT_TOKEN'
37
+
38
+ EE_ROOT_TOPIC_ENV_KEY = 'EE_ROOT_TOPIC'
@@ -7,12 +7,82 @@ import hashlib
7
7
  import numpy as np
8
8
  import traceback
9
9
  import random
10
+ import pandas as pd
10
11
  from queue import Queue
11
12
 
12
13
  from collections import OrderedDict, deque, defaultdict
13
14
 
14
15
  from io import BytesIO, TextIOWrapper
15
16
 
17
+ class ColorDataFrame(pd.DataFrame):
18
+ """
19
+ A DataFrame subclass that colors specific rows red when printed in a console.
20
+
21
+ Parameters
22
+ ----------
23
+ *args : tuple
24
+ Positional arguments passed to the pd.DataFrame constructor.
25
+ color_condition : callable, optional
26
+ A function that takes a row (pd.Series) and returns True if the row should be
27
+ highlighted in red, or False otherwise.
28
+ **kwargs : dict
29
+ Keyword arguments passed to the pd.DataFrame constructor.
30
+
31
+ Returns
32
+ -------
33
+ ColorDataFrame
34
+ A subclass of DataFrame that overrides the to_string method for coloring.
35
+
36
+ Examples
37
+ --------
38
+
39
+ df = ColorDataFrame(
40
+ df,
41
+ color_condition=lambda row: row['value'] > 9
42
+ )
43
+ print(df)
44
+ """
45
+
46
+ _metadata = ['_color_condition']
47
+
48
+ def __init__(self, *args, color_condition=lambda row: False, **kwargs):
49
+ super().__init__(*args, **kwargs)
50
+ # Store the condition function as an attribute
51
+ self._color_condition = color_condition
52
+ return
53
+
54
+ def to_string(self, *args, **kwargs):
55
+ """
56
+ Overridden version of to_string that applies ANSI colors to rows
57
+ matching the condition.
58
+ """
59
+ original_string = super().to_string(*args, **kwargs)
60
+ # Split the original string into lines
61
+ lines = original_string.split('\n')
62
+
63
+ header_lines = lines[:1]
64
+ data_lines = lines[1:]
65
+
66
+ colored_data_lines = []
67
+ for row_index, row_line in enumerate(data_lines):
68
+ # Attempt to parse the index from the leftmost part of each row line
69
+ try:
70
+ # The row's index in the actual DataFrame
71
+ df_index = self.index[row_index]
72
+ except IndexError:
73
+ colored_data_lines.append(row_line)
74
+ continue
75
+
76
+ # Check if row meets the color condition
77
+ if self._color_condition(self.loc[df_index]):
78
+ # Red color ANSI: \033[91m ... \033[0m
79
+ row_line = f"\033[91m{row_line}\033[0m"
80
+
81
+ colored_data_lines.append(row_line)
82
+
83
+ return "\n".join(header_lines + colored_data_lines)
84
+
85
+
16
86
 
17
87
  adjectives = [
18
88
  'able', 'arco', 'arty', 'awed', 'awny', 'bald', 'base', 'bass', 'bent', 'best', 'boxy',
@@ -64,6 +134,14 @@ class _UtilsMixin(object):
64
134
 
65
135
  def __init__(self):
66
136
  super(_UtilsMixin, self).__init__()
137
+
138
+
139
+ @staticmethod
140
+ def colored_dataframe(df, color_condition=lambda row: False):
141
+ """
142
+ A DataFrame subclass that colors specific rows red when printed in a console.
143
+ """
144
+ return ColorDataFrame(df, color_condition=color_condition)
67
145
 
68
146
  @staticmethod
69
147
  def get_function_parameters(function):
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "naeural_client"
7
- version = "3.2.0"
7
+ version = "3.2.3"
8
8
  authors = [
9
9
  { name="Andrei Ionut Damian", email="andrei.damian@me.com" },
10
10
  { name="Cristan Bleotiu", email="cristibleotiu@gmail.com" },
@@ -0,0 +1,23 @@
1
+ EE_MQTT_HOST=192.168.1.1
2
+ EE_MQTT_PORT=1883
3
+ EE_MQTT_USER=local-user
4
+ EE_MQTT=some-p@55word
5
+ EE_DAUTH_URL=N/A
6
+ EE_ETH_ENABLED=false
7
+ EE_VPN_IMPL=1
8
+ EE_SECURED=false
9
+ EE_ROOT_TOPIC=some-vpn-root-topic
10
+
11
+
12
+
13
+ # EE_MQTT_HOST=
14
+ # EE_MQTT_PORT=
15
+ # EE_MQTT_USER=
16
+ # EE_MQTT=
17
+ # EE_SECURED=true
18
+
19
+ TARGET_NODE=0xai_A9GWvmq3m-cyEMUyOaTTeyMSTkAwk-mfY2ftn1fsOQXE
20
+ TELEGRAM_BOT_TOKEN=7741954463:AAEmAvTtbFkWe3AAgtGiN-jJcgf986v-eV0
21
+ TELEGRAM_BOT_NAME=Aimethica_bot
22
+
23
+ TELEGRAM_API_AGENT_TOKEN=
@@ -6,6 +6,5 @@ if __name__ == '__main__':
6
6
  silent=False,
7
7
  verbosity=3,
8
8
  )
9
- sess.P(sess.get_client_address(), color='g')
10
9
 
11
10
  sess.wait(seconds=15, close_session=True)
@@ -4,13 +4,13 @@ from naeural_client import Session
4
4
 
5
5
  if __name__ == '__main__':
6
6
  sess = Session(
7
- silent=False,
7
+ silent=True,
8
8
  verbosity=3,
9
9
  )
10
10
  sess.P(sess.get_client_address(), color='g')
11
11
 
12
12
  node = '0xai_AxLOEgr3I1SCi3wp1c3tYxgVEpZrfV_qpDoG3_J8Sc4e'
13
- df = sess.get_node_apps(node=node, show_full=True, as_json=False, as_df=True)
14
- sess.P(f"Results:\n{df}", color='b')
13
+ df = sess.get_nodes_apps(node=node, show_full=True, as_json=False, as_df=True)
14
+ sess.P(f"Results:\n{df}", color='b', show=True)
15
15
 
16
16
  sess.wait(seconds=15, close_session=True)
@@ -0,0 +1,74 @@
1
+ import pandas as pd
2
+
3
+ class ColorDataFrame(pd.DataFrame):
4
+ """
5
+ A DataFrame subclass that colors specific rows red when printed in a console.
6
+
7
+ Parameters
8
+ ----------
9
+ *args : tuple
10
+ Positional arguments passed to the pd.DataFrame constructor.
11
+ color_condition : callable, optional
12
+ A function that takes a row (pd.Series) and returns True if the row should be
13
+ highlighted in red, or False otherwise.
14
+ **kwargs : dict
15
+ Keyword arguments passed to the pd.DataFrame constructor.
16
+
17
+ Returns
18
+ -------
19
+ ColorDataFrame
20
+ A subclass of DataFrame that overrides the to_string method for coloring.
21
+
22
+ Examples
23
+ --------
24
+
25
+ >>> df = ColorDataFrame(
26
+ df,
27
+ ... color_condition=lambda row: row['value'] > 9
28
+ )
29
+ >>> print(df)
30
+ """
31
+
32
+ _metadata = ['_color_condition']
33
+
34
+ def __init__(self, *args, color_condition=lambda row: False, **kwargs):
35
+ super().__init__(*args, **kwargs)
36
+ # Store the condition function as an attribute
37
+ self._color_condition = color_condition
38
+ return
39
+
40
+ def to_string(self, *args, **kwargs):
41
+ """
42
+ Overridden version of to_string that applies ANSI colors to rows
43
+ matching the condition.
44
+ """
45
+ original_string = super().to_string(*args, **kwargs)
46
+ # Split the original string into lines
47
+ lines = original_string.split('\n')
48
+
49
+ header_lines = lines[:1]
50
+ data_lines = lines[1:]
51
+
52
+ colored_data_lines = []
53
+ for row_index, row_line in enumerate(data_lines):
54
+ # Attempt to parse the index from the leftmost part of each row line
55
+ try:
56
+ # The row's index in the actual DataFrame
57
+ df_index = self.index[row_index]
58
+ except IndexError:
59
+ colored_data_lines.append(row_line)
60
+ continue
61
+
62
+ # Check if row meets the color condition
63
+ if self._color_condition(self.loc[df_index]):
64
+ # Red color ANSI: \033[91m ... \033[0m
65
+ row_line = f"\033[91m{row_line}\033[0m"
66
+
67
+ colored_data_lines.append(row_line)
68
+
69
+ return "\n".join(header_lines + colored_data_lines)
70
+
71
+
72
+ if __name__ == "__main__":
73
+ df = ColorDataFrame({'value': [10, -5, 3]}, color_condition=lambda row: row['value'] > 9)
74
+ print(df)
File without changes
File without changes
File without changes