dsf-python 3.6.0rc2.post1__tar.gz → 3.7.0b1__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 (293) hide show
  1. dsf_python-3.7.0b1/PKG-INFO +303 -0
  2. dsf_python-3.7.0b1/README.md +261 -0
  3. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/setup.cfg +1 -1
  4. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/setup.py +4 -7
  5. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/__init__.py +2 -2
  6. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/base_command.py +4 -2
  7. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/code.py +34 -24
  8. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/code_channel.py +7 -1
  9. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/code_interception.py +0 -4
  10. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/code_parameter.py +106 -62
  11. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/files.py +7 -5
  12. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/generic.py +4 -28
  13. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/http_endpoints.py +0 -14
  14. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/object_model.py +0 -12
  15. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/packages.py +4 -4
  16. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/plugins.py +15 -15
  17. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/responses.py +27 -14
  18. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/user_sessions.py +2 -8
  19. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/connections/base_command_connection.py +11 -4
  20. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/connections/base_connection.py +27 -8
  21. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/connections/command_connection.py +2 -2
  22. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/connections/exceptions.py +3 -1
  23. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/connections/init_messages/client_init_messages.py +19 -7
  24. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/connections/init_messages/server_init_message.py +9 -3
  25. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/connections/intercept_connection.py +3 -3
  26. dsf_python-3.7.0b1/src/dsf/connections/subscribe_connection.py +219 -0
  27. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/http.py +33 -16
  28. dsf_python-3.7.0b1/src/dsf/object_model/boards/accelerometer.py +19 -0
  29. dsf_python-3.7.0b1/src/dsf/object_model/boards/board_closed_loop.py +15 -0
  30. dsf_python-3.7.0b1/src/dsf/object_model/boards/boards.py +112 -0
  31. dsf_python-3.7.0b1/src/dsf/object_model/boards/direct_display/direct_display.py +18 -0
  32. dsf_python-3.7.0b1/src/dsf/object_model/boards/direct_display/direct_display_encoder.py +12 -0
  33. dsf_python-3.7.0b1/src/dsf/object_model/boards/direct_display/direct_display_screen.py +54 -0
  34. dsf_python-3.7.0b1/src/dsf/object_model/boards/direct_display/direct_display_screen_st7567.py +14 -0
  35. dsf_python-3.7.0b1/src/dsf/object_model/boards/driver.py +20 -0
  36. dsf_python-3.7.0b1/src/dsf/object_model/boards/driver_closed_loop.py +41 -0
  37. dsf_python-3.7.0b1/src/dsf/object_model/boards/driver_config.py +16 -0
  38. dsf_python-3.7.0b1/src/dsf/object_model/boards/driver_mode.py +23 -0
  39. dsf_python-3.7.0b1/src/dsf/object_model/boards/min_max_current.py +18 -0
  40. dsf_python-3.7.0b1/src/dsf/object_model/directories/directories.py +32 -0
  41. dsf_python-3.7.0b1/src/dsf/object_model/fans/fan_thermostatic_control.py +19 -0
  42. dsf_python-3.7.0b1/src/dsf/object_model/fans/fans.py +40 -0
  43. dsf_python-3.7.0b1/src/dsf/object_model/heat/heat.py +36 -0
  44. dsf_python-3.7.0b1/src/dsf/object_model/heat/heater.py +81 -0
  45. dsf_python-3.7.0b1/src/dsf/object_model/heat/heater_model.py +40 -0
  46. dsf_python-3.7.0b1/src/dsf/object_model/heat/heater_model_pid.py +21 -0
  47. dsf_python-3.7.0b1/src/dsf/object_model/heat/heater_monitor.py +52 -0
  48. dsf_python-3.7.0b1/src/dsf/object_model/inputs/input_channel.py +65 -0
  49. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/inputs/input_channel_state.py +3 -0
  50. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/inputs/inputs.py +1 -1
  51. dsf_python-3.7.0b1/src/dsf/object_model/job/build.py +25 -0
  52. dsf_python-3.7.0b1/src/dsf/object_model/job/build_object.py +24 -0
  53. dsf_python-3.7.0b1/src/dsf/object_model/job/gcode_fileinfo.py +51 -0
  54. dsf_python-3.7.0b1/src/dsf/object_model/job/job.py +51 -0
  55. dsf_python-3.7.0b1/src/dsf/object_model/job/layer.py +27 -0
  56. dsf_python-3.7.0b1/src/dsf/object_model/job/thumbnail_info.py +41 -0
  57. dsf_python-3.7.0b1/src/dsf/object_model/job/times_left.py +23 -0
  58. dsf_python-3.7.0b1/src/dsf/object_model/led_strips/led_strip.py +44 -0
  59. dsf_python-3.7.0b1/src/dsf/object_model/led_strips/led_strip_color_order.py +22 -0
  60. dsf_python-3.7.0b1/src/dsf/object_model/limits/limits.py +93 -0
  61. dsf_python-3.7.0b1/src/dsf/object_model/messages/messages.py +51 -0
  62. dsf_python-3.7.0b1/src/dsf/object_model/model_collection.py +156 -0
  63. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/model_dictionary.py +22 -7
  64. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/model_object.py +27 -19
  65. dsf_python-3.7.0b1/src/dsf/object_model/model_type.py +21 -0
  66. dsf_python-3.7.0b1/src/dsf/object_model/move/axis.py +132 -0
  67. dsf_python-3.7.0b1/src/dsf/object_model/move/current_move.py +41 -0
  68. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/move/driver_id.py +10 -4
  69. dsf_python-3.7.0b1/src/dsf/object_model/move/extruder.py +67 -0
  70. dsf_python-3.7.0b1/src/dsf/object_model/move/extruder_non_linear.py +17 -0
  71. dsf_python-3.7.0b1/src/dsf/object_model/move/extruder_pressure_advance.py +18 -0
  72. dsf_python-3.7.0b1/src/dsf/object_model/move/input_shaping.py +63 -0
  73. dsf_python-3.7.0b1/src/dsf/object_model/move/keepout_zone.py +31 -0
  74. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/move/kinematics/core_kinematics.py +7 -13
  75. dsf_python-3.7.0b1/src/dsf/object_model/move/kinematics/delta_kinematics.py +32 -0
  76. dsf_python-3.7.0b1/src/dsf/object_model/move/kinematics/delta_tower.py +29 -0
  77. dsf_python-3.7.0b1/src/dsf/object_model/move/kinematics/hangprinter_kinematics.py +22 -0
  78. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/move/kinematics/kinematics.py +14 -30
  79. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/move/kinematics/kinematics_name.py +8 -8
  80. dsf_python-3.7.0b1/src/dsf/object_model/move/kinematics/polar_kinematics.py +29 -0
  81. dsf_python-3.7.0b1/src/dsf/object_model/move/kinematics/scara_kinematics.py +38 -0
  82. dsf_python-3.7.0b1/src/dsf/object_model/move/kinematics/tilt_correction.py +30 -0
  83. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/move/kinematics/zleadscrew_kinematics.py +5 -7
  84. dsf_python-3.7.0b1/src/dsf/object_model/move/microstepping.py +15 -0
  85. dsf_python-3.7.0b1/src/dsf/object_model/move/motion_system.py +52 -0
  86. dsf_python-3.7.0b1/src/dsf/object_model/move/motors_idle_control.py +15 -0
  87. dsf_python-3.7.0b1/src/dsf/object_model/move/move.py +95 -0
  88. dsf_python-3.7.0b1/src/dsf/object_model/move/move_calibration.py +19 -0
  89. dsf_python-3.7.0b1/src/dsf/object_model/move/move_compensation.py +46 -0
  90. dsf_python-3.7.0b1/src/dsf/object_model/move/move_deviations.py +15 -0
  91. dsf_python-3.7.0b1/src/dsf/object_model/move/move_queue_item.py +15 -0
  92. dsf_python-3.7.0b1/src/dsf/object_model/move/move_rotation.py +16 -0
  93. dsf_python-3.7.0b1/src/dsf/object_model/move/move_segmentation.py +12 -0
  94. dsf_python-3.7.0b1/src/dsf/object_model/move/probe_grid.py +25 -0
  95. dsf_python-3.7.0b1/src/dsf/object_model/move/skew.py +21 -0
  96. dsf_python-3.7.0b1/src/dsf/object_model/network/network.py +30 -0
  97. dsf_python-3.7.0b1/src/dsf/object_model/network/network_interface.py +57 -0
  98. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/network/network_interface_type.py +1 -1
  99. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/network/network_state.py +3 -0
  100. dsf_python-3.7.0b1/src/dsf/object_model/object_model.py +62 -0
  101. dsf_python-3.7.0b1/src/dsf/object_model/plugins/plugin_manifest.py +98 -0
  102. dsf_python-3.7.0b1/src/dsf/object_model/plugins/plugins.py +25 -0
  103. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/plugins/sbc_permissions.py +2 -2
  104. dsf_python-3.7.0b1/src/dsf/object_model/sbc/cpu.py +15 -0
  105. dsf_python-3.7.0b1/src/dsf/object_model/sbc/dsf/communication_method.py +11 -0
  106. dsf_python-3.7.0b1/src/dsf/object_model/sbc/dsf/dsf.py +25 -0
  107. dsf_python-3.7.0b1/src/dsf/object_model/sbc/dsf/http_endpoint.py +28 -0
  108. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/sbc/dsf/http_endpoint_type.py +2 -2
  109. dsf_python-3.7.0b1/src/dsf/object_model/sbc/dsf/user_sessions/user_sessions.py +26 -0
  110. dsf_python-3.7.0b1/src/dsf/object_model/sbc/memory.py +12 -0
  111. dsf_python-3.7.0b1/src/dsf/object_model/sbc/sbc.py +24 -0
  112. dsf_python-3.7.0b1/src/dsf/object_model/sensors/analog_sensor.py +27 -0
  113. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/sensors/analog_sensor_type.py +24 -6
  114. dsf_python-3.7.0b1/src/dsf/object_model/sensors/endstop.py +22 -0
  115. dsf_python-3.7.0b1/src/dsf/object_model/sensors/filament_monitors/Duet3DFilamentMonitor.py +28 -0
  116. dsf_python-3.7.0b1/src/dsf/object_model/sensors/filament_monitors/filament_monitor.py +52 -0
  117. dsf_python-3.7.0b1/src/dsf/object_model/sensors/filament_monitors/laser_filament_monitor.py +58 -0
  118. dsf_python-3.7.0b1/src/dsf/object_model/sensors/filament_monitors/pulsed_filament_monitor.py +58 -0
  119. dsf_python-3.7.0b1/src/dsf/object_model/sensors/filament_monitors/rotating_magnet_filament_monitor.py +58 -0
  120. dsf_python-3.7.0b1/src/dsf/object_model/sensors/gp_input_port.py +12 -0
  121. dsf_python-3.7.0b1/src/dsf/object_model/sensors/probe.py +33 -0
  122. dsf_python-3.7.0b1/src/dsf/object_model/sensors/probe_touch_mode.py +14 -0
  123. dsf_python-3.7.0b1/src/dsf/object_model/sensors/sensors.py +32 -0
  124. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/sensors/temperature_error.py +12 -0
  125. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/spindles/spindle_type.py +0 -3
  126. dsf_python-3.7.0b1/src/dsf/object_model/spindles/spindles.py +44 -0
  127. dsf_python-3.7.0b1/src/dsf/object_model/state/beep_request.py +12 -0
  128. dsf_python-3.7.0b1/src/dsf/object_model/state/gp_output_port.py +15 -0
  129. dsf_python-3.7.0b1/src/dsf/object_model/state/message_box.py +52 -0
  130. dsf_python-3.7.0b1/src/dsf/object_model/state/restore_point.py +23 -0
  131. dsf_python-3.7.0b1/src/dsf/object_model/state/startup_error.py +20 -0
  132. dsf_python-3.7.0b1/src/dsf/object_model/state/state.py +47 -0
  133. dsf_python-3.7.0b1/src/dsf/object_model/tools/tool_retraction.py +24 -0
  134. dsf_python-3.7.0b1/src/dsf/object_model/tools/tools.py +36 -0
  135. dsf_python-3.7.0b1/src/dsf/object_model/utils.py +154 -0
  136. dsf_python-3.7.0b1/src/dsf/object_model/volumes/volumes.py +33 -0
  137. dsf_python-3.7.0b1/src/dsf/utils.py +132 -0
  138. dsf_python-3.7.0b1/src/dsf_python.egg-info/PKG-INFO +303 -0
  139. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf_python.egg-info/SOURCES.txt +9 -0
  140. dsf_python-3.7.0b1/tests/test_base_connection.py +34 -0
  141. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/tests/test_custom_http_endpoint.py +10 -10
  142. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/tests/test_custom_m_codes.py +1 -1
  143. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/tests/test_object_model.py +336 -3
  144. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/tests/test_send_simple_code.py +1 -1
  145. dsf_python-3.7.0b1/tests/test_subscribe_object_model.py +268 -0
  146. dsf_python-3.6.0rc2.post1/PKG-INFO +0 -60
  147. dsf_python-3.6.0rc2.post1/README.md +0 -15
  148. dsf_python-3.6.0rc2.post1/src/dsf/connections/subscribe_connection.py +0 -65
  149. dsf_python-3.6.0rc2.post1/src/dsf/object_model/boards/accelerometer.py +0 -42
  150. dsf_python-3.6.0rc2.post1/src/dsf/object_model/boards/board_closed_loop.py +0 -29
  151. dsf_python-3.6.0rc2.post1/src/dsf/object_model/boards/boards.py +0 -290
  152. dsf_python-3.6.0rc2.post1/src/dsf/object_model/boards/direct_display/direct_display.py +0 -23
  153. dsf_python-3.6.0rc2.post1/src/dsf/object_model/boards/direct_display/direct_display_encoder.py +0 -19
  154. dsf_python-3.6.0rc2.post1/src/dsf/object_model/boards/direct_display/direct_display_screen.py +0 -101
  155. dsf_python-3.6.0rc2.post1/src/dsf/object_model/boards/direct_display/direct_display_screen_st7567.py +0 -31
  156. dsf_python-3.6.0rc2.post1/src/dsf/object_model/boards/driver.py +0 -29
  157. dsf_python-3.6.0rc2.post1/src/dsf/object_model/boards/driver_closed_loop.py +0 -77
  158. dsf_python-3.6.0rc2.post1/src/dsf/object_model/boards/min_max_current.py +0 -41
  159. dsf_python-3.6.0rc2.post1/src/dsf/object_model/directories/directories.py +0 -86
  160. dsf_python-3.6.0rc2.post1/src/dsf/object_model/fans/fan_thermostatic_control.py +0 -47
  161. dsf_python-3.6.0rc2.post1/src/dsf/object_model/fans/fans.py +0 -116
  162. dsf_python-3.6.0rc2.post1/src/dsf/object_model/heat/heat.py +0 -57
  163. dsf_python-3.6.0rc2.post1/src/dsf/object_model/heat/heater.py +0 -201
  164. dsf_python-3.6.0rc2.post1/src/dsf/object_model/heat/heater_model.py +0 -115
  165. dsf_python-3.6.0rc2.post1/src/dsf/object_model/heat/heater_model_pid.py +0 -63
  166. dsf_python-3.6.0rc2.post1/src/dsf/object_model/heat/heater_monitor.py +0 -96
  167. dsf_python-3.6.0rc2.post1/src/dsf/object_model/inputs/input_channel.py +0 -212
  168. dsf_python-3.6.0rc2.post1/src/dsf/object_model/job/build.py +0 -55
  169. dsf_python-3.6.0rc2.post1/src/dsf/object_model/job/build_object.py +0 -46
  170. dsf_python-3.6.0rc2.post1/src/dsf/object_model/job/gcode_fileinfo.py +0 -126
  171. dsf_python-3.6.0rc2.post1/src/dsf/object_model/job/job.py +0 -188
  172. dsf_python-3.6.0rc2.post1/src/dsf/object_model/job/layer.py +0 -57
  173. dsf_python-3.6.0rc2.post1/src/dsf/object_model/job/thumbnail_info.py +0 -96
  174. dsf_python-3.6.0rc2.post1/src/dsf/object_model/job/times_left.py +0 -43
  175. dsf_python-3.6.0rc2.post1/src/dsf/object_model/led_strips/led_strip.py +0 -74
  176. dsf_python-3.6.0rc2.post1/src/dsf/object_model/limits/limits.py +0 -307
  177. dsf_python-3.6.0rc2.post1/src/dsf/object_model/messages/messages.py +0 -84
  178. dsf_python-3.6.0rc2.post1/src/dsf/object_model/model_collection.py +0 -66
  179. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/axis.py +0 -305
  180. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/current_move.py +0 -75
  181. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/extruder.py +0 -187
  182. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/extruder_non_linear.py +0 -39
  183. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/input_shaping.py +0 -90
  184. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/keepout_zone.py +0 -58
  185. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/kinematics/delta_kinematics.py +0 -74
  186. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/kinematics/delta_tower.py +0 -62
  187. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/kinematics/hangprinter_kinematics.py +0 -33
  188. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/kinematics/polar_kinematics.py +0 -13
  189. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/kinematics/scara_kinematics.py +0 -12
  190. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/kinematics/tilt_correction.py +0 -63
  191. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/microstepping.py +0 -29
  192. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/motors_idle_control.py +0 -29
  193. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/move.py +0 -188
  194. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/move_calibration.py +0 -33
  195. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/move_compensation.py +0 -88
  196. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/move_deviations.py +0 -29
  197. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/move_queue_item.py +0 -29
  198. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/move_rotation.py +0 -27
  199. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/move_segmentation.py +0 -27
  200. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/probe_grid.py +0 -48
  201. dsf_python-3.6.0rc2.post1/src/dsf/object_model/move/skew.py +0 -52
  202. dsf_python-3.6.0rc2.post1/src/dsf/object_model/network/network.py +0 -59
  203. dsf_python-3.6.0rc2.post1/src/dsf/object_model/network/network_interface.py +0 -202
  204. dsf_python-3.6.0rc2.post1/src/dsf/object_model/object_model.py +0 -165
  205. dsf_python-3.6.0rc2.post1/src/dsf/object_model/plugins/plugin_manifest.py +0 -264
  206. dsf_python-3.6.0rc2.post1/src/dsf/object_model/plugins/plugins.py +0 -38
  207. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sbc/cpu.py +0 -50
  208. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sbc/dsf/dsf.py +0 -76
  209. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sbc/dsf/http_endpoint.py +0 -73
  210. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sbc/dsf/user_sessions/user_sessions.py +0 -74
  211. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sbc/memory.py +0 -30
  212. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sbc/sbc.py +0 -100
  213. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sensors/analog_sensor.py +0 -154
  214. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sensors/endstop.py +0 -56
  215. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sensors/filament_monitors/Duet3DFilamentMonitor.py +0 -77
  216. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sensors/filament_monitors/filament_monitor.py +0 -95
  217. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sensors/filament_monitors/laser_filament_monitor.py +0 -138
  218. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sensors/filament_monitors/pulsed_filament_monitor.py +0 -126
  219. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sensors/filament_monitors/rotating_magnet_filament_monitor.py +0 -126
  220. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sensors/gp_input_port.py +0 -18
  221. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sensors/probe.py +0 -234
  222. dsf_python-3.6.0rc2.post1/src/dsf/object_model/sensors/sensors.py +0 -46
  223. dsf_python-3.6.0rc2.post1/src/dsf/object_model/spindles/spindles.py +0 -147
  224. dsf_python-3.6.0rc2.post1/src/dsf/object_model/state/beep_request.py +0 -27
  225. dsf_python-3.6.0rc2.post1/src/dsf/object_model/state/gp_output_port.py +0 -30
  226. dsf_python-3.6.0rc2.post1/src/dsf/object_model/state/message_box.py +0 -168
  227. dsf_python-3.6.0rc2.post1/src/dsf/object_model/state/restore_point.py +0 -85
  228. dsf_python-3.6.0rc2.post1/src/dsf/object_model/state/startup_error.py +0 -43
  229. dsf_python-3.6.0rc2.post1/src/dsf/object_model/state/state.py +0 -261
  230. dsf_python-3.6.0rc2.post1/src/dsf/object_model/tools/tool_retraction.py +0 -63
  231. dsf_python-3.6.0rc2.post1/src/dsf/object_model/tools/tools.py +0 -208
  232. dsf_python-3.6.0rc2.post1/src/dsf/object_model/utils.py +0 -49
  233. dsf_python-3.6.0rc2.post1/src/dsf/object_model/volumes/volumes.py +0 -98
  234. dsf_python-3.6.0rc2.post1/src/dsf/utils.py +0 -55
  235. dsf_python-3.6.0rc2.post1/src/dsf_python.egg-info/PKG-INFO +0 -60
  236. dsf_python-3.6.0rc2.post1/tests/test_subscribe_object_model.py +0 -136
  237. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/LICENSE +0 -0
  238. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/MANIFEST.in +0 -0
  239. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/pyproject.toml +0 -0
  240. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/__init__.py +0 -0
  241. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/code_flags.py +0 -0
  242. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/code_type.py +0 -0
  243. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/condition_type.py +0 -0
  244. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/commands/model_subscription.py +0 -0
  245. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/connections/__init__.py +0 -0
  246. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/connections/init_messages/__init__.py +0 -0
  247. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/exceptions.py +0 -0
  248. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/__init__.py +0 -0
  249. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/boards/__init__.py +0 -0
  250. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/boards/direct_display/__init__.py +0 -0
  251. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/boards/direct_display/direct_display_controller.py +0 -0
  252. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/boards/inductive_sensor.py +0 -0
  253. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/directories/__init__.py +0 -0
  254. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/fans/__init__.py +0 -0
  255. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/heat/__init__.py +0 -0
  256. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/inputs/__init__.py +0 -0
  257. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/inputs/compatibility.py +0 -0
  258. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/inputs/distance_unit.py +0 -0
  259. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/job/__init__.py +0 -0
  260. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/led_strips/__init__.py +0 -0
  261. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/limits/__init__.py +0 -0
  262. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/messages/__init__.py +0 -0
  263. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/move/__init__.py +0 -0
  264. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/move/kinematics/__init__.py +0 -0
  265. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/network/__init__.py +0 -0
  266. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/network/network_protocol.py +0 -0
  267. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/plugins/__init__.py +0 -0
  268. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/sbc/__init__.py +0 -0
  269. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/sbc/dsf/__init__.py +0 -0
  270. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/sbc/dsf/user_sessions/__init__.py +0 -0
  271. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/sbc/dsf/user_sessions/access_level.py +0 -0
  272. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/sbc/dsf/user_sessions/session_type.py +0 -0
  273. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/sensors/__init__.py +0 -0
  274. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/sensors/endstop_type.py +0 -0
  275. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/sensors/filament_monitors/__init__.py +0 -0
  276. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/sensors/filament_monitors/filament_monitor_enable_type.py +0 -0
  277. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/sensors/filament_monitors/filament_monitor_status.py +0 -0
  278. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/sensors/filament_monitors/filament_monitor_type.py +0 -0
  279. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/sensors/probe_type.py +0 -0
  280. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/spindles/__init__.py +0 -0
  281. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/spindles/spindle_state.py +0 -0
  282. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/state/__init__.py +0 -0
  283. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/state/log_level.py +0 -0
  284. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/state/machine_mode.py +0 -0
  285. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/state/machine_status.py +0 -0
  286. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/tools/__init__.py +0 -0
  287. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/tools/tool_state.py +0 -0
  288. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/object_model/volumes/__init__.py +0 -0
  289. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf/utility/__init__.py +0 -0
  290. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf_python.egg-info/dependency_links.txt +0 -0
  291. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf_python.egg-info/requires.txt +0 -0
  292. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/src/dsf_python.egg-info/top_level.txt +0 -0
  293. {dsf_python-3.6.0rc2.post1 → dsf_python-3.7.0b1}/tests/test_code.py +0 -0
@@ -0,0 +1,303 @@
1
+ Metadata-Version: 2.4
2
+ Name: dsf-python
3
+ Version: 3.7.0b1
4
+ Summary: Python interface to access DuetSoftwareFramework
5
+ Home-page: https://github.com/Duet3D/dsf-python
6
+ Author: Duet3D Ltd.
7
+ Author-email: pkg@duet3d.com
8
+ Project-URL: Duet3D Support, https://forum.duet3d.com/
9
+ Project-URL: Bug Reports, https://github.com/Duet3D/dsf-python/issues
10
+ Project-URL: Source, https://github.com/Duet3D/dsf-python/
11
+ Keywords: Duet3D,DuetSoftwareFramework,DSF,dsf-python
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Topic :: Software Development :: Libraries
15
+ Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Programming Language :: Python :: 3 :: Only
22
+ Requires-Python: >=3.11, <4
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: python-dateutil
26
+ Provides-Extra: dev
27
+ Requires-Dist: sphinx; extra == "dev"
28
+ Requires-Dist: tox; extra == "dev"
29
+ Dynamic: author
30
+ Dynamic: author-email
31
+ Dynamic: classifier
32
+ Dynamic: description
33
+ Dynamic: description-content-type
34
+ Dynamic: home-page
35
+ Dynamic: keywords
36
+ Dynamic: license-file
37
+ Dynamic: project-url
38
+ Dynamic: provides-extra
39
+ Dynamic: requires-dist
40
+ Dynamic: requires-python
41
+ Dynamic: summary
42
+
43
+ # Duet Software Framework Python Bindings
44
+
45
+ `dsf-python` provides Python bindings for the Duet Software Framework control server.
46
+ It exposes the DSF socket protocol as Python connection classes, typed object model
47
+ classes, command builders, and helpers for custom HTTP endpoints.
48
+
49
+ This project is also published on [PyPI](https://pypi.org/project/dsf-python/).
50
+
51
+ Useful links:
52
+
53
+ - [Duet Software Framework](https://github.com/Duet3D/DuetSoftwareFramework)
54
+ - [dsf-python examples](https://github.com/Duet3D/dsf-python/tree/main/examples)
55
+ - [Duet Software Framework forum](https://forum.duet3d.com/category/31/dsf-development)
56
+
57
+ ## What The Library Contains
58
+
59
+ The top-level package is organised around the main DSF workflows.
60
+
61
+ - `dsf.connections`: socket-based client connections for commands, subscriptions, and code interception
62
+ - `dsf.commands`: request payload builders for low-level DSF commands
63
+ - `dsf.object_model`: the typed DSF object model and related enums
64
+ - `dsf.http`: helpers for custom HTTP and WebSocket endpoints exposed through DSF
65
+ - `dsf.exceptions`: shared exception types raised by connection classes
66
+
67
+ ## Installation
68
+
69
+ The package can be installed from source:
70
+
71
+ ```bash
72
+ python3 setup.py install
73
+ ```
74
+
75
+ Or with `pip`:
76
+
77
+ ```bash
78
+ python3 -m pip install dsf-python
79
+ ```
80
+
81
+ Most code using this library must run on a system with Duet Software Framework
82
+ installed and with permission to access the DSF UNIX socket.
83
+
84
+ ## Quick Start
85
+
86
+ ### Run A Simple Command
87
+
88
+ Use `CommandConnection` to send general-purpose commands such as G-code or to
89
+ request the full object model on demand.
90
+
91
+ ```python
92
+ from dsf.connections import CommandConnection
93
+
94
+ connection = CommandConnection()
95
+ connection.connect()
96
+
97
+ response = connection.perform_simple_code("M115")
98
+ print(response.result)
99
+
100
+ connection.close()
101
+ ```
102
+
103
+ ### Read The Object Model Once
104
+
105
+ ```python
106
+ from dsf.connections import CommandConnection
107
+
108
+ connection = CommandConnection()
109
+ connection.connect()
110
+
111
+ object_model = connection.get_object_model()
112
+ print(object_model.state.status)
113
+ print(object_model.move.axes[0].letter)
114
+
115
+ connection.close()
116
+ ```
117
+
118
+ ### Subscribe To Object Model Updates
119
+
120
+ Use `SubscribeConnection` when you want DSF to push object model updates over a
121
+ subscription socket.
122
+
123
+ ```python
124
+ from dsf.connections import SubscribeConnection, SubscriptionMode
125
+
126
+ subscription = SubscribeConnection(SubscriptionMode.PATCH)
127
+ subscription.connect()
128
+
129
+ object_model = subscription.get_object_model()
130
+
131
+ while True:
132
+ object_model = subscription.get_object_model()
133
+ ```
134
+
135
+ In `SubscriptionMode.PATCH`, the first `get_object_model()` call reads the full
136
+ model. Later calls reuse an internal cached model and apply one queued patch if
137
+ available.
138
+
139
+ ## Connections
140
+
141
+ ### CommandConnection
142
+
143
+ `CommandConnection` is the general-purpose connection type. It is used for:
144
+
145
+ - sending simple G-code
146
+ - requesting the full object model
147
+ - working with files, packages, plugins, and user sessions through DSF commands
148
+ - issuing lower-level requests through the command helpers in `dsf.commands`
149
+
150
+ Choose this connection when you want request-response behaviour and do not need
151
+ streamed updates.
152
+
153
+ ### SubscribeConnection
154
+
155
+ `SubscribeConnection` receives streamed object model updates from DSF. It supports:
156
+
157
+ - `SubscriptionMode.FULL`: every update is a full object model
158
+ - `SubscriptionMode.PATCH`: every update is a partial JSON fragment
159
+
160
+ #### Key-Based Callbacks
161
+
162
+ `SubscribeConnection.subscribe_to_keys()` can run callbacks synchronously when
163
+ selected object model paths appear in a patch update processed by `get_object_model()`.
164
+
165
+ Key paths use dot notation and can include list indexes:
166
+
167
+ - `state.upTime`
168
+ - `heat.heaters.0.current`
169
+ - `move.axes.2.userPosition`
170
+
171
+ Use `^` in a list position to match any changed index:
172
+
173
+ - `heat.heaters.^.current`
174
+ - `tools.^.state`
175
+
176
+ Callbacks always receive keyword arguments:
177
+
178
+ - `key`: the subscribed key path that matched
179
+ - `data`: the changed value found at that path
180
+ - `indices`: a tuple of matched wildcard indexes, or `None` when the key does not use `^`
181
+
182
+ ```python
183
+ from dsf.connections import SubscribeConnection, SubscriptionMode
184
+
185
+
186
+ def handle_change(*, key, data, indices):
187
+ print(key, data, indices)
188
+
189
+
190
+ subscription = SubscribeConnection(SubscriptionMode.PATCH)
191
+ subscription.connect()
192
+ subscription.get_object_model()
193
+
194
+ unsubscribe = subscription.subscribe_to_keys(
195
+ ["heat.heaters.0.current", "state.upTime"],
196
+ handle_change,
197
+ )
198
+
199
+ while True:
200
+ object_model = subscription.get_object_model()
201
+ ```
202
+
203
+ Wildcard example:
204
+
205
+ ```python
206
+ def handle_any_heater(*, key, data, indices):
207
+ print(key, indices, data)
208
+
209
+
210
+ subscription.subscribe_to_keys(
211
+ ["heat.heaters.^.current"],
212
+ handle_any_heater,
213
+ )
214
+ ```
215
+
216
+ ### InterceptConnection
217
+
218
+ `InterceptConnection` is used for custom code handling and code interception. Use it
219
+ when a plugin needs to receive G/M/T-code events before or after the firmware handles them.
220
+
221
+ Typical use cases include:
222
+
223
+ - implementing custom M-codes
224
+ - inspecting or rewriting commands
225
+ - reacting to executed code notifications
226
+
227
+ See `examples/custom_m_codes.py` for a complete example.
228
+
229
+ ## Object Model
230
+
231
+ The `dsf.object_model` package mirrors the DSF object model in typed Python classes.
232
+ It lets you work with structured properties instead of manually traversing raw JSON.
233
+
234
+ Examples:
235
+
236
+ ```python
237
+ print(object_model.boards[0].name)
238
+ print(object_model.state.up_time)
239
+ print(object_model.move.axes[0].letter)
240
+ print(object_model.tools[0].state)
241
+ ```
242
+
243
+ Object model instances support JSON-driven updates:
244
+
245
+ ```python
246
+ object_model.update_from_json({"state": {"upTime": 1234}})
247
+ print(object_model.state.up_time)
248
+ ```
249
+
250
+ This is the mechanism used internally when patch subscriptions are applied.
251
+
252
+ ## Commands
253
+
254
+ The `dsf.commands` package contains low-level command builders for code execution,
255
+ file access, plugins, packages, object model manipulation, and other DSF protocol
256
+ requests.
257
+
258
+ Most users should start with the higher-level methods on `CommandConnection` or
259
+ `BaseCommandConnection`. Reach for `dsf.commands` directly when you need explicit
260
+ control over the payload sent to DSF.
261
+
262
+ ## Custom HTTP Endpoints
263
+
264
+ The `dsf.http` module contains helpers for custom HTTP and WebSocket endpoints.
265
+ This is useful when a DSF plugin needs to expose an HTTP route that is handled by
266
+ Python code.
267
+
268
+ Key types include:
269
+
270
+ - `HttpEndpointUnixSocket`
271
+ - `HttpEndpointConnection`
272
+ - `ReceivedHttpRequest`
273
+ - `HttpResponseType`
274
+
275
+ See `examples/custom_http_endpoint.py` for a practical example.
276
+
277
+ ## Included Examples
278
+
279
+ The `examples/` directory demonstrates the main workflows supported by the library.
280
+
281
+ - `send_simple_code.py`: send G-code over a command connection
282
+ - `subscribe_object_model.py`: subscribe to object model updates
283
+ - `custom_m_codes.py`: intercept and implement custom M-codes
284
+ - `custom_http_endpoint.py`: serve a custom HTTP endpoint through DSF
285
+
286
+ ## API Reference
287
+
288
+ The Sphinx docs expose the package API for the major public modules:
289
+
290
+ - `dsf`
291
+ - `dsf.connections`
292
+ - `dsf.commands`
293
+ - `dsf.object_model`
294
+ - `dsf.http`
295
+
296
+ ## Development Notes
297
+
298
+ The library talks to DSF using the configured UNIX socket path. By default this is
299
+ resolved from the DSF config and falls back to `/run/dsf/dcs.sock`.
300
+
301
+ If you are extending the library itself, the test suite under `tests/` contains
302
+ mock socket servers and object model fixtures that are useful for validating new
303
+ connection behaviour.
@@ -0,0 +1,261 @@
1
+ # Duet Software Framework Python Bindings
2
+
3
+ `dsf-python` provides Python bindings for the Duet Software Framework control server.
4
+ It exposes the DSF socket protocol as Python connection classes, typed object model
5
+ classes, command builders, and helpers for custom HTTP endpoints.
6
+
7
+ This project is also published on [PyPI](https://pypi.org/project/dsf-python/).
8
+
9
+ Useful links:
10
+
11
+ - [Duet Software Framework](https://github.com/Duet3D/DuetSoftwareFramework)
12
+ - [dsf-python examples](https://github.com/Duet3D/dsf-python/tree/main/examples)
13
+ - [Duet Software Framework forum](https://forum.duet3d.com/category/31/dsf-development)
14
+
15
+ ## What The Library Contains
16
+
17
+ The top-level package is organised around the main DSF workflows.
18
+
19
+ - `dsf.connections`: socket-based client connections for commands, subscriptions, and code interception
20
+ - `dsf.commands`: request payload builders for low-level DSF commands
21
+ - `dsf.object_model`: the typed DSF object model and related enums
22
+ - `dsf.http`: helpers for custom HTTP and WebSocket endpoints exposed through DSF
23
+ - `dsf.exceptions`: shared exception types raised by connection classes
24
+
25
+ ## Installation
26
+
27
+ The package can be installed from source:
28
+
29
+ ```bash
30
+ python3 setup.py install
31
+ ```
32
+
33
+ Or with `pip`:
34
+
35
+ ```bash
36
+ python3 -m pip install dsf-python
37
+ ```
38
+
39
+ Most code using this library must run on a system with Duet Software Framework
40
+ installed and with permission to access the DSF UNIX socket.
41
+
42
+ ## Quick Start
43
+
44
+ ### Run A Simple Command
45
+
46
+ Use `CommandConnection` to send general-purpose commands such as G-code or to
47
+ request the full object model on demand.
48
+
49
+ ```python
50
+ from dsf.connections import CommandConnection
51
+
52
+ connection = CommandConnection()
53
+ connection.connect()
54
+
55
+ response = connection.perform_simple_code("M115")
56
+ print(response.result)
57
+
58
+ connection.close()
59
+ ```
60
+
61
+ ### Read The Object Model Once
62
+
63
+ ```python
64
+ from dsf.connections import CommandConnection
65
+
66
+ connection = CommandConnection()
67
+ connection.connect()
68
+
69
+ object_model = connection.get_object_model()
70
+ print(object_model.state.status)
71
+ print(object_model.move.axes[0].letter)
72
+
73
+ connection.close()
74
+ ```
75
+
76
+ ### Subscribe To Object Model Updates
77
+
78
+ Use `SubscribeConnection` when you want DSF to push object model updates over a
79
+ subscription socket.
80
+
81
+ ```python
82
+ from dsf.connections import SubscribeConnection, SubscriptionMode
83
+
84
+ subscription = SubscribeConnection(SubscriptionMode.PATCH)
85
+ subscription.connect()
86
+
87
+ object_model = subscription.get_object_model()
88
+
89
+ while True:
90
+ object_model = subscription.get_object_model()
91
+ ```
92
+
93
+ In `SubscriptionMode.PATCH`, the first `get_object_model()` call reads the full
94
+ model. Later calls reuse an internal cached model and apply one queued patch if
95
+ available.
96
+
97
+ ## Connections
98
+
99
+ ### CommandConnection
100
+
101
+ `CommandConnection` is the general-purpose connection type. It is used for:
102
+
103
+ - sending simple G-code
104
+ - requesting the full object model
105
+ - working with files, packages, plugins, and user sessions through DSF commands
106
+ - issuing lower-level requests through the command helpers in `dsf.commands`
107
+
108
+ Choose this connection when you want request-response behaviour and do not need
109
+ streamed updates.
110
+
111
+ ### SubscribeConnection
112
+
113
+ `SubscribeConnection` receives streamed object model updates from DSF. It supports:
114
+
115
+ - `SubscriptionMode.FULL`: every update is a full object model
116
+ - `SubscriptionMode.PATCH`: every update is a partial JSON fragment
117
+
118
+ #### Key-Based Callbacks
119
+
120
+ `SubscribeConnection.subscribe_to_keys()` can run callbacks synchronously when
121
+ selected object model paths appear in a patch update processed by `get_object_model()`.
122
+
123
+ Key paths use dot notation and can include list indexes:
124
+
125
+ - `state.upTime`
126
+ - `heat.heaters.0.current`
127
+ - `move.axes.2.userPosition`
128
+
129
+ Use `^` in a list position to match any changed index:
130
+
131
+ - `heat.heaters.^.current`
132
+ - `tools.^.state`
133
+
134
+ Callbacks always receive keyword arguments:
135
+
136
+ - `key`: the subscribed key path that matched
137
+ - `data`: the changed value found at that path
138
+ - `indices`: a tuple of matched wildcard indexes, or `None` when the key does not use `^`
139
+
140
+ ```python
141
+ from dsf.connections import SubscribeConnection, SubscriptionMode
142
+
143
+
144
+ def handle_change(*, key, data, indices):
145
+ print(key, data, indices)
146
+
147
+
148
+ subscription = SubscribeConnection(SubscriptionMode.PATCH)
149
+ subscription.connect()
150
+ subscription.get_object_model()
151
+
152
+ unsubscribe = subscription.subscribe_to_keys(
153
+ ["heat.heaters.0.current", "state.upTime"],
154
+ handle_change,
155
+ )
156
+
157
+ while True:
158
+ object_model = subscription.get_object_model()
159
+ ```
160
+
161
+ Wildcard example:
162
+
163
+ ```python
164
+ def handle_any_heater(*, key, data, indices):
165
+ print(key, indices, data)
166
+
167
+
168
+ subscription.subscribe_to_keys(
169
+ ["heat.heaters.^.current"],
170
+ handle_any_heater,
171
+ )
172
+ ```
173
+
174
+ ### InterceptConnection
175
+
176
+ `InterceptConnection` is used for custom code handling and code interception. Use it
177
+ when a plugin needs to receive G/M/T-code events before or after the firmware handles them.
178
+
179
+ Typical use cases include:
180
+
181
+ - implementing custom M-codes
182
+ - inspecting or rewriting commands
183
+ - reacting to executed code notifications
184
+
185
+ See `examples/custom_m_codes.py` for a complete example.
186
+
187
+ ## Object Model
188
+
189
+ The `dsf.object_model` package mirrors the DSF object model in typed Python classes.
190
+ It lets you work with structured properties instead of manually traversing raw JSON.
191
+
192
+ Examples:
193
+
194
+ ```python
195
+ print(object_model.boards[0].name)
196
+ print(object_model.state.up_time)
197
+ print(object_model.move.axes[0].letter)
198
+ print(object_model.tools[0].state)
199
+ ```
200
+
201
+ Object model instances support JSON-driven updates:
202
+
203
+ ```python
204
+ object_model.update_from_json({"state": {"upTime": 1234}})
205
+ print(object_model.state.up_time)
206
+ ```
207
+
208
+ This is the mechanism used internally when patch subscriptions are applied.
209
+
210
+ ## Commands
211
+
212
+ The `dsf.commands` package contains low-level command builders for code execution,
213
+ file access, plugins, packages, object model manipulation, and other DSF protocol
214
+ requests.
215
+
216
+ Most users should start with the higher-level methods on `CommandConnection` or
217
+ `BaseCommandConnection`. Reach for `dsf.commands` directly when you need explicit
218
+ control over the payload sent to DSF.
219
+
220
+ ## Custom HTTP Endpoints
221
+
222
+ The `dsf.http` module contains helpers for custom HTTP and WebSocket endpoints.
223
+ This is useful when a DSF plugin needs to expose an HTTP route that is handled by
224
+ Python code.
225
+
226
+ Key types include:
227
+
228
+ - `HttpEndpointUnixSocket`
229
+ - `HttpEndpointConnection`
230
+ - `ReceivedHttpRequest`
231
+ - `HttpResponseType`
232
+
233
+ See `examples/custom_http_endpoint.py` for a practical example.
234
+
235
+ ## Included Examples
236
+
237
+ The `examples/` directory demonstrates the main workflows supported by the library.
238
+
239
+ - `send_simple_code.py`: send G-code over a command connection
240
+ - `subscribe_object_model.py`: subscribe to object model updates
241
+ - `custom_m_codes.py`: intercept and implement custom M-codes
242
+ - `custom_http_endpoint.py`: serve a custom HTTP endpoint through DSF
243
+
244
+ ## API Reference
245
+
246
+ The Sphinx docs expose the package API for the major public modules:
247
+
248
+ - `dsf`
249
+ - `dsf.connections`
250
+ - `dsf.commands`
251
+ - `dsf.object_model`
252
+ - `dsf.http`
253
+
254
+ ## Development Notes
255
+
256
+ The library talks to DSF using the configured UNIX socket path. By default this is
257
+ resolved from the DSF config and falls back to `/run/dsf/dcs.sock`.
258
+
259
+ If you are extending the library itself, the test suite under `tests/` contains
260
+ mock socket servers and object model fixtures that are useful for validating new
261
+ connection behaviour.
@@ -5,7 +5,7 @@ license_files = LICENSE
5
5
  max-line-length = 120
6
6
 
7
7
  [sdist_dsc]
8
- forced-upstream-version = 3.6.0-rc.2.post1
8
+ forced-upstream-version = 3.7.0-beta.1
9
9
 
10
10
  [egg_info]
11
11
  tag_build =
@@ -6,7 +6,7 @@ long_description = open("README.md", encoding="utf-8").read()
6
6
 
7
7
  setuptools.setup(
8
8
  name="dsf-python",
9
- version="3.6.0-rc.2.post1",
9
+ version="3.7.0-beta.1",
10
10
  description="Python interface to access DuetSoftwareFramework",
11
11
  long_description=long_description,
12
12
  long_description_content_type="text/markdown",
@@ -19,22 +19,19 @@ setuptools.setup(
19
19
  "Topic :: Software Development :: Libraries",
20
20
  "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
21
21
  "Programming Language :: Python :: 3",
22
- "Programming Language :: Python :: 3.7",
23
- "Programming Language :: Python :: 3.8",
24
- "Programming Language :: Python :: 3.9",
25
- "Programming Language :: Python :: 3.10",
26
22
  "Programming Language :: Python :: 3.11",
27
23
  "Programming Language :: Python :: 3.12",
28
24
  "Programming Language :: Python :: 3.13",
25
+ "Programming Language :: Python :: 3.14",
29
26
  "Programming Language :: Python :: 3 :: Only",
30
27
  ],
31
28
  install_requires=[
32
- 'python-dateutil'
29
+ 'python-dateutil',
33
30
  ],
34
31
  keywords="Duet3D, DuetSoftwareFramework, DSF, dsf-python",
35
32
  package_dir={"": "src"},
36
33
  packages=setuptools.find_packages(where="src"),
37
- python_requires=">=3.7, <4",
34
+ python_requires=">=3.11, <4",
38
35
  extras_require={
39
36
  "dev": [
40
37
  "sphinx",
@@ -1,10 +1,10 @@
1
- __version__ = "3.6.0-rc.2.post1"
1
+ __version__ = "3.7.0-beta.1"
2
2
 
3
3
  import json
4
4
  import os
5
5
 
6
6
  # Default socket file path
7
- SOCKET_FILE = "/run/dsf/dcs.sock"
7
+ SOCKET_FILE: str = "/run/dsf/dcs.sock"
8
8
 
9
9
  # Try to read socket file path from config
10
10
  config_path = "/opt/dsf/conf/config.json"
@@ -1,12 +1,14 @@
1
+ from typing import Any
2
+
1
3
  class BaseCommand:
2
4
  """Base class of a command."""
3
5
 
4
6
  @classmethod
5
- def from_json(cls, data):
7
+ def from_json(cls, data: Any):
6
8
  """Deserialize an instance of this class from a JSON deserialized dictionary"""
7
9
  return cls(**data)
8
10
 
9
- def __init__(self, command: str, **kwargs):
11
+ def __init__(self, command: str, **kwargs: Any):
10
12
  self.command = command
11
13
  for key, value in kwargs.items():
12
14
  self.__dict__[key] = value