meerk40t 0.9.3001__py2.py3-none-any.whl → 0.9.7020__py2.py3-none-any.whl

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 (446) hide show
  1. meerk40t/__init__.py +1 -1
  2. meerk40t/balormk/balor_params.py +167 -167
  3. meerk40t/balormk/clone_loader.py +457 -457
  4. meerk40t/balormk/controller.py +1566 -1512
  5. meerk40t/balormk/cylindermod.py +64 -0
  6. meerk40t/balormk/device.py +966 -1959
  7. meerk40t/balormk/driver.py +778 -591
  8. meerk40t/balormk/galvo_commands.py +1194 -0
  9. meerk40t/balormk/gui/balorconfig.py +237 -111
  10. meerk40t/balormk/gui/balorcontroller.py +191 -184
  11. meerk40t/balormk/gui/baloroperationproperties.py +116 -115
  12. meerk40t/balormk/gui/corscene.py +845 -0
  13. meerk40t/balormk/gui/gui.py +179 -147
  14. meerk40t/balormk/livelightjob.py +466 -382
  15. meerk40t/balormk/mock_connection.py +131 -109
  16. meerk40t/balormk/plugin.py +133 -135
  17. meerk40t/balormk/usb_connection.py +306 -301
  18. meerk40t/camera/__init__.py +1 -1
  19. meerk40t/camera/camera.py +514 -397
  20. meerk40t/camera/gui/camerapanel.py +1241 -1095
  21. meerk40t/camera/gui/gui.py +58 -58
  22. meerk40t/camera/plugin.py +441 -399
  23. meerk40t/ch341/__init__.py +27 -27
  24. meerk40t/ch341/ch341device.py +628 -628
  25. meerk40t/ch341/libusb.py +595 -589
  26. meerk40t/ch341/mock.py +171 -171
  27. meerk40t/ch341/windriver.py +157 -157
  28. meerk40t/constants.py +13 -0
  29. meerk40t/core/__init__.py +1 -1
  30. meerk40t/core/bindalias.py +550 -539
  31. meerk40t/core/core.py +47 -47
  32. meerk40t/core/cutcode/cubiccut.py +73 -73
  33. meerk40t/core/cutcode/cutcode.py +315 -312
  34. meerk40t/core/cutcode/cutgroup.py +141 -137
  35. meerk40t/core/cutcode/cutobject.py +192 -185
  36. meerk40t/core/cutcode/dwellcut.py +37 -37
  37. meerk40t/core/cutcode/gotocut.py +29 -29
  38. meerk40t/core/cutcode/homecut.py +29 -29
  39. meerk40t/core/cutcode/inputcut.py +34 -34
  40. meerk40t/core/cutcode/linecut.py +33 -33
  41. meerk40t/core/cutcode/outputcut.py +34 -34
  42. meerk40t/core/cutcode/plotcut.py +335 -335
  43. meerk40t/core/cutcode/quadcut.py +61 -61
  44. meerk40t/core/cutcode/rastercut.py +168 -148
  45. meerk40t/core/cutcode/waitcut.py +34 -34
  46. meerk40t/core/cutplan.py +1843 -1316
  47. meerk40t/core/drivers.py +330 -329
  48. meerk40t/core/elements/align.py +801 -669
  49. meerk40t/core/elements/branches.py +1858 -1507
  50. meerk40t/core/elements/clipboard.py +229 -219
  51. meerk40t/core/elements/element_treeops.py +4595 -2837
  52. meerk40t/core/elements/element_types.py +125 -105
  53. meerk40t/core/elements/elements.py +4315 -3617
  54. meerk40t/core/elements/files.py +117 -64
  55. meerk40t/core/elements/geometry.py +473 -224
  56. meerk40t/core/elements/grid.py +467 -316
  57. meerk40t/core/elements/materials.py +158 -94
  58. meerk40t/core/elements/notes.py +50 -38
  59. meerk40t/core/elements/offset_clpr.py +934 -912
  60. meerk40t/core/elements/offset_mk.py +963 -955
  61. meerk40t/core/elements/penbox.py +339 -267
  62. meerk40t/core/elements/placements.py +300 -83
  63. meerk40t/core/elements/render.py +785 -687
  64. meerk40t/core/elements/shapes.py +2618 -2092
  65. meerk40t/core/elements/testcases.py +105 -0
  66. meerk40t/core/elements/trace.py +651 -563
  67. meerk40t/core/elements/tree_commands.py +415 -409
  68. meerk40t/core/elements/undo_redo.py +116 -58
  69. meerk40t/core/elements/wordlist.py +319 -200
  70. meerk40t/core/exceptions.py +9 -9
  71. meerk40t/core/laserjob.py +220 -220
  72. meerk40t/core/logging.py +63 -63
  73. meerk40t/core/node/blobnode.py +83 -86
  74. meerk40t/core/node/bootstrap.py +105 -103
  75. meerk40t/core/node/branch_elems.py +40 -31
  76. meerk40t/core/node/branch_ops.py +45 -38
  77. meerk40t/core/node/branch_regmark.py +48 -41
  78. meerk40t/core/node/cutnode.py +29 -32
  79. meerk40t/core/node/effect_hatch.py +375 -257
  80. meerk40t/core/node/effect_warp.py +398 -0
  81. meerk40t/core/node/effect_wobble.py +441 -309
  82. meerk40t/core/node/elem_ellipse.py +404 -309
  83. meerk40t/core/node/elem_image.py +1082 -801
  84. meerk40t/core/node/elem_line.py +358 -292
  85. meerk40t/core/node/elem_path.py +259 -201
  86. meerk40t/core/node/elem_point.py +129 -102
  87. meerk40t/core/node/elem_polyline.py +310 -246
  88. meerk40t/core/node/elem_rect.py +376 -286
  89. meerk40t/core/node/elem_text.py +445 -418
  90. meerk40t/core/node/filenode.py +59 -40
  91. meerk40t/core/node/groupnode.py +138 -74
  92. meerk40t/core/node/image_processed.py +777 -766
  93. meerk40t/core/node/image_raster.py +156 -113
  94. meerk40t/core/node/layernode.py +31 -31
  95. meerk40t/core/node/mixins.py +135 -107
  96. meerk40t/core/node/node.py +1427 -1304
  97. meerk40t/core/node/nutils.py +117 -114
  98. meerk40t/core/node/op_cut.py +463 -335
  99. meerk40t/core/node/op_dots.py +296 -251
  100. meerk40t/core/node/op_engrave.py +414 -311
  101. meerk40t/core/node/op_image.py +755 -369
  102. meerk40t/core/node/op_raster.py +787 -522
  103. meerk40t/core/node/place_current.py +37 -40
  104. meerk40t/core/node/place_point.py +329 -126
  105. meerk40t/core/node/refnode.py +58 -47
  106. meerk40t/core/node/rootnode.py +225 -219
  107. meerk40t/core/node/util_console.py +48 -48
  108. meerk40t/core/node/util_goto.py +84 -65
  109. meerk40t/core/node/util_home.py +61 -61
  110. meerk40t/core/node/util_input.py +102 -102
  111. meerk40t/core/node/util_output.py +102 -102
  112. meerk40t/core/node/util_wait.py +65 -65
  113. meerk40t/core/parameters.py +709 -707
  114. meerk40t/core/planner.py +875 -785
  115. meerk40t/core/plotplanner.py +656 -652
  116. meerk40t/core/space.py +120 -113
  117. meerk40t/core/spoolers.py +706 -705
  118. meerk40t/core/svg_io.py +1836 -1549
  119. meerk40t/core/treeop.py +534 -445
  120. meerk40t/core/undos.py +278 -124
  121. meerk40t/core/units.py +784 -680
  122. meerk40t/core/view.py +393 -322
  123. meerk40t/core/webhelp.py +62 -62
  124. meerk40t/core/wordlist.py +513 -504
  125. meerk40t/cylinder/cylinder.py +247 -0
  126. meerk40t/cylinder/gui/cylindersettings.py +41 -0
  127. meerk40t/cylinder/gui/gui.py +24 -0
  128. meerk40t/device/__init__.py +1 -1
  129. meerk40t/device/basedevice.py +322 -123
  130. meerk40t/device/devicechoices.py +50 -0
  131. meerk40t/device/dummydevice.py +163 -128
  132. meerk40t/device/gui/defaultactions.py +618 -602
  133. meerk40t/device/gui/effectspanel.py +114 -0
  134. meerk40t/device/gui/formatterpanel.py +253 -290
  135. meerk40t/device/gui/warningpanel.py +337 -260
  136. meerk40t/device/mixins.py +13 -13
  137. meerk40t/dxf/__init__.py +1 -1
  138. meerk40t/dxf/dxf_io.py +766 -554
  139. meerk40t/dxf/plugin.py +47 -35
  140. meerk40t/external_plugins.py +79 -79
  141. meerk40t/external_plugins_build.py +28 -28
  142. meerk40t/extra/cag.py +112 -116
  143. meerk40t/extra/coolant.py +403 -0
  144. meerk40t/extra/encode_detect.py +204 -0
  145. meerk40t/extra/ezd.py +1165 -1165
  146. meerk40t/extra/hershey.py +834 -340
  147. meerk40t/extra/imageactions.py +322 -316
  148. meerk40t/extra/inkscape.py +628 -622
  149. meerk40t/extra/lbrn.py +424 -424
  150. meerk40t/extra/outerworld.py +283 -0
  151. meerk40t/extra/param_functions.py +1542 -1556
  152. meerk40t/extra/potrace.py +257 -253
  153. meerk40t/extra/serial_exchange.py +118 -0
  154. meerk40t/extra/updater.py +602 -453
  155. meerk40t/extra/vectrace.py +147 -146
  156. meerk40t/extra/winsleep.py +83 -83
  157. meerk40t/extra/xcs_reader.py +597 -0
  158. meerk40t/fill/fills.py +781 -335
  159. meerk40t/fill/patternfill.py +1061 -1061
  160. meerk40t/fill/patterns.py +614 -567
  161. meerk40t/grbl/control.py +87 -87
  162. meerk40t/grbl/controller.py +990 -903
  163. meerk40t/grbl/device.py +1084 -768
  164. meerk40t/grbl/driver.py +989 -771
  165. meerk40t/grbl/emulator.py +532 -497
  166. meerk40t/grbl/gcodejob.py +783 -767
  167. meerk40t/grbl/gui/grblconfiguration.py +373 -298
  168. meerk40t/grbl/gui/grblcontroller.py +485 -271
  169. meerk40t/grbl/gui/grblhardwareconfig.py +269 -153
  170. meerk40t/grbl/gui/grbloperationconfig.py +105 -0
  171. meerk40t/grbl/gui/gui.py +147 -116
  172. meerk40t/grbl/interpreter.py +44 -44
  173. meerk40t/grbl/loader.py +22 -22
  174. meerk40t/grbl/mock_connection.py +56 -56
  175. meerk40t/grbl/plugin.py +294 -264
  176. meerk40t/grbl/serial_connection.py +93 -88
  177. meerk40t/grbl/tcp_connection.py +81 -79
  178. meerk40t/grbl/ws_connection.py +112 -0
  179. meerk40t/gui/__init__.py +1 -1
  180. meerk40t/gui/about.py +2042 -296
  181. meerk40t/gui/alignment.py +1644 -1608
  182. meerk40t/gui/autoexec.py +199 -0
  183. meerk40t/gui/basicops.py +791 -670
  184. meerk40t/gui/bufferview.py +77 -71
  185. meerk40t/gui/busy.py +232 -133
  186. meerk40t/gui/choicepropertypanel.py +1662 -1469
  187. meerk40t/gui/consolepanel.py +706 -542
  188. meerk40t/gui/devicepanel.py +687 -581
  189. meerk40t/gui/dialogoptions.py +110 -107
  190. meerk40t/gui/executejob.py +316 -306
  191. meerk40t/gui/fonts.py +90 -90
  192. meerk40t/gui/functionwrapper.py +252 -0
  193. meerk40t/gui/gui_mixins.py +729 -0
  194. meerk40t/gui/guicolors.py +205 -182
  195. meerk40t/gui/help_assets/help_assets.py +218 -201
  196. meerk40t/gui/helper.py +154 -0
  197. meerk40t/gui/hersheymanager.py +1440 -846
  198. meerk40t/gui/icons.py +3422 -2747
  199. meerk40t/gui/imagesplitter.py +555 -508
  200. meerk40t/gui/keymap.py +354 -344
  201. meerk40t/gui/laserpanel.py +897 -806
  202. meerk40t/gui/laserrender.py +1470 -1232
  203. meerk40t/gui/lasertoolpanel.py +805 -793
  204. meerk40t/gui/magnetoptions.py +436 -0
  205. meerk40t/gui/materialmanager.py +2944 -0
  206. meerk40t/gui/materialtest.py +1722 -1694
  207. meerk40t/gui/mkdebug.py +646 -359
  208. meerk40t/gui/mwindow.py +163 -140
  209. meerk40t/gui/navigationpanels.py +2605 -2467
  210. meerk40t/gui/notes.py +143 -142
  211. meerk40t/gui/opassignment.py +414 -410
  212. meerk40t/gui/operation_info.py +310 -299
  213. meerk40t/gui/plugin.py +500 -328
  214. meerk40t/gui/position.py +714 -669
  215. meerk40t/gui/preferences.py +901 -650
  216. meerk40t/gui/propertypanels/attributes.py +1461 -1131
  217. meerk40t/gui/propertypanels/blobproperty.py +117 -114
  218. meerk40t/gui/propertypanels/consoleproperty.py +83 -80
  219. meerk40t/gui/propertypanels/gotoproperty.py +77 -0
  220. meerk40t/gui/propertypanels/groupproperties.py +223 -217
  221. meerk40t/gui/propertypanels/hatchproperty.py +489 -469
  222. meerk40t/gui/propertypanels/imageproperty.py +2244 -1384
  223. meerk40t/gui/propertypanels/inputproperty.py +59 -58
  224. meerk40t/gui/propertypanels/opbranchproperties.py +82 -80
  225. meerk40t/gui/propertypanels/operationpropertymain.py +1890 -1638
  226. meerk40t/gui/propertypanels/outputproperty.py +59 -58
  227. meerk40t/gui/propertypanels/pathproperty.py +389 -380
  228. meerk40t/gui/propertypanels/placementproperty.py +1214 -383
  229. meerk40t/gui/propertypanels/pointproperty.py +140 -136
  230. meerk40t/gui/propertypanels/propertywindow.py +313 -181
  231. meerk40t/gui/propertypanels/rasterwizardpanels.py +996 -912
  232. meerk40t/gui/propertypanels/regbranchproperties.py +76 -0
  233. meerk40t/gui/propertypanels/textproperty.py +770 -755
  234. meerk40t/gui/propertypanels/waitproperty.py +56 -55
  235. meerk40t/gui/propertypanels/warpproperty.py +121 -0
  236. meerk40t/gui/propertypanels/wobbleproperty.py +255 -204
  237. meerk40t/gui/ribbon.py +2471 -2210
  238. meerk40t/gui/scene/scene.py +1100 -1051
  239. meerk40t/gui/scene/sceneconst.py +22 -22
  240. meerk40t/gui/scene/scenepanel.py +439 -349
  241. meerk40t/gui/scene/scenespacewidget.py +365 -365
  242. meerk40t/gui/scene/widget.py +518 -505
  243. meerk40t/gui/scenewidgets/affinemover.py +215 -215
  244. meerk40t/gui/scenewidgets/attractionwidget.py +315 -309
  245. meerk40t/gui/scenewidgets/bedwidget.py +120 -97
  246. meerk40t/gui/scenewidgets/elementswidget.py +137 -107
  247. meerk40t/gui/scenewidgets/gridwidget.py +785 -745
  248. meerk40t/gui/scenewidgets/guidewidget.py +765 -765
  249. meerk40t/gui/scenewidgets/laserpathwidget.py +66 -66
  250. meerk40t/gui/scenewidgets/machineoriginwidget.py +86 -86
  251. meerk40t/gui/scenewidgets/nodeselector.py +28 -28
  252. meerk40t/gui/scenewidgets/rectselectwidget.py +592 -346
  253. meerk40t/gui/scenewidgets/relocatewidget.py +33 -33
  254. meerk40t/gui/scenewidgets/reticlewidget.py +83 -83
  255. meerk40t/gui/scenewidgets/selectionwidget.py +2958 -2756
  256. meerk40t/gui/simpleui.py +362 -333
  257. meerk40t/gui/simulation.py +2451 -2094
  258. meerk40t/gui/snapoptions.py +208 -203
  259. meerk40t/gui/spoolerpanel.py +1227 -1180
  260. meerk40t/gui/statusbarwidgets/defaultoperations.py +480 -353
  261. meerk40t/gui/statusbarwidgets/infowidget.py +520 -483
  262. meerk40t/gui/statusbarwidgets/opassignwidget.py +356 -355
  263. meerk40t/gui/statusbarwidgets/selectionwidget.py +172 -171
  264. meerk40t/gui/statusbarwidgets/shapepropwidget.py +754 -236
  265. meerk40t/gui/statusbarwidgets/statusbar.py +272 -260
  266. meerk40t/gui/statusbarwidgets/statusbarwidget.py +268 -270
  267. meerk40t/gui/statusbarwidgets/strokewidget.py +267 -251
  268. meerk40t/gui/themes.py +200 -78
  269. meerk40t/gui/tips.py +590 -0
  270. meerk40t/gui/toolwidgets/circlebrush.py +35 -35
  271. meerk40t/gui/toolwidgets/toolcircle.py +248 -242
  272. meerk40t/gui/toolwidgets/toolcontainer.py +82 -77
  273. meerk40t/gui/toolwidgets/tooldraw.py +97 -90
  274. meerk40t/gui/toolwidgets/toolellipse.py +219 -212
  275. meerk40t/gui/toolwidgets/toolimagecut.py +25 -132
  276. meerk40t/gui/toolwidgets/toolline.py +39 -144
  277. meerk40t/gui/toolwidgets/toollinetext.py +79 -236
  278. meerk40t/gui/toolwidgets/toollinetext_inline.py +296 -0
  279. meerk40t/gui/toolwidgets/toolmeasure.py +163 -216
  280. meerk40t/gui/toolwidgets/toolnodeedit.py +2088 -2074
  281. meerk40t/gui/toolwidgets/toolnodemove.py +92 -94
  282. meerk40t/gui/toolwidgets/toolparameter.py +754 -668
  283. meerk40t/gui/toolwidgets/toolplacement.py +108 -108
  284. meerk40t/gui/toolwidgets/toolpoint.py +68 -59
  285. meerk40t/gui/toolwidgets/toolpointlistbuilder.py +294 -0
  286. meerk40t/gui/toolwidgets/toolpointmove.py +183 -0
  287. meerk40t/gui/toolwidgets/toolpolygon.py +288 -403
  288. meerk40t/gui/toolwidgets/toolpolyline.py +38 -196
  289. meerk40t/gui/toolwidgets/toolrect.py +211 -207
  290. meerk40t/gui/toolwidgets/toolrelocate.py +72 -72
  291. meerk40t/gui/toolwidgets/toolribbon.py +598 -113
  292. meerk40t/gui/toolwidgets/tooltabedit.py +546 -0
  293. meerk40t/gui/toolwidgets/tooltext.py +98 -89
  294. meerk40t/gui/toolwidgets/toolvector.py +213 -204
  295. meerk40t/gui/toolwidgets/toolwidget.py +39 -39
  296. meerk40t/gui/usbconnect.py +98 -91
  297. meerk40t/gui/utilitywidgets/buttonwidget.py +18 -18
  298. meerk40t/gui/utilitywidgets/checkboxwidget.py +90 -90
  299. meerk40t/gui/utilitywidgets/controlwidget.py +14 -14
  300. meerk40t/gui/utilitywidgets/cyclocycloidwidget.py +343 -340
  301. meerk40t/gui/utilitywidgets/debugwidgets.py +148 -0
  302. meerk40t/gui/utilitywidgets/handlewidget.py +27 -27
  303. meerk40t/gui/utilitywidgets/harmonograph.py +450 -447
  304. meerk40t/gui/utilitywidgets/openclosewidget.py +40 -40
  305. meerk40t/gui/utilitywidgets/rotationwidget.py +54 -54
  306. meerk40t/gui/utilitywidgets/scalewidget.py +75 -75
  307. meerk40t/gui/utilitywidgets/seekbarwidget.py +183 -183
  308. meerk40t/gui/utilitywidgets/togglewidget.py +142 -142
  309. meerk40t/gui/utilitywidgets/toolbarwidget.py +8 -8
  310. meerk40t/gui/wordlisteditor.py +985 -931
  311. meerk40t/gui/wxmeerk40t.py +1447 -1169
  312. meerk40t/gui/wxmmain.py +5644 -4112
  313. meerk40t/gui/wxmribbon.py +1591 -1076
  314. meerk40t/gui/wxmscene.py +1631 -1453
  315. meerk40t/gui/wxmtree.py +2416 -2089
  316. meerk40t/gui/wxutils.py +1769 -1099
  317. meerk40t/gui/zmatrix.py +102 -102
  318. meerk40t/image/__init__.py +1 -1
  319. meerk40t/image/dither.py +429 -0
  320. meerk40t/image/imagetools.py +2793 -2269
  321. meerk40t/internal_plugins.py +150 -130
  322. meerk40t/kernel/__init__.py +63 -12
  323. meerk40t/kernel/channel.py +259 -212
  324. meerk40t/kernel/context.py +538 -538
  325. meerk40t/kernel/exceptions.py +41 -41
  326. meerk40t/kernel/functions.py +463 -414
  327. meerk40t/kernel/jobs.py +100 -100
  328. meerk40t/kernel/kernel.py +3828 -3571
  329. meerk40t/kernel/lifecycles.py +71 -71
  330. meerk40t/kernel/module.py +49 -49
  331. meerk40t/kernel/service.py +147 -147
  332. meerk40t/kernel/settings.py +383 -343
  333. meerk40t/lihuiyu/controller.py +883 -876
  334. meerk40t/lihuiyu/device.py +1181 -1069
  335. meerk40t/lihuiyu/driver.py +1466 -1372
  336. meerk40t/lihuiyu/gui/gui.py +127 -106
  337. meerk40t/lihuiyu/gui/lhyaccelgui.py +377 -363
  338. meerk40t/lihuiyu/gui/lhycontrollergui.py +741 -651
  339. meerk40t/lihuiyu/gui/lhydrivergui.py +470 -446
  340. meerk40t/lihuiyu/gui/lhyoperationproperties.py +238 -237
  341. meerk40t/lihuiyu/gui/tcpcontroller.py +226 -190
  342. meerk40t/lihuiyu/interpreter.py +53 -53
  343. meerk40t/lihuiyu/laserspeed.py +450 -450
  344. meerk40t/lihuiyu/loader.py +90 -90
  345. meerk40t/lihuiyu/parser.py +404 -404
  346. meerk40t/lihuiyu/plugin.py +101 -102
  347. meerk40t/lihuiyu/tcp_connection.py +111 -109
  348. meerk40t/main.py +231 -165
  349. meerk40t/moshi/builder.py +788 -781
  350. meerk40t/moshi/controller.py +505 -499
  351. meerk40t/moshi/device.py +495 -442
  352. meerk40t/moshi/driver.py +862 -696
  353. meerk40t/moshi/gui/gui.py +78 -76
  354. meerk40t/moshi/gui/moshicontrollergui.py +538 -522
  355. meerk40t/moshi/gui/moshidrivergui.py +87 -75
  356. meerk40t/moshi/plugin.py +43 -43
  357. meerk40t/network/console_server.py +140 -57
  358. meerk40t/network/kernelserver.py +10 -9
  359. meerk40t/network/tcp_server.py +142 -140
  360. meerk40t/network/udp_server.py +103 -77
  361. meerk40t/network/web_server.py +404 -0
  362. meerk40t/newly/controller.py +1158 -1144
  363. meerk40t/newly/device.py +874 -732
  364. meerk40t/newly/driver.py +540 -412
  365. meerk40t/newly/gui/gui.py +219 -188
  366. meerk40t/newly/gui/newlyconfig.py +116 -101
  367. meerk40t/newly/gui/newlycontroller.py +193 -186
  368. meerk40t/newly/gui/operationproperties.py +51 -51
  369. meerk40t/newly/mock_connection.py +82 -82
  370. meerk40t/newly/newly_params.py +56 -56
  371. meerk40t/newly/plugin.py +1214 -1246
  372. meerk40t/newly/usb_connection.py +322 -322
  373. meerk40t/rotary/gui/gui.py +52 -46
  374. meerk40t/rotary/gui/rotarysettings.py +240 -232
  375. meerk40t/rotary/rotary.py +202 -98
  376. meerk40t/ruida/control.py +291 -91
  377. meerk40t/ruida/controller.py +138 -1088
  378. meerk40t/ruida/device.py +676 -231
  379. meerk40t/ruida/driver.py +534 -472
  380. meerk40t/ruida/emulator.py +1494 -1491
  381. meerk40t/ruida/exceptions.py +4 -4
  382. meerk40t/ruida/gui/gui.py +71 -76
  383. meerk40t/ruida/gui/ruidaconfig.py +239 -72
  384. meerk40t/ruida/gui/ruidacontroller.py +187 -184
  385. meerk40t/ruida/gui/ruidaoperationproperties.py +48 -47
  386. meerk40t/ruida/loader.py +54 -52
  387. meerk40t/ruida/mock_connection.py +57 -109
  388. meerk40t/ruida/plugin.py +124 -87
  389. meerk40t/ruida/rdjob.py +2084 -945
  390. meerk40t/ruida/serial_connection.py +116 -0
  391. meerk40t/ruida/tcp_connection.py +146 -0
  392. meerk40t/ruida/udp_connection.py +73 -0
  393. meerk40t/svgelements.py +9671 -9669
  394. meerk40t/tools/driver_to_path.py +584 -579
  395. meerk40t/tools/geomstr.py +5583 -4680
  396. meerk40t/tools/jhfparser.py +357 -292
  397. meerk40t/tools/kerftest.py +904 -890
  398. meerk40t/tools/livinghinges.py +1168 -1033
  399. meerk40t/tools/pathtools.py +987 -949
  400. meerk40t/tools/pmatrix.py +234 -0
  401. meerk40t/tools/pointfinder.py +942 -942
  402. meerk40t/tools/polybool.py +941 -940
  403. meerk40t/tools/rasterplotter.py +1660 -547
  404. meerk40t/tools/shxparser.py +1047 -901
  405. meerk40t/tools/ttfparser.py +726 -446
  406. meerk40t/tools/zinglplotter.py +595 -593
  407. {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/LICENSE +21 -21
  408. {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/METADATA +150 -139
  409. meerk40t-0.9.7020.dist-info/RECORD +446 -0
  410. {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/WHEEL +1 -1
  411. {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/top_level.txt +0 -1
  412. {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/zip-safe +1 -1
  413. meerk40t/balormk/elementlightjob.py +0 -159
  414. meerk40t-0.9.3001.dist-info/RECORD +0 -437
  415. test/bootstrap.py +0 -63
  416. test/test_cli.py +0 -12
  417. test/test_core_cutcode.py +0 -418
  418. test/test_core_elements.py +0 -144
  419. test/test_core_plotplanner.py +0 -397
  420. test/test_core_viewports.py +0 -312
  421. test/test_drivers_grbl.py +0 -108
  422. test/test_drivers_lihuiyu.py +0 -443
  423. test/test_drivers_newly.py +0 -113
  424. test/test_element_degenerate_points.py +0 -43
  425. test/test_elements_classify.py +0 -97
  426. test/test_elements_penbox.py +0 -22
  427. test/test_file_svg.py +0 -176
  428. test/test_fill.py +0 -155
  429. test/test_geomstr.py +0 -1523
  430. test/test_geomstr_nodes.py +0 -18
  431. test/test_imagetools_actualize.py +0 -306
  432. test/test_imagetools_wizard.py +0 -258
  433. test/test_kernel.py +0 -200
  434. test/test_laser_speeds.py +0 -3303
  435. test/test_length.py +0 -57
  436. test/test_lifecycle.py +0 -66
  437. test/test_operations.py +0 -251
  438. test/test_operations_hatch.py +0 -57
  439. test/test_ruida.py +0 -19
  440. test/test_spooler.py +0 -22
  441. test/test_tools_rasterplotter.py +0 -29
  442. test/test_wobble.py +0 -133
  443. test/test_zingl.py +0 -124
  444. {test → meerk40t/cylinder}/__init__.py +0 -0
  445. /meerk40t/{core/element_commands.py → cylinder/gui/__init__.py} +0 -0
  446. {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/entry_points.txt +0 -0
meerk40t/extra/updater.py CHANGED
@@ -1,453 +1,602 @@
1
- """
2
- The code inside this module provides routines to look for newer versions of meerk40t on GitHub
3
- """
4
- import http.client
5
- import json
6
- from urllib.error import HTTPError, URLError
7
- from urllib.request import Request, urlopen
8
-
9
-
10
- def plugin(kernel, lifecycle):
11
- if lifecycle == "register":
12
- _ = kernel.translation
13
- choices = [
14
- {
15
- "attr": "update_check",
16
- "object": kernel.root,
17
- "default": 1,
18
- "type": int,
19
- "label": _("Action"),
20
- "style": "option",
21
- "display": (
22
- _("No, thank you"),
23
- _("Look for major releases"),
24
- _("Look for major+beta releases"),
25
- ),
26
- "choices": (0, 1, 2),
27
- "tip": _("Check for available updates on startup."),
28
- "page": "Options",
29
- "section": "Check for updates on startup",
30
- },
31
- {
32
- "attr": "update_frequency",
33
- "object": kernel.root,
34
- "default": 1,
35
- "type": int,
36
- "label": _("Frequency"),
37
- "style": "option",
38
- "display": (
39
- _("At every startup"),
40
- _("Once per day"),
41
- _("Once per week"),
42
- ),
43
- "choices": (0, 1, 2),
44
- "tip": _("How often should MeerK40t look for new versions"),
45
- "page": "Options",
46
- "section": "Check for updates on startup",
47
- "conditional": (kernel.root, "update_check", 1, 2),
48
- },
49
- ]
50
- kernel.register_choices("preferences", choices)
51
-
52
- # https://docs.github.com/en/rest/reference/repos#get-the-latest-release
53
- GITHUB_LATEST = "https://api.github.com/repos/meerk40t/meerk40t/releases/latest"
54
- # https://docs.github.com/en/rest/reference/repos#list-releases
55
- GITHUB_RELEASES = (
56
- "https://api.github.com/repos/meerk40t/meerk40t/releases?perpage=100"
57
- )
58
- GITHUB_HEADER = ("Accept", "application/vnd.github.v3+json")
59
-
60
- UPDATE_MESSAGE_HEADER = _("A new {type} release is available:")
61
- UPDATE_MESSAGE_BODY = _(
62
- "Version: {name} v{version} ({label})\n" + "Url: {url}\n" + "Info: {info}"
63
- )
64
- NO_UPDATE_MESSAGE_HEADER = _("You seem to have the latest version.")
65
- NO_UPDATE_MESSAGE_BODY = _(
66
- "Latest version on github: {name} v{version} ({label})\n"
67
- + "Url: {url}\n"
68
- + "Info: {info}"
69
- )
70
- ERROR_MESSAGE = _("Could not find any release information on github")
71
-
72
- context = kernel.root
73
- context.setting(bool, "check_for_betas", False)
74
-
75
- @context.console_option(
76
- "beta", "b", type=bool, action="store_true", help=_("Check for betas")
77
- )
78
- @context.console_option(
79
- "verbosity",
80
- "p",
81
- type=int,
82
- help="Show Info: 0 never, 1 console only, 2 if version found, 3 always",
83
- )
84
- @kernel.console_command(
85
- "check_for_updates",
86
- help=_("Check whether a newer version of Meerk40t is available"),
87
- )
88
- def check_for_updates(channel, _, beta=None, verbosity=None, **kwargs):
89
- """
90
- This command checks for updates and outputs the results to the console.
91
-
92
- If we run a beta
93
- then we get the release list and iterate through
94
- to find the latest full and beta releases that are > currently running
95
-
96
- If we are not currently running a beta
97
- then we check only for a full release > currently running
98
- """
99
-
100
- def comparable_version(version):
101
- """
102
- Return a comparable sequence from a version string
103
- "Major", "Minor", "Release", "Beta"
104
- Beta is derived from Release by default if release > 100 and last two digits != 0
105
- """
106
- src = beta = False
107
- orgversion = version
108
- ending = ""
109
- result = list()
110
- if version is not None:
111
- if version.startswith("v"):
112
- version = version[1:]
113
- if " " in version:
114
- version, ending = version.split(" ", 1)
115
- if ending == "git":
116
- src = True
117
- elif ending == "src":
118
- src = True
119
-
120
- result = list(map(int, version.split(".")))
121
- if len(result) > 3:
122
- result = result[0:2]
123
- while len(result) < 3:
124
- result.append(0)
125
- if result[2] > 100:
126
- subrelease = result[2] % 100
127
- beta = bool(subrelease != 0)
128
- result.append(beta)
129
- result.append(src)
130
- # print (f"Looking at {orgversion}: {result}")
131
- return result
132
-
133
- def extract_from_json(response):
134
- # print (response)
135
- tag = response["tag_name"]
136
- version = comparable_version(tag)
137
- if response["prerelease"]:
138
- version[3] = True
139
- url = response["html_url"]
140
- assets = response["assets"]
141
- label = response["name"]
142
- rel_info = ""
143
- if response["body"]:
144
- infomessages = response["body"].split("\n")
145
- for idx, line in enumerate(infomessages):
146
- if (
147
- "what's changed" in line.lower()
148
- or "full changelog:" in line.lower()
149
- or idx > 6
150
- ):
151
- # Too much information... stop
152
- break
153
- if rel_info != "":
154
- rel_info += "\n"
155
- rel_info += line
156
- rel_info = rel_info.strip()
157
- return tag, version, label, url, assets, rel_info
158
-
159
- def newer_version(candidate_version, reference_version):
160
- """
161
- Checks whether the given candidate_version is newer than
162
- the provided reference_version
163
- Args:
164
- candidate_version: tuple (major, minor, release, is_a_beta, is_source)
165
- reference_version: tuple (major, minor, release, is_a_beta, is_source)
166
- """
167
- is_newer = False
168
- sub_ref = [0, 0, 0]
169
- sub_cand = [0, 0, 0]
170
- # python can compare lists
171
- if candidate_version is not None and isinstance(
172
- candidate_version, (list, tuple)
173
- ):
174
- sub_cand = candidate_version[0:3]
175
- if reference_version is not None and isinstance(
176
- reference_version, (list, tuple)
177
- ):
178
- sub_ref = reference_version[0:3]
179
- # print (sub_cand, sub_ref, bool(sub_cand > sub_ref))
180
- try:
181
- if sub_cand > sub_ref:
182
- is_newer = True
183
- except TypeError:
184
- # Invalid data
185
- is_newer = False
186
- # print (f"Comparing {candidate_version} vs {reference_version}: {is_newer}")
187
- return is_newer
188
-
189
- def update_check(verbosity=None, beta=None):
190
- def update_test(*args):
191
- version_current = comparable_version(kernel.version)
192
- # print (f"Current version: {version_current}")
193
- is_a_beta = version_current[3]
194
- if beta:
195
- url = GITHUB_RELEASES
196
- else:
197
- url = GITHUB_LATEST
198
- if verbosity > 0:
199
- channel(
200
- f"Testing against current {'beta' if is_a_beta else 'full'} version: {kernel.version} (include betas: {'yes' if beta else 'no'})"
201
- )
202
- req = Request(url)
203
- req.add_header(*GITHUB_HEADER)
204
- try:
205
- req = urlopen(req)
206
- response = json.loads(req.read())
207
- except (HTTPError, URLError, http.client.IncompleteRead):
208
- if verbosity > 0:
209
- channel(ERROR_MESSAGE)
210
- return
211
-
212
- tag_full = tag_beta = None
213
- label_full = label_beta = None
214
- version_full = version_beta = version_newest = None
215
- url_full = url_beta = None
216
- assets_full = assets_beta = None
217
- info_full = info_beta = ""
218
- something = False
219
- if beta:
220
- for resp in response:
221
- if resp["draft"]:
222
- continue
223
- (
224
- tag,
225
- version,
226
- label,
227
- url,
228
- assets,
229
- rel_info,
230
- ) = extract_from_json(resp)
231
- # What is the newest beta
232
- if resp["prerelease"]:
233
- if newer_version(version, version_beta):
234
- (
235
- tag_beta,
236
- version_beta,
237
- label_beta,
238
- url_beta,
239
- assets_beta,
240
- info_beta,
241
- ) = (
242
- tag,
243
- version,
244
- label,
245
- url,
246
- assets,
247
- rel_info,
248
- )
249
- # What is the newest release
250
- elif newer_version(version, version_full):
251
- (
252
- tag_full,
253
- version_full,
254
- label_full,
255
- url_full,
256
- assets_full,
257
- info_full,
258
- ) = (
259
- tag,
260
- version,
261
- label,
262
- url,
263
- assets,
264
- rel_info,
265
- )
266
- # If full version is latest, disregard betas
267
- if newer_version(version_full, version_beta):
268
- (
269
- tag_beta,
270
- version_beta,
271
- label_beta,
272
- url_beta,
273
- assets_beta,
274
- info_beta,
275
- ) = (
276
- None,
277
- None,
278
- None,
279
- None,
280
- None,
281
- "",
282
- )
283
- else:
284
- resp = response
285
- (
286
- tag_full,
287
- version_full,
288
- label_full,
289
- url_full,
290
- assets_full,
291
- info_full,
292
- ) = extract_from_json(resp)
293
- # print (f"Newest release: {version_full}, newest beta: {version_beta}, current: {version_current}")
294
- version_newest = version_full
295
- tag_newest = tag_full
296
- url_newest = url_full
297
- label_newest = label_full
298
- type_newest = ""
299
- info_newest = info_full
300
- if newer_version(version_beta, version_full):
301
- version_newest = version_beta
302
- tag_newest = tag_beta
303
- label_newest = label_beta
304
- url_newest = url_beta
305
- type_newest = " (beta)"
306
- info_newest = info_beta
307
- # print ("Beta is newer than full")
308
- newest_message_header = ""
309
- newest_message_body = ""
310
- if newer_version(version_full, version_current):
311
- something = True
312
- message_header = UPDATE_MESSAGE_HEADER.format(
313
- type="full",
314
- )
315
- message_body = UPDATE_MESSAGE_BODY.format(
316
- name=kernel.name,
317
- version=tag_full,
318
- label=label_full,
319
- url=url_full,
320
- info=info_full,
321
- )
322
- if verbosity > 0:
323
- channel(message_header + "\n" + message_body)
324
- newest_message_header = message_header
325
- newest_message_body = message_body
326
-
327
- if newer_version(version_beta, version_current):
328
- something = True
329
- message_header = UPDATE_MESSAGE_HEADER.format(type="beta")
330
- message_body = UPDATE_MESSAGE_BODY.format(
331
- name=kernel.name,
332
- version=tag_beta,
333
- label=label_beta,
334
- url=url_beta,
335
- info=info_beta,
336
- )
337
- if verbosity > 0:
338
- channel(message_header + "\n" + message_body)
339
- newest_message_header = message_header
340
- newest_message_body = message_body
341
- has_wx = False
342
- try:
343
- import wx
344
-
345
- from meerk40t.gui.choicepropertypanel import ChoicePropertyPanel
346
- from meerk40t.gui.wxutils import dip_size
347
-
348
- has_wx = True
349
- except ImportError:
350
- pass
351
- action = False
352
-
353
- def get_response(header, content, footer):
354
- if has_wx:
355
- # Very simple panel
356
- dlg = wx.Dialog(
357
- None,
358
- wx.ID_ANY,
359
- title=_("Update-Info"),
360
- size=wx.DefaultSize,
361
- pos=wx.DefaultPosition,
362
- style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
363
- )
364
- # contents
365
- sizer = wx.BoxSizer(wx.VERTICAL)
366
-
367
- label = wx.StaticText(dlg, wx.ID_ANY, header)
368
- sizer.Add(label, 0, wx.EXPAND, 0)
369
- info = wx.TextCtrl(
370
- dlg, wx.ID_ANY, style=wx.TE_READONLY | wx.TE_MULTILINE
371
- )
372
- info.SetValue(content)
373
- sizer.Add(info, 1, wx.EXPAND, 0)
374
- label = wx.StaticText(dlg, wx.ID_ANY, footer)
375
- sizer.Add(label, 0, wx.EXPAND, 0)
376
- btnsizer = wx.StdDialogButtonSizer()
377
- btn = wx.Button(dlg, wx.ID_OK)
378
- btn.SetDefault()
379
- btnsizer.AddButton(btn)
380
- btn = wx.Button(dlg, wx.ID_CANCEL)
381
- btnsizer.AddButton(btn)
382
- btnsizer.Realize()
383
- sizer.Add(btnsizer, 0, wx.EXPAND, 0)
384
- panel = ChoicePropertyPanel(
385
- dlg, wx.ID_ANY, context=context, choices=choices
386
- )
387
- sizer.Add(panel, 1, wx.EXPAND, 0)
388
- dlg.SetSizer(sizer)
389
- sizer.Fit(dlg)
390
- dlg.SetSize(dip_size(dlg, 620, 400))
391
- dlg.CenterOnScreen()
392
- answer = dlg.ShowModal()
393
- dlg.Destroy()
394
- response = bool(answer in (wx.YES, wx.ID_YES, wx.ID_OK))
395
- else:
396
- question = header + "\n" + content + "\n" + footer
397
- response = kernel.yesno(question)
398
- return response
399
-
400
- if something:
401
- # if we have a hit then we brag about it
402
- #
403
- if verbosity > 1:
404
- action = get_response(
405
- newest_message_header,
406
- newest_message_body,
407
- _("Do you want to go the download page?"),
408
- )
409
- else:
410
- if version_newest is not None:
411
- message_header = NO_UPDATE_MESSAGE_HEADER
412
- message_body = NO_UPDATE_MESSAGE_BODY.format(
413
- name=kernel.name,
414
- version=tag_newest,
415
- type=type_newest,
416
- label=label_newest,
417
- url=url_newest,
418
- info=info_newest,
419
- )
420
- if verbosity > 2:
421
- channel(message_header + "\n" + message_body)
422
- action = get_response(
423
- message_header,
424
- message_body,
425
- _("Do you want to look for yourself?"),
426
- )
427
- elif verbosity > 0:
428
- channel(message_header + "\n" + message_body)
429
- else:
430
- if verbosity > 0:
431
- channel(ERROR_MESSAGE)
432
- # Yes, please open a webpage
433
- if action:
434
- import webbrowser
435
-
436
- webbrowser.open(url_newest, new=0, autoraise=True)
437
-
438
- if beta is None:
439
- beta = False
440
- if verbosity is None:
441
- verbosity = 1
442
- return update_test
443
-
444
- from meerk40t.kernel.kernel import Job
445
-
446
- _job = Job(
447
- process=update_check(verbosity, beta),
448
- job_name="update_check_job",
449
- interval=0.01,
450
- times=1,
451
- run_main=True,
452
- )
453
- context.schedule(_job)
1
+ """
2
+ The code inside this module provides routines to look for newer versions of meerk40t on GitHub
3
+ """
4
+ import http.client
5
+ import json
6
+ import platform
7
+ from urllib.error import HTTPError, URLError
8
+ from urllib.request import Request, urlopen
9
+
10
+
11
+ def plugin(kernel, lifecycle):
12
+ if lifecycle == "register":
13
+ _ = kernel.translation
14
+ choices = [
15
+ {
16
+ "attr": "update_check",
17
+ "object": kernel.root,
18
+ "default": 1,
19
+ "type": int,
20
+ "label": _("Action"),
21
+ "style": "option",
22
+ "display": (
23
+ _("No, thank you"),
24
+ _("Look for major releases"),
25
+ _("Look for major+beta releases"),
26
+ ),
27
+ "choices": (0, 1, 2),
28
+ "tip": _("Check for available updates on startup."),
29
+ "page": "Options",
30
+ "section": "Check for updates on startup",
31
+ },
32
+ {
33
+ "attr": "update_frequency",
34
+ "object": kernel.root,
35
+ "default": 1,
36
+ "type": int,
37
+ "label": _("Frequency"),
38
+ "style": "option",
39
+ "display": (
40
+ _("At every startup"),
41
+ _("Once per day"),
42
+ _("Once per week"),
43
+ ),
44
+ "choices": (0, 1, 2),
45
+ "tip": _("How often should MeerK40t look for new versions"),
46
+ "page": "Options",
47
+ "section": "Check for updates on startup",
48
+ "conditional": (kernel.root, "update_check", 1, 2),
49
+ },
50
+ ]
51
+ kernel.register_choices("preferences", choices)
52
+
53
+ # https://docs.github.com/en/rest/reference/repos#get-the-latest-release
54
+ GITHUB_LATEST = "https://api.github.com/repos/meerk40t/meerk40t/releases/latest"
55
+ # https://docs.github.com/en/rest/reference/repos#list-releases
56
+ GITHUB_RELEASES = (
57
+ "https://api.github.com/repos/meerk40t/meerk40t/releases?perpage=100"
58
+ )
59
+ GITHUB_HEADER = ("Accept", "application/vnd.github.v3+json")
60
+
61
+ UPDATE_MESSAGE_HEADER = _("A new {type} release is available ({system}):")
62
+ UPDATE_MESSAGE_BODY = _(
63
+ "Version: {name} v{version} ({label})\n" + "Url: {url}\n" + "Info: {info}"
64
+ )
65
+ NO_UPDATE_MESSAGE_HEADER = _("You seem to have the latest {system} version.")
66
+ NO_UPDATE_MESSAGE_BODY = _(
67
+ "Latest version on github: {name} v{version} ({label})\n"
68
+ + "Url: {url}\n"
69
+ + "Info: {info}"
70
+ )
71
+ ERROR_MESSAGE = _("Could not find any release information on github")
72
+
73
+ context = kernel.root
74
+ context.setting(bool, "check_for_betas", False)
75
+
76
+ @context.console_option(
77
+ "beta", "b", type=bool, action="store_true", help=_("Check for betas")
78
+ )
79
+ @context.console_option(
80
+ "verbosity",
81
+ "v",
82
+ type=int,
83
+ help="Show Info: 0 never, 1 console only, 2 if version found, 3 always",
84
+ )
85
+ @context.console_option(
86
+ "sysdefault",
87
+ "s",
88
+ type=int,
89
+ help=_("System: 0=Auto, 1=Source, 2=Windows, 3=Linux, 4=MacOSX, 5=RPI"),
90
+ )
91
+ @context.console_option(
92
+ "force",
93
+ "f",
94
+ type=bool,
95
+ action="store_true",
96
+ help=_("Force a found message"),
97
+ )
98
+ @kernel.console_command(
99
+ "check_for_updates",
100
+ help=_("Check whether a newer version of Meerk40t is available"),
101
+ )
102
+ def check_for_updates(
103
+ channel, _, beta=None, verbosity=None, sysdefault=None, force=None, **kwargs
104
+ ):
105
+ """
106
+ This command checks for updates and outputs the results to the console.
107
+
108
+ If we run a beta
109
+ then we get the release list and iterate through
110
+ to find the latest full and beta releases that are > currently running
111
+
112
+ If we are not currently running a beta
113
+ then we check only for a full release > currently running
114
+ """
115
+
116
+ def comparable_version(version):
117
+ """
118
+ Return a comparable sequence from a version string
119
+ "Major", "Minor", "Release", "Beta"
120
+ Beta is derived from Release by default if release > 100 and last two digits != 0
121
+ """
122
+ src = beta = False
123
+ ending = ""
124
+ result = list()
125
+ if version is not None:
126
+ if version.startswith("v"):
127
+ version = version[1:]
128
+ if " " in version:
129
+ version, ending = version.split(" ", 1)
130
+ if "git" in ending:
131
+ src = True
132
+ elif "src" in ending:
133
+ src = True
134
+
135
+ result = list(map(int, version.split(".")))
136
+ if len(result) > 3:
137
+ result = result[0:2]
138
+ while len(result) < 3:
139
+ result.append(0)
140
+ if result[2] > 100:
141
+ subrelease = result[2] % 100
142
+ beta = bool(subrelease != 0)
143
+ result.append(beta)
144
+ result.append(src)
145
+ # print (f"Looking at {orgversion}: {result}")
146
+ return result
147
+
148
+ def extract_from_json(response):
149
+ # print (response)
150
+ tag = response["tag_name"]
151
+ version = comparable_version(tag)
152
+ if response["prerelease"]:
153
+ version[3] = True
154
+ url = response["html_url"]
155
+ assets = response["assets"]
156
+ label = response["name"]
157
+ rel_info = ""
158
+ if response["body"]:
159
+ infomessages = response["body"].split("\n")
160
+ for idx, line in enumerate(infomessages):
161
+ if (
162
+ "what's changed" in line.lower()
163
+ or "full changelog:" in line.lower()
164
+ or idx > 6
165
+ ):
166
+ # Too much information... stop
167
+ break
168
+ if rel_info != "":
169
+ rel_info += "\n"
170
+ rel_info += line
171
+ rel_info = rel_info.strip()
172
+ return tag, version, label, url, assets, rel_info
173
+
174
+ def newer_version(
175
+ candidate_version, reference_version, candidate_assets, asset_need
176
+ ):
177
+ """
178
+ Checks whether the given candidate_version is newer than
179
+ the provided reference_version
180
+ Args:
181
+ candidate_version: tuple (major, minor, release, is_a_beta, is_source)
182
+ reference_version: tuple (major, minor, release, is_a_beta, is_source)
183
+ candidate_assets: list of asset-dictionary
184
+ asset_need: list of names that would be needed in candidate_assets
185
+ """
186
+ is_newer = False
187
+ sub_ref = [0, 0, 0]
188
+ sub_cand = [0, 0, 0]
189
+ # python can compare lists
190
+ if candidate_version is not None and isinstance(
191
+ candidate_version, (list, tuple)
192
+ ):
193
+ sub_cand = list(candidate_version[0:3])
194
+ if reference_version is not None and isinstance(
195
+ reference_version, (list, tuple)
196
+ ):
197
+ sub_ref = list(reference_version[0:3])
198
+
199
+ if candidate_assets is not None and asset_need is not None:
200
+ # Do we have something to look for, if yes then we only
201
+ # compare if we have a matching entry
202
+ valid = False
203
+ for asset in candidate_assets:
204
+ # print (f"[{sub_cand[0]}.{sub_cand[1]}.{sub_cand[2]}] {asset['name']}: {asset['browser_download_url']}")
205
+ cname = asset["name"].lower()
206
+ if cname in asset_need:
207
+ valid = True
208
+ break
209
+
210
+ if not valid:
211
+ return False
212
+
213
+ try:
214
+ if sub_cand > sub_ref:
215
+ is_newer = True
216
+ except TypeError:
217
+ # Invalid data
218
+ is_newer = False
219
+ # print (f"Comparing {candidate_version} vs {reference_version}: {is_newer}")
220
+ return is_newer
221
+
222
+ def update_check(
223
+ verbosity_level, look_for_betas, force_feedback, system_to_use
224
+ ):
225
+ if look_for_betas is None:
226
+ look_for_betas = False
227
+ if verbosity_level is None:
228
+ verbosity_level = 1
229
+ if force_feedback is None:
230
+ force_feedback = False
231
+ if system_to_use is None:
232
+ system_to_use = 0
233
+ default_system = system_to_use
234
+
235
+ def update_test(*args):
236
+ version_current = comparable_version(kernel.version)
237
+ # print (f"Current version: {version_current}")
238
+ # Are we running a compiled version?
239
+ # Then we restrict the search just those versions where
240
+ # we have a corresponding asset
241
+ if force_feedback:
242
+ version_current = (0, 0, 0, 0)
243
+ is_a_beta = version_current[3]
244
+ is_source = version_current[4]
245
+ default_system = system_to_use
246
+ if default_system == 0:
247
+ # Let's see...
248
+ os_system = platform.system()
249
+ os_machine = platform.machine()
250
+ if is_source:
251
+ default_system = 1
252
+ else:
253
+ # 2 = Windows, 3 = Linux, 4 = MacOSX, 5 = RPI
254
+ if os_system == "Windows":
255
+ default_system = 2
256
+ elif os_system == "Linux":
257
+ if os_machine in ("armv7l", "aarch64"):
258
+ # Arm processor of a rpi
259
+ default_system = 5
260
+ else:
261
+ default_system = 3
262
+ elif os_system == "Darwin":
263
+ default_system = 4
264
+
265
+ if default_system == 2:
266
+ # Windows:
267
+ asset_requirement = (
268
+ "meerk40t.exe",
269
+ "wx-meerk40t.exe",
270
+ )
271
+ system_type = "Windows"
272
+ is_source = False
273
+ elif default_system == 3:
274
+ # Linux:
275
+ asset_requirement = ("meerk40t-Linux",)
276
+ system_type = "Linux"
277
+ is_source = False
278
+ elif default_system == 4:
279
+ # Darwin:
280
+ asset_requirement = (
281
+ "meerk40t.dmg",
282
+ "meerk40t-m1.dmg",
283
+ "MeerK40t_PyInst_11.dmg",
284
+ "MeerK40t_unsigned.dmg",
285
+ )
286
+ system_type = "Mac-OSX"
287
+ is_source = False
288
+ elif default_system == 5:
289
+ # Raspberry-Pi:
290
+ asset_requirement = (
291
+ "meerk40t_pi.tar",
292
+ "meerk40t_pi64.tar",
293
+ "meerk40t_pi_slow.tar",
294
+ )
295
+ system_type = "Raspberry Pi"
296
+ is_source = False
297
+ else:
298
+ # Source
299
+ asset_requirement = None
300
+ system_type = "Source"
301
+ is_source = True
302
+ if asset_requirement is not None:
303
+ asset_requirement = list(c.lower() for c in asset_requirement)
304
+ # Now that we look at the requirement to have a corresponding asset available
305
+ # we need to look at all releases
306
+ # if beta:
307
+ # url = GITHUB_RELEASES
308
+ # else:
309
+ # url = GITHUB_LATEST
310
+ url = GITHUB_RELEASES
311
+ if verbosity_level > 0:
312
+ channel(
313
+ f"Testing against current {'beta' if is_a_beta else 'full'} version: {kernel.version}"
314
+ )
315
+ channel(
316
+ f"(include betas: {'yes' if look_for_betas else 'no'}, run from source: {'yes' if is_source else 'no'})"
317
+ )
318
+ req = Request(url)
319
+ req.add_header(*GITHUB_HEADER)
320
+ try:
321
+ req = urlopen(req)
322
+ response = json.loads(req.read())
323
+ except Exception as e:
324
+ if verbosity_level > 0:
325
+ channel(ERROR_MESSAGE + f"\n{e}")
326
+ return
327
+
328
+ tag_full = tag_beta = None
329
+ label_full = label_beta = None
330
+ version_full = version_beta = version_newest = None
331
+ url_full = url_beta = None
332
+ assets_full = assets_beta = None
333
+ info_full = info_beta = ""
334
+ something = False
335
+
336
+ if look_for_betas:
337
+ for resp in response:
338
+ if resp["draft"]:
339
+ continue
340
+ (
341
+ tag,
342
+ version,
343
+ label,
344
+ url,
345
+ assets,
346
+ rel_info,
347
+ ) = extract_from_json(resp)
348
+ # What is the newest beta
349
+ if resp["prerelease"]:
350
+ if newer_version(
351
+ version, version_beta, assets, asset_requirement
352
+ ):
353
+ (
354
+ tag_beta,
355
+ version_beta,
356
+ label_beta,
357
+ url_beta,
358
+ assets_beta,
359
+ info_beta,
360
+ ) = (
361
+ tag,
362
+ version,
363
+ label,
364
+ url,
365
+ assets,
366
+ rel_info,
367
+ )
368
+ # What is the newest release
369
+ elif newer_version(
370
+ version, version_full, assets, asset_requirement
371
+ ):
372
+ (
373
+ tag_full,
374
+ version_full,
375
+ label_full,
376
+ url_full,
377
+ assets_full,
378
+ info_full,
379
+ ) = (
380
+ tag,
381
+ version,
382
+ label,
383
+ url,
384
+ assets,
385
+ rel_info,
386
+ )
387
+ # If full version is latest, disregard betas
388
+ if newer_version(version_full, version_beta, None, None):
389
+ (
390
+ tag_beta,
391
+ version_beta,
392
+ label_beta,
393
+ url_beta,
394
+ assets_beta,
395
+ info_beta,
396
+ ) = (
397
+ None,
398
+ None,
399
+ None,
400
+ None,
401
+ None,
402
+ "",
403
+ )
404
+ else:
405
+ for resp in response:
406
+ if resp["draft"]:
407
+ continue
408
+ if resp["prerelease"]:
409
+ continue
410
+ (
411
+ tag,
412
+ version,
413
+ label,
414
+ url,
415
+ assets,
416
+ rel_info,
417
+ ) = extract_from_json(resp)
418
+ if newer_version(
419
+ version, version_full, assets, asset_requirement
420
+ ):
421
+ (
422
+ tag_full,
423
+ version_full,
424
+ label_full,
425
+ url_full,
426
+ assets_full,
427
+ info_full,
428
+ ) = (
429
+ tag,
430
+ version,
431
+ label,
432
+ url,
433
+ assets,
434
+ rel_info,
435
+ )
436
+ # print (f"Newest release: {version_full}, newest beta: {version_beta}, current: {version_current}")
437
+ version_newest = version_full
438
+ tag_newest = tag_full
439
+ url_newest = url_full
440
+ label_newest = label_full
441
+ type_newest = ""
442
+ info_newest = info_full
443
+ if newer_version(version_beta, version_full, None, None):
444
+ version_newest = version_beta
445
+ tag_newest = tag_beta
446
+ label_newest = label_beta
447
+ url_newest = url_beta
448
+ type_newest = " (beta)"
449
+ info_newest = info_beta
450
+ # print ("Beta is newer than full")
451
+ newest_message_header = ""
452
+ newest_message_body = ""
453
+ if newer_version(version_full, version_current, None, None):
454
+ something = True
455
+ message_header = UPDATE_MESSAGE_HEADER.format(
456
+ type="full",
457
+ system=system_type,
458
+ )
459
+ message_body = UPDATE_MESSAGE_BODY.format(
460
+ name=kernel.name,
461
+ version=tag_full,
462
+ label=label_full,
463
+ url=url_full,
464
+ info=info_full,
465
+ )
466
+ if verbosity_level > 0:
467
+ channel(message_header + "\n" + message_body)
468
+ newest_message_header = message_header
469
+ newest_message_body = message_body
470
+
471
+ if newer_version(version_beta, version_current, None, None):
472
+ something = True
473
+ message_header = UPDATE_MESSAGE_HEADER.format(
474
+ type="beta", system=system_type
475
+ )
476
+ message_body = UPDATE_MESSAGE_BODY.format(
477
+ name=kernel.name,
478
+ version=tag_beta,
479
+ label=label_beta,
480
+ url=url_beta,
481
+ info=info_beta,
482
+ )
483
+ if verbosity_level > 0:
484
+ channel(message_header + "\n" + message_body)
485
+ newest_message_header = message_header
486
+ newest_message_body = message_body
487
+ # print (f"Something: {something}, verbosity={verbosity}")
488
+ has_wx = False
489
+ try:
490
+ import wx
491
+
492
+ from meerk40t.gui.choicepropertypanel import ChoicePropertyPanel
493
+ from meerk40t.gui.wxutils import dip_size, wxButton, wxStaticText, TextCtrl
494
+
495
+ has_wx = True
496
+ except ImportError:
497
+ pass
498
+ action = False
499
+
500
+ def get_response(header, content, footer):
501
+ if has_wx:
502
+ # Very simple panel
503
+ dlg = wx.Dialog(
504
+ None,
505
+ wx.ID_ANY,
506
+ title=_("Update-Info"),
507
+ size=wx.DefaultSize,
508
+ pos=wx.DefaultPosition,
509
+ style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
510
+ )
511
+ # contents
512
+ kernel.themes.set_window_colors(dlg)
513
+
514
+ sizer = wx.BoxSizer(wx.VERTICAL)
515
+
516
+ label = wxStaticText(dlg, wx.ID_ANY, header)
517
+ sizer.Add(label, 0, wx.EXPAND, 0)
518
+ info = TextCtrl(
519
+ dlg, wx.ID_ANY, style=wx.TE_READONLY | wx.TE_MULTILINE
520
+ )
521
+ info.SetValue(content)
522
+ sizer.Add(info, 1, wx.EXPAND, 0)
523
+ label = wxStaticText(dlg, wx.ID_ANY, footer)
524
+ sizer.Add(label, 0, wx.EXPAND, 0)
525
+ btnsizer = wx.StdDialogButtonSizer()
526
+ btn = wxButton(dlg, wx.ID_OK)
527
+ btn.SetDefault()
528
+ btnsizer.AddButton(btn)
529
+ btn = wxButton(dlg, wx.ID_CANCEL)
530
+ btnsizer.AddButton(btn)
531
+ btnsizer.Realize()
532
+ sizer.Add(btnsizer, 0, wx.EXPAND, 0)
533
+ panel = ChoicePropertyPanel(
534
+ dlg, wx.ID_ANY, context=context, choices=choices
535
+ )
536
+ sizer.Add(panel, 1, wx.EXPAND, 0)
537
+ dlg.SetSizer(sizer)
538
+ sizer.Fit(dlg)
539
+ dlg.SetSize(dip_size(dlg, 620, 400))
540
+ dlg.CenterOnScreen()
541
+ answer = dlg.ShowModal()
542
+ # Unlisten
543
+ panel.module_close()
544
+ dlg.Destroy()
545
+ response = bool(answer in (wx.YES, wx.ID_YES, wx.ID_OK))
546
+ else:
547
+ question = header + "\n" + content + "\n" + footer
548
+ response = kernel.yesno(question)
549
+ return response
550
+
551
+ if something:
552
+ # if we have a hit then we brag about it
553
+ #
554
+ if verbosity_level > 1:
555
+ action = get_response(
556
+ newest_message_header,
557
+ newest_message_body,
558
+ _("Do you want to go the download page?"),
559
+ )
560
+ else:
561
+ if version_newest is not None:
562
+ message_header = NO_UPDATE_MESSAGE_HEADER.format(
563
+ system=system_type
564
+ )
565
+ message_body = NO_UPDATE_MESSAGE_BODY.format(
566
+ name=kernel.name,
567
+ version=tag_newest,
568
+ type=type_newest,
569
+ label=label_newest,
570
+ url=url_newest,
571
+ info=info_newest,
572
+ )
573
+ if verbosity_level > 2:
574
+ channel(message_header + "\n" + message_body)
575
+ action = get_response(
576
+ message_header,
577
+ message_body,
578
+ _("Do you want to look for yourself?"),
579
+ )
580
+ elif verbosity_level > 0:
581
+ channel(message_header + "\n" + message_body)
582
+ else:
583
+ if verbosity_level > 0:
584
+ channel(ERROR_MESSAGE)
585
+ # Yes, please open a webpage
586
+ if action:
587
+ import webbrowser
588
+
589
+ webbrowser.open(url_newest, new=0, autoraise=True)
590
+
591
+ return update_test
592
+
593
+ from meerk40t.kernel.kernel import Job
594
+
595
+ _job = Job(
596
+ process=update_check(verbosity, beta, force, sysdefault),
597
+ job_name="update_check_job",
598
+ interval=0.01,
599
+ times=1,
600
+ run_main=True,
601
+ )
602
+ context.schedule(_job)