dsf-python 3.6.0b2.post3__tar.gz → 3.6.0rc1.post1__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 (197) hide show
  1. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/PKG-INFO +15 -2
  2. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/setup.cfg +1 -1
  3. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/setup.py +1 -1
  4. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/__init__.py +1 -1
  5. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/connections/base_connection.py +7 -1
  6. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/connections/intercept_connection.py +2 -1
  7. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/http.py +2 -1
  8. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/heat/heater.py +23 -1
  9. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/job/gcode_fileinfo.py +6 -0
  10. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/model_collection.py +15 -6
  11. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/axis.py +11 -0
  12. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/extruder.py +11 -0
  13. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/input_shaping.py +5 -18
  14. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/network/network_interface.py +14 -1
  15. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/analog_sensor.py +20 -0
  16. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/filament_monitors/Duet3DFilamentMonitor.py +11 -0
  17. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/filament_monitors/pulsed_filament_monitor.py +10 -0
  18. dsf_python-3.6.0rc1.post1/src/dsf/object_model/spindles/spindle_type.py +14 -0
  19. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/spindles/spindles.py +19 -0
  20. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/tools/tools.py +24 -0
  21. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/utils.py +8 -3
  22. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf_python.egg-info/PKG-INFO +15 -2
  23. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf_python.egg-info/SOURCES.txt +1 -0
  24. dsf_python-3.6.0rc1.post1/tests/test_custom_http_endpoint.py +103 -0
  25. dsf_python-3.6.0rc1.post1/tests/test_custom_m_codes.py +145 -0
  26. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/tests/test_object_model.py +23 -5
  27. dsf_python-3.6.0rc1.post1/tests/test_send_simple_code.py +106 -0
  28. dsf_python-3.6.0rc1.post1/tests/test_subscribe_object_model.py +136 -0
  29. dsf_python-3.6.0b2.post3/tests/test_custom_http_endpoint.py +0 -53
  30. dsf_python-3.6.0b2.post3/tests/test_custom_m_codes.py +0 -70
  31. dsf_python-3.6.0b2.post3/tests/test_send_simple_code.py +0 -46
  32. dsf_python-3.6.0b2.post3/tests/test_subscribe_object_model.py +0 -54
  33. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/LICENSE +0 -0
  34. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/MANIFEST.in +0 -0
  35. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/README.md +0 -0
  36. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/pyproject.toml +0 -0
  37. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/__init__.py +0 -0
  38. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/base_command.py +0 -0
  39. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/code.py +0 -0
  40. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/code_channel.py +0 -0
  41. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/code_flags.py +0 -0
  42. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/code_interception.py +0 -0
  43. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/code_parameter.py +0 -0
  44. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/code_type.py +0 -0
  45. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/condition_type.py +0 -0
  46. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/files.py +0 -0
  47. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/generic.py +0 -0
  48. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/http_endpoints.py +0 -0
  49. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/model_subscription.py +0 -0
  50. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/object_model.py +0 -0
  51. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/packages.py +0 -0
  52. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/plugins.py +0 -0
  53. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/responses.py +0 -0
  54. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/commands/user_sessions.py +0 -0
  55. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/connections/__init__.py +0 -0
  56. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/connections/base_command_connection.py +0 -0
  57. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/connections/command_connection.py +0 -0
  58. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/connections/exceptions.py +0 -0
  59. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/connections/init_messages/__init__.py +0 -0
  60. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/connections/init_messages/client_init_messages.py +0 -0
  61. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/connections/init_messages/server_init_message.py +0 -0
  62. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/connections/subscribe_connection.py +0 -0
  63. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/exceptions.py +0 -0
  64. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/__init__.py +0 -0
  65. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/boards/__init__.py +0 -0
  66. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/boards/accelerometer.py +0 -0
  67. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/boards/board_closed_loop.py +0 -0
  68. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/boards/boards.py +0 -0
  69. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/boards/direct_display/__init__.py +0 -0
  70. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/boards/direct_display/direct_display.py +0 -0
  71. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/boards/direct_display/direct_display_controller.py +0 -0
  72. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/boards/direct_display/direct_display_encoder.py +0 -0
  73. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/boards/direct_display/direct_display_screen.py +0 -0
  74. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/boards/direct_display/direct_display_screen_st7567.py +0 -0
  75. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/boards/driver.py +0 -0
  76. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/boards/driver_closed_loop.py +0 -0
  77. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/boards/inductive_sensor.py +0 -0
  78. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/boards/min_max_current.py +0 -0
  79. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/directories/__init__.py +0 -0
  80. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/directories/directories.py +0 -0
  81. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/fans/__init__.py +0 -0
  82. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/fans/fan_thermostatic_control.py +0 -0
  83. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/fans/fans.py +0 -0
  84. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/heat/__init__.py +0 -0
  85. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/heat/heat.py +0 -0
  86. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/heat/heater_model.py +0 -0
  87. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/heat/heater_model_pid.py +0 -0
  88. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/heat/heater_monitor.py +0 -0
  89. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/inputs/__init__.py +0 -0
  90. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/inputs/compatibility.py +0 -0
  91. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/inputs/distance_unit.py +0 -0
  92. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/inputs/input_channel.py +0 -0
  93. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/inputs/input_channel_state.py +0 -0
  94. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/inputs/inputs.py +0 -0
  95. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/job/__init__.py +0 -0
  96. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/job/build.py +0 -0
  97. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/job/build_object.py +0 -0
  98. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/job/job.py +0 -0
  99. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/job/layer.py +0 -0
  100. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/job/thumbnail_info.py +0 -0
  101. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/job/times_left.py +0 -0
  102. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/led_strips/__init__.py +0 -0
  103. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/led_strips/led_strip.py +0 -0
  104. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/limits/__init__.py +0 -0
  105. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/limits/limits.py +0 -0
  106. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/messages/__init__.py +0 -0
  107. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/messages/messages.py +0 -0
  108. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/model_dictionary.py +0 -0
  109. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/model_object.py +0 -0
  110. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/__init__.py +0 -0
  111. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/current_move.py +0 -0
  112. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/driver_id.py +0 -0
  113. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/extruder_non_linear.py +0 -0
  114. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/keepout_zone.py +0 -0
  115. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/kinematics/__init__.py +0 -0
  116. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/kinematics/core_kinematics.py +0 -0
  117. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/kinematics/delta_kinematics.py +0 -0
  118. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/kinematics/delta_tower.py +0 -0
  119. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/kinematics/hangprinter_kinematics.py +0 -0
  120. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/kinematics/kinematics.py +0 -0
  121. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/kinematics/kinematics_name.py +0 -0
  122. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/kinematics/polar_kinematics.py +0 -0
  123. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/kinematics/scara_kinematics.py +0 -0
  124. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/kinematics/tilt_correction.py +0 -0
  125. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/kinematics/zleadscrew_kinematics.py +0 -0
  126. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/microstepping.py +0 -0
  127. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/motors_idle_control.py +0 -0
  128. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/move.py +0 -0
  129. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/move_calibration.py +0 -0
  130. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/move_compensation.py +0 -0
  131. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/move_deviations.py +0 -0
  132. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/move_queue_item.py +0 -0
  133. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/move_rotation.py +0 -0
  134. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/move_segmentation.py +0 -0
  135. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/probe_grid.py +0 -0
  136. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/move/skew.py +0 -0
  137. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/network/__init__.py +0 -0
  138. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/network/network.py +0 -0
  139. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/network/network_interface_type.py +0 -0
  140. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/network/network_protocol.py +0 -0
  141. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/network/network_state.py +0 -0
  142. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/object_model.py +0 -0
  143. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/plugins/__init__.py +0 -0
  144. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/plugins/plugin_manifest.py +0 -0
  145. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/plugins/plugins.py +0 -0
  146. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/plugins/sbc_permissions.py +0 -0
  147. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sbc/__init__.py +0 -0
  148. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sbc/cpu.py +0 -0
  149. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sbc/dsf/__init__.py +0 -0
  150. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sbc/dsf/dsf.py +0 -0
  151. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sbc/dsf/http_endpoint.py +0 -0
  152. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sbc/dsf/http_endpoint_type.py +0 -0
  153. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sbc/dsf/user_sessions/__init__.py +0 -0
  154. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sbc/dsf/user_sessions/access_level.py +0 -0
  155. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sbc/dsf/user_sessions/session_type.py +0 -0
  156. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sbc/dsf/user_sessions/user_sessions.py +0 -0
  157. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sbc/memory.py +0 -0
  158. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sbc/sbc.py +0 -0
  159. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/__init__.py +0 -0
  160. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/analog_sensor_type.py +0 -0
  161. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/endstop.py +0 -0
  162. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/endstop_type.py +0 -0
  163. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/filament_monitors/__init__.py +0 -0
  164. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/filament_monitors/filament_monitor.py +0 -0
  165. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/filament_monitors/filament_monitor_enable_type.py +0 -0
  166. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/filament_monitors/filament_monitor_status.py +0 -0
  167. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/filament_monitors/filament_monitor_type.py +0 -0
  168. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/filament_monitors/laser_filament_monitor.py +0 -0
  169. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/filament_monitors/rotating_magnet_filament_monitor.py +0 -0
  170. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/gp_input_port.py +0 -0
  171. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/probe.py +0 -0
  172. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/probe_type.py +0 -0
  173. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/sensors.py +0 -0
  174. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/sensors/temperature_error.py +0 -0
  175. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/spindles/__init__.py +0 -0
  176. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/spindles/spindle_state.py +0 -0
  177. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/state/__init__.py +0 -0
  178. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/state/beep_request.py +0 -0
  179. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/state/gp_output_port.py +0 -0
  180. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/state/log_level.py +0 -0
  181. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/state/machine_mode.py +0 -0
  182. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/state/machine_status.py +0 -0
  183. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/state/message_box.py +0 -0
  184. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/state/restore_point.py +0 -0
  185. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/state/startup_error.py +0 -0
  186. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/state/state.py +0 -0
  187. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/tools/__init__.py +0 -0
  188. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/tools/tool_retraction.py +0 -0
  189. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/tools/tool_state.py +0 -0
  190. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/volumes/__init__.py +0 -0
  191. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/object_model/volumes/volumes.py +0 -0
  192. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/utility/__init__.py +0 -0
  193. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf/utils.py +0 -0
  194. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf_python.egg-info/dependency_links.txt +0 -0
  195. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf_python.egg-info/requires.txt +0 -0
  196. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/src/dsf_python.egg-info/top_level.txt +0 -0
  197. {dsf_python-3.6.0b2.post3 → dsf_python-3.6.0rc1.post1}/tests/test_code.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: dsf-python
3
- Version: 3.6.0b2.post3
3
+ Version: 3.6.0rc1.post1
4
4
  Summary: Python interface to access DuetSoftwareFramework
5
5
  Home-page: https://github.com/Duet3D/dsf-python
6
6
  Author: Duet3D Ltd.
@@ -29,6 +29,19 @@ Requires-Dist: python-dateutil
29
29
  Provides-Extra: dev
30
30
  Requires-Dist: sphinx; extra == "dev"
31
31
  Requires-Dist: tox; extra == "dev"
32
+ Dynamic: author
33
+ Dynamic: author-email
34
+ Dynamic: classifier
35
+ Dynamic: description
36
+ Dynamic: description-content-type
37
+ Dynamic: home-page
38
+ Dynamic: keywords
39
+ Dynamic: license-file
40
+ Dynamic: project-url
41
+ Dynamic: provides-extra
42
+ Dynamic: requires-dist
43
+ Dynamic: requires-python
44
+ Dynamic: summary
32
45
 
33
46
  # Duet Software Framework Python Bindings
34
47
 
@@ -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-b2.post3
8
+ forced-upstream-version = 3.6.0-rc1.post1
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-b2.post3",
9
+ version="3.6.0-rc1.post1",
10
10
  description="Python interface to access DuetSoftwareFramework",
11
11
  long_description=long_description,
12
12
  long_description_content_type="text/markdown",
@@ -1,4 +1,4 @@
1
- __version__ = "3.6.0-b2.post3"
1
+ __version__ = "3.6.0-rc1.post1"
2
2
 
3
3
  # path to unix socket file
4
4
  SOCKET_FILE = "/run/dsf/dcs.sock"
@@ -1,5 +1,6 @@
1
1
  import json
2
2
  import socket
3
+ import time
3
4
  from typing import Optional
4
5
 
5
6
  from .exceptions import IncompatibleVersionException, InternalServerException, TaskCanceledException
@@ -25,7 +26,8 @@ class BaseConnection:
25
26
 
26
27
  self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
27
28
  self.socket.connect(socket_file)
28
- self.socket.setblocking(True)
29
+ self.socket.settimeout(self.timeout if self.timeout > 0 else None)
30
+ # self.socket.setblocking(True)
29
31
  server_init_msg = server_init_message.ServerInitMessage.from_json(
30
32
  json.loads(self.socket.recv(50).decode("utf8"))
31
33
  )
@@ -98,7 +100,11 @@ class BaseConnection:
98
100
  json_string = json_string[:end_index]
99
101
  else:
100
102
  found = False
103
+ start_time = time.time()
101
104
  while not found:
105
+ if (self.timeout > 0) and (time.time() - start_time > self.timeout):
106
+ raise TimeoutError("Timeout while waiting for JSON response")
107
+
102
108
  # Refill the buffer and check again
103
109
  BUFF_SIZE = 4096 # 4 KiB
104
110
  data = b""
@@ -37,8 +37,9 @@ class InterceptConnection(BaseCommandConnection):
37
37
  auto_evaluate_expression: bool = True,
38
38
  priority_codes: bool = False,
39
39
  debug: bool = False,
40
+ timeout: int = 0
40
41
  ):
41
- super().__init__(debug)
42
+ super().__init__(debug, timeout)
42
43
  self.interception_mode = interception_mode
43
44
  self.channels = channels if channels is not None else CodeChannel.list()
44
45
  self.filters = filters
@@ -140,7 +140,8 @@ class HttpEndpointUnixSocket:
140
140
  if self._loop is not None:
141
141
  # TODO: this enables correctly ending the loop. Why?
142
142
  self._loop.set_debug(True)
143
- self._server.close()
143
+ if self._server is not None:
144
+ self._server.close()
144
145
  self._loop.stop()
145
146
  self.event_loop.cancel()
146
147
  self.executor.shutdown(wait=False)
@@ -1,5 +1,5 @@
1
1
  from enum import Enum
2
- from typing import List
2
+ from typing import List, Union
3
3
 
4
4
  from .heater_model import HeaterModel
5
5
  from .heater_monitor import HeaterMonitor
@@ -39,6 +39,10 @@ class Heater(ModelObject):
39
39
  self._avg_pwm = 0
40
40
  # Current temperature of the heater (in C)
41
41
  self._current = -273.15
42
+ # Current feedforward PWM boost applied to the heater
43
+ self._extr_pwm_boost = 0.0
44
+ # Current temperature boost applied to the heater
45
+ self._extr_temp_boost = 0.0
42
46
  # Maximum temperature allowed for this heater (in C)
43
47
  # This is only temporary and should be replaced by a representation of the heater protection as in RRF
44
48
  self._max = 285
@@ -89,6 +93,24 @@ class Heater(ModelObject):
89
93
  def current(self, value: float):
90
94
  self._current = float(value)
91
95
 
96
+ @property
97
+ def extr_pwm_boost(self) -> float:
98
+ """Current feedforward PWM boost applied to the heater"""
99
+ return self._extr_pwm_boost
100
+
101
+ @extr_pwm_boost.setter
102
+ def extr_pwm_boost(self, value: float):
103
+ self._extr_pwm_boost = float(value)
104
+
105
+ @property
106
+ def extr_temp_boost(self) -> float:
107
+ """Current temperature boost applied to the heater"""
108
+ return self._extr_temp_boost
109
+
110
+ @extr_temp_boost.setter
111
+ def extr_temp_boost(self, value: float):
112
+ self._extr_temp_boost = float(value)
113
+
92
114
  @property
93
115
  def max(self) -> float:
94
116
  """Maximum temperature allowed for this heater (in C)
@@ -11,6 +11,7 @@ class GCodeFileInfo(ModelObject):
11
11
 
12
12
  def __init__(self):
13
13
  super().__init__()
14
+ self._custom_info = {}
14
15
  self._filament = []
15
16
  self._file_name = ""
16
17
  self._generated_by = ""
@@ -23,6 +24,11 @@ class GCodeFileInfo(ModelObject):
23
24
  self._size = 0
24
25
  self._thumbnails = ModelCollection(ThumbnailInfo)
25
26
 
27
+ @property
28
+ def custom_info(self) -> dict:
29
+ """Custom information extracted from the G-code file"""
30
+ return self._custom_info
31
+
26
32
  @property
27
33
  def filament(self) -> List[float]:
28
34
  """Filament consumption per extruder drive (in mm)"""
@@ -1,25 +1,34 @@
1
+ from typing import Generic, TypeVar, Type, List, Dict, Any, Union, Optional
1
2
  from .utils import is_model_object
2
3
 
4
+ T = TypeVar('T')
3
5
 
4
- class ModelCollection(list):
6
+
7
+ class ModelCollection(Generic[T], list):
5
8
  """
6
9
  Class for storing model object items in a list
7
10
  Useful for updating model object items from JSON data (patches)
8
11
  """
9
12
 
10
- def __init__(self, item_constructor, value=None):
13
+ def __init__(self, item_constructor: Type[T], value: Optional[List[T]] = None) -> None:
11
14
  """
12
-
13
15
  :param item_constructor: Item constructor type that items must derive from
14
16
  :param value: Value used to initialize the list from
15
17
  """
16
18
  super().__init__()
17
- self._item_constructor = item_constructor
19
+ self._item_constructor: Type[T] = item_constructor
18
20
 
19
21
  if value is not None:
20
- self[:] = value
22
+ self[:] = []
23
+ for (i, item) in enumerate(value):
24
+ if isinstance(item, self._item_constructor):
25
+ self.append(item)
26
+ else:
27
+ ref_item = self._item_constructor()
28
+ ref_item.update_from_json(item)
29
+ self.append(ref_item)
21
30
 
22
- def update_from_json(self, json_element):
31
+ def update_from_json(self, json_element: List[Any]) -> 'ModelCollection[T]':
23
32
  """
24
33
  Update this instance from the given data
25
34
  :param json_element: JSON data to upgrade this instance from
@@ -86,6 +86,8 @@ class Axis(ModelObject):
86
86
  self._percent_current = 100
87
87
  # Percentage applied to the motor current during standstill (0..100 or None if not supported)
88
88
  self._percent_stst_current = None
89
+ # Motor jerk during the current print only (in mm/s)
90
+ self._printing_jerk = None
89
91
  # Reduced accelerations used by Z probing and stall homing moves (in mm/s^2)
90
92
  self._reduced_acceleration = 0
91
93
  # Maximum speed (in mm/min)
@@ -242,6 +244,15 @@ class Axis(ModelObject):
242
244
  def percent_stst_current(self, value):
243
245
  self._percent_stst_current = int(value) if value is not None else None
244
246
 
247
+ @property
248
+ def printing_jerk(self) -> Union[float, None]:
249
+ """Motor jerk during the current print only (in mm/s)"""
250
+ return self._printing_jerk
251
+
252
+ @printing_jerk.setter
253
+ def printing_jerk(self, value):
254
+ self._printing_jerk = float(value) if value is not None else None
255
+
245
256
  @property
246
257
  def reduced_acceleration(self) -> float:
247
258
  """Reduced accelerations used by Z probing and stall homing moves (in mm/s^2)"""
@@ -41,6 +41,8 @@ class Extruder(ModelObject):
41
41
  self._position = 0
42
42
  # Pressure advance
43
43
  self._pressure_advance = 0
44
+ # Motor jerk during the current print only (in mm/s)
45
+ self._printing_jerk = None
44
46
  # Raw extruder position as commanded by the slicer without extrusion factor applied (in mm)
45
47
  self._raw_position = 0
46
48
  # Maximum speed (in mm/s)
@@ -148,6 +150,15 @@ class Extruder(ModelObject):
148
150
  def pressure_advance(self, value):
149
151
  self._pressure_advance = float(value)
150
152
 
153
+ @property
154
+ def printing_jerk(self) -> Union[float, None]:
155
+ """Motor jerk during the current print only (in mm/s)"""
156
+ return self._printing_jerk
157
+
158
+ @printing_jerk.setter
159
+ def printing_jerk(self, value):
160
+ self._printing_jerk = float(value) if value is not None else None
161
+
151
162
  @property
152
163
  def raw_position(self) -> float:
153
164
  """Raw extruder position as commanded by the slicer without extrusion factor applied (in mm)"""
@@ -40,13 +40,10 @@ class InputShaping(ModelObject):
40
40
  self._amplitudes = []
41
41
  # Damping factor
42
42
  self._damping = 0.1
43
- # Input shaper durations (in s)
44
- self._durations = []
43
+ # Input shaper delays (in s)
44
+ self._delays = []
45
45
  # Frequency (in Hz)
46
46
  self._frequency = 40
47
- # Minimum fraction of the original acceleration or feed rate to which the acceleration or
48
- # feed rate may be reduced in order to apply input shaping
49
- self._reduction_limit = 0.25
50
47
  # Configured input shaping type
51
48
  self._type = InputShapingType.none
52
49
 
@@ -65,9 +62,9 @@ class InputShaping(ModelObject):
65
62
  self._damping = float(value)
66
63
 
67
64
  @property
68
- def durations(self) -> List[float]:
69
- """Input shaper durations (in s)"""
70
- return self._durations
65
+ def delays(self) -> List[float]:
66
+ """Input shaper delays (in s)"""
67
+ return self._delays
71
68
 
72
69
  @property
73
70
  def frequency(self) -> float:
@@ -78,16 +75,6 @@ class InputShaping(ModelObject):
78
75
  def frequency(self, value):
79
76
  self._frequency = float(value)
80
77
 
81
- @property
82
- def reduction_limit(self) -> float:
83
- """Minimum fraction of the original acceleration or feed rate to which the acceleration or
84
- feed rate may be reduced in order to apply input shaping"""
85
- return self._reduction_limit
86
-
87
- @reduction_limit.setter
88
- def reduction_limit(self, value):
89
- self._reduction_limit = float(value)
90
-
91
78
  @property
92
79
  def type(self) -> InputShapingType:
93
80
  """Configured input shaping type"""
@@ -4,6 +4,7 @@ from .network_interface_type import NetworkInterfaceType
4
4
  from .network_protocol import NetworkProtocol
5
5
  from .network_state import NetworkState
6
6
  from ..model_object import ModelObject
7
+ from ...utils import deprecated
7
8
 
8
9
 
9
10
  class NetworkInterface(ModelObject):
@@ -27,6 +28,8 @@ class NetworkInterface(ModelObject):
27
28
  self._mac = ""
28
29
  # Number of reconnect attempts or null if unknown
29
30
  self._num_reconnects = None
31
+ # Received signal strength indicator of the WiFi adapter (only WiFi, in dBm, or null if unknown)
32
+ self._rssi = None
30
33
  # Signal of the Wi-Fi adapter (only Wi-Fi, in dBm, or null if unknown)
31
34
  self._signal = None
32
35
  # Speed of the network interface (in MBit, null if unknown, 0 if not connected)
@@ -112,10 +115,20 @@ class NetworkInterface(ModelObject):
112
115
  self._num_reconnects = int(value) if value is not None else None
113
116
 
114
117
  @property
118
+ def rssi(self) -> Union[int, None]:
119
+ """Received signal strength indicator of the WiFi adapter (only WiFi, in dBm, or None if unknown)"""
120
+ return self._rssi
121
+
122
+ @rssi.setter
123
+ def rssi(self, value):
124
+ self._rssi = int(value) if value is not None else None
125
+
126
+ @property
127
+ @deprecated(f"Use '{__name__}.rssi' instead.")
115
128
  def signal(self) -> Union[int, None]:
116
129
  """Signal of the Wi-Fi adapter (only Wi-Fi, in dBm, or null if unknown)"""
117
130
  return self._signal
118
-
131
+
119
132
  @signal.setter
120
133
  def signal(self, value):
121
134
  self._signal = int(value) if value is not None else None
@@ -12,7 +12,9 @@ class AnalogSensor(ModelObject):
12
12
  super(AnalogSensor, self).__init__()
13
13
  self._beta = None
14
14
  self._c = None
15
+ self._high_reading = None
15
16
  self._last_reading = None
17
+ self._low_reading = None
16
18
  self._name = None
17
19
  self._offset_adj = 0.0
18
20
  self._port = None
@@ -40,6 +42,15 @@ class AnalogSensor(ModelObject):
40
42
  def c(self, value):
41
43
  self._c = float(value) if value is not None else None
42
44
 
45
+ @property
46
+ def high_reading(self) -> Union[float, None]:
47
+ """High sensor reading (only linear analog sensors, otherwise null)"""
48
+ return self._high_reading
49
+
50
+ @high_reading.setter
51
+ def high_reading(self, value):
52
+ self._high_reading = float(value) if value is not None else None
53
+
43
54
  @property
44
55
  def last_reading(self) -> Union[float, None]:
45
56
  """Last sensor reading (in C) or null if invalid"""
@@ -48,6 +59,15 @@ class AnalogSensor(ModelObject):
48
59
  @last_reading.setter
49
60
  def last_reading(self, value):
50
61
  self._last_reading = float(value) if value is not None else None
62
+
63
+ @property
64
+ def low_reading(self) -> Union[float, None]:
65
+ """Low sensor reading (only linear analog sensors, otherwise null)"""
66
+ return self._low_reading
67
+
68
+ @low_reading.setter
69
+ def low_reading(self, value):
70
+ self._low_reading = float(value) if value is not None else None
51
71
 
52
72
  @property
53
73
  def name(self) -> Union[str, None]:
@@ -17,6 +17,8 @@ class Duet3DFilamentMonitor(FilamentMonitor):
17
17
  self._max_percentage = None
18
18
  # Minimum ratio of measured vs. commanded movement
19
19
  self._min_percentage = None
20
+ # Position of the sensor (in mm)
21
+ self._position = 0
20
22
  # Total extrusion commanded (in mm)
21
23
  self._total_extrusion = 0
22
24
 
@@ -55,6 +57,15 @@ class Duet3DFilamentMonitor(FilamentMonitor):
55
57
  @min_percentage.setter
56
58
  def min_percentage(self, value):
57
59
  self._min_percentage = None if value is None else int(value)
60
+
61
+ @property
62
+ def position(self) -> float:
63
+ """Position of the sensor (in mm)"""
64
+ return self._position
65
+
66
+ @position.setter
67
+ def position(self, value):
68
+ self._position = float(value)
58
69
 
59
70
  @property
60
71
  def total_extrusion(self) -> float:
@@ -108,9 +108,19 @@ class PulsedFilamentMonitor(FilamentMonitor):
108
108
  super(PulsedFilamentMonitor, self).__init__()
109
109
  self._calibrated = None
110
110
  self._configured = PulsedFilamentMonitorConfigured()
111
+ self._position = None
111
112
  self._type = FilamentMonitorType.Pulsed
112
113
 
113
114
  @property
114
115
  def configured(self) -> PulsedFilamentMonitorConfigured:
115
116
  """Configured properties of this filament monitor"""
116
117
  return self._configured
118
+
119
+ @property
120
+ def position(self) -> float:
121
+ """Position of the sensor (in mm)"""
122
+ return self._position
123
+
124
+ @position.setter
125
+ def position(self, value):
126
+ self._position = float(value)
@@ -0,0 +1,14 @@
1
+ from enum import Enum
2
+
3
+
4
+ class SpindleType(str, Enum):
5
+ """Possible types of spindles"""
6
+
7
+ # Spindle not configured
8
+ null = "null"
9
+
10
+ # Enable and direction
11
+ enaDir = "enaDir"
12
+
13
+ # Forward and reverse
14
+ fwdRev = "fwdRev"
@@ -1,4 +1,5 @@
1
1
  from .spindle_state import SpindleState
2
+ from .spindle_type import SpindleType
2
3
  from ..model_object import ModelObject
3
4
 
4
5
  from typing import Union
@@ -29,6 +30,8 @@ class Spindle(ModelObject):
29
30
  self._min_pwm = 0
30
31
  # Current state
31
32
  self._state = SpindleState.unconfigured
33
+ # Spindle type
34
+ self._type = SpindleType.null
32
35
 
33
36
  @property
34
37
  def active(self) -> Union[int, None]:
@@ -126,3 +129,19 @@ class Spindle(ModelObject):
126
129
  self._state = value
127
130
  else:
128
131
  raise TypeError(f"{__name__}.state must be of type SpindleState. Got {type(value)}: {value}")
132
+
133
+ @property
134
+ def type(self) -> SpindleType:
135
+ """Spindle type"""
136
+ return self._type
137
+
138
+ @type.setter
139
+ def type(self, value):
140
+ if value is None or value == "":
141
+ self._type = SpindleType.null
142
+ elif isinstance(value, str):
143
+ self._type = SpindleType(value)
144
+ elif isinstance(value, SpindleType):
145
+ self._type = value
146
+ else:
147
+ raise TypeError(f"{__name__}.type must be of type SpindleType. Got {type(value)}: {value}")
@@ -3,6 +3,7 @@ from typing import List
3
3
  from .tool_state import ToolState
4
4
  from .tool_retraction import ToolRetraction
5
5
  from ..model_object import ModelObject
6
+ from ...utils import deprecated
6
7
 
7
8
 
8
9
  class Tool(ModelObject):
@@ -20,6 +21,9 @@ class Tool(ModelObject):
20
21
  self._fans = []
21
22
  # Feedforward coefficients to apply to the mapped heaters during extrusions
22
23
  self._feed_forward = []
24
+ self._feed_forward_pwm = []
25
+ self._feed_forward_advance = None
26
+ self._feed_forward_temp = []
23
27
  # Extruder drive index for resolving the tool filament (index or -1)
24
28
  self._filament_extruder = -1
25
29
  # List of associated heaters (indices)
@@ -74,10 +78,30 @@ class Tool(ModelObject):
74
78
  return self._fans
75
79
 
76
80
  @property
81
+ @deprecated("Use feed_forward_pwm instead.")
77
82
  def feed_forward(self) -> List[float]:
78
83
  """Feedforward coefficients to apply to the mapped heaters during extrusions"""
79
84
  return self._feed_forward
80
85
 
86
+ @property
87
+ def feed_forward_advance(self) -> float:
88
+ """Time advance for applying feedforward in milliseconds"""
89
+ return self._feed_forward_advance
90
+
91
+ @feed_forward_advance.setter
92
+ def feed_forward_advance(self, value):
93
+ self._feed_forward_advance = float(value)
94
+
95
+ @property
96
+ def feed_forward_pwm(self) -> List[float]:
97
+ """Feedforward coefficients to apply to the mapped heaters during extrusions"""
98
+ return self._feed_forward_pwm
99
+
100
+ @property
101
+ def feed_forward_temp(self) -> List[float]:
102
+ """Temperature increase per mm/dec extrusion speed"""
103
+ return self._feed_forward_temp
104
+
81
105
  @property
82
106
  def filament_extruder(self) -> int:
83
107
  """Extruder drive index for resolving the tool filament (index or -1)"""
@@ -1,3 +1,5 @@
1
+ from typing import Type, TypeVar, Any, Union, Dict
2
+
1
3
 
2
4
  def is_model_object(o):
3
5
  from .model_object import ModelObject
@@ -7,7 +9,10 @@ def is_model_object(o):
7
9
  return isinstance(o, ModelObject) or isinstance(o, ModelCollection) or isinstance(o, ModelDictionary)
8
10
 
9
11
 
10
- def wrap_model_property(name, model_type):
12
+ T = TypeVar('T') # Type variable for model objects
13
+
14
+
15
+ def wrap_model_property(name: str, model_type: Type[T]) -> Union[Type[T], None]:
11
16
  """
12
17
  Wrap a nullable model object property so that type checks can be performed during update
13
18
  :param name: Property of the derived class
@@ -18,11 +23,11 @@ def wrap_model_property(name, model_type):
18
23
  STORAGE_NAME = '_' + name
19
24
 
20
25
  @property
21
- def prop(self):
26
+ def prop(self) -> Union[Type[T], None]:
22
27
  return getattr(self, STORAGE_NAME)
23
28
 
24
29
  @prop.setter
25
- def prop(self, value):
30
+ def prop(self, value: Union[Type[T], str, Dict[str, Any], None]):
26
31
  if value is None or isinstance(value, model_type):
27
32
  setattr(self, STORAGE_NAME, value)
28
33
  elif isinstance(value, dict): # Update from JSON
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: dsf-python
3
- Version: 3.6.0b2.post3
3
+ Version: 3.6.0rc1.post1
4
4
  Summary: Python interface to access DuetSoftwareFramework
5
5
  Home-page: https://github.com/Duet3D/dsf-python
6
6
  Author: Duet3D Ltd.
@@ -29,6 +29,19 @@ Requires-Dist: python-dateutil
29
29
  Provides-Extra: dev
30
30
  Requires-Dist: sphinx; extra == "dev"
31
31
  Requires-Dist: tox; extra == "dev"
32
+ Dynamic: author
33
+ Dynamic: author-email
34
+ Dynamic: classifier
35
+ Dynamic: description
36
+ Dynamic: description-content-type
37
+ Dynamic: home-page
38
+ Dynamic: keywords
39
+ Dynamic: license-file
40
+ Dynamic: project-url
41
+ Dynamic: provides-extra
42
+ Dynamic: requires-dist
43
+ Dynamic: requires-python
44
+ Dynamic: summary
32
45
 
33
46
  # Duet Software Framework Python Bindings
34
47
 
@@ -160,6 +160,7 @@ src/dsf/object_model/sensors/filament_monitors/pulsed_filament_monitor.py
160
160
  src/dsf/object_model/sensors/filament_monitors/rotating_magnet_filament_monitor.py
161
161
  src/dsf/object_model/spindles/__init__.py
162
162
  src/dsf/object_model/spindles/spindle_state.py
163
+ src/dsf/object_model/spindles/spindle_type.py
163
164
  src/dsf/object_model/spindles/spindles.py
164
165
  src/dsf/object_model/state/__init__.py
165
166
  src/dsf/object_model/state/beep_request.py