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.
- meerk40t/__init__.py +1 -1
- meerk40t/balormk/balor_params.py +167 -167
- meerk40t/balormk/clone_loader.py +457 -457
- meerk40t/balormk/controller.py +1566 -1512
- meerk40t/balormk/cylindermod.py +64 -0
- meerk40t/balormk/device.py +966 -1959
- meerk40t/balormk/driver.py +778 -591
- meerk40t/balormk/galvo_commands.py +1194 -0
- meerk40t/balormk/gui/balorconfig.py +237 -111
- meerk40t/balormk/gui/balorcontroller.py +191 -184
- meerk40t/balormk/gui/baloroperationproperties.py +116 -115
- meerk40t/balormk/gui/corscene.py +845 -0
- meerk40t/balormk/gui/gui.py +179 -147
- meerk40t/balormk/livelightjob.py +466 -382
- meerk40t/balormk/mock_connection.py +131 -109
- meerk40t/balormk/plugin.py +133 -135
- meerk40t/balormk/usb_connection.py +306 -301
- meerk40t/camera/__init__.py +1 -1
- meerk40t/camera/camera.py +514 -397
- meerk40t/camera/gui/camerapanel.py +1241 -1095
- meerk40t/camera/gui/gui.py +58 -58
- meerk40t/camera/plugin.py +441 -399
- meerk40t/ch341/__init__.py +27 -27
- meerk40t/ch341/ch341device.py +628 -628
- meerk40t/ch341/libusb.py +595 -589
- meerk40t/ch341/mock.py +171 -171
- meerk40t/ch341/windriver.py +157 -157
- meerk40t/constants.py +13 -0
- meerk40t/core/__init__.py +1 -1
- meerk40t/core/bindalias.py +550 -539
- meerk40t/core/core.py +47 -47
- meerk40t/core/cutcode/cubiccut.py +73 -73
- meerk40t/core/cutcode/cutcode.py +315 -312
- meerk40t/core/cutcode/cutgroup.py +141 -137
- meerk40t/core/cutcode/cutobject.py +192 -185
- meerk40t/core/cutcode/dwellcut.py +37 -37
- meerk40t/core/cutcode/gotocut.py +29 -29
- meerk40t/core/cutcode/homecut.py +29 -29
- meerk40t/core/cutcode/inputcut.py +34 -34
- meerk40t/core/cutcode/linecut.py +33 -33
- meerk40t/core/cutcode/outputcut.py +34 -34
- meerk40t/core/cutcode/plotcut.py +335 -335
- meerk40t/core/cutcode/quadcut.py +61 -61
- meerk40t/core/cutcode/rastercut.py +168 -148
- meerk40t/core/cutcode/waitcut.py +34 -34
- meerk40t/core/cutplan.py +1843 -1316
- meerk40t/core/drivers.py +330 -329
- meerk40t/core/elements/align.py +801 -669
- meerk40t/core/elements/branches.py +1858 -1507
- meerk40t/core/elements/clipboard.py +229 -219
- meerk40t/core/elements/element_treeops.py +4595 -2837
- meerk40t/core/elements/element_types.py +125 -105
- meerk40t/core/elements/elements.py +4315 -3617
- meerk40t/core/elements/files.py +117 -64
- meerk40t/core/elements/geometry.py +473 -224
- meerk40t/core/elements/grid.py +467 -316
- meerk40t/core/elements/materials.py +158 -94
- meerk40t/core/elements/notes.py +50 -38
- meerk40t/core/elements/offset_clpr.py +934 -912
- meerk40t/core/elements/offset_mk.py +963 -955
- meerk40t/core/elements/penbox.py +339 -267
- meerk40t/core/elements/placements.py +300 -83
- meerk40t/core/elements/render.py +785 -687
- meerk40t/core/elements/shapes.py +2618 -2092
- meerk40t/core/elements/testcases.py +105 -0
- meerk40t/core/elements/trace.py +651 -563
- meerk40t/core/elements/tree_commands.py +415 -409
- meerk40t/core/elements/undo_redo.py +116 -58
- meerk40t/core/elements/wordlist.py +319 -200
- meerk40t/core/exceptions.py +9 -9
- meerk40t/core/laserjob.py +220 -220
- meerk40t/core/logging.py +63 -63
- meerk40t/core/node/blobnode.py +83 -86
- meerk40t/core/node/bootstrap.py +105 -103
- meerk40t/core/node/branch_elems.py +40 -31
- meerk40t/core/node/branch_ops.py +45 -38
- meerk40t/core/node/branch_regmark.py +48 -41
- meerk40t/core/node/cutnode.py +29 -32
- meerk40t/core/node/effect_hatch.py +375 -257
- meerk40t/core/node/effect_warp.py +398 -0
- meerk40t/core/node/effect_wobble.py +441 -309
- meerk40t/core/node/elem_ellipse.py +404 -309
- meerk40t/core/node/elem_image.py +1082 -801
- meerk40t/core/node/elem_line.py +358 -292
- meerk40t/core/node/elem_path.py +259 -201
- meerk40t/core/node/elem_point.py +129 -102
- meerk40t/core/node/elem_polyline.py +310 -246
- meerk40t/core/node/elem_rect.py +376 -286
- meerk40t/core/node/elem_text.py +445 -418
- meerk40t/core/node/filenode.py +59 -40
- meerk40t/core/node/groupnode.py +138 -74
- meerk40t/core/node/image_processed.py +777 -766
- meerk40t/core/node/image_raster.py +156 -113
- meerk40t/core/node/layernode.py +31 -31
- meerk40t/core/node/mixins.py +135 -107
- meerk40t/core/node/node.py +1427 -1304
- meerk40t/core/node/nutils.py +117 -114
- meerk40t/core/node/op_cut.py +463 -335
- meerk40t/core/node/op_dots.py +296 -251
- meerk40t/core/node/op_engrave.py +414 -311
- meerk40t/core/node/op_image.py +755 -369
- meerk40t/core/node/op_raster.py +787 -522
- meerk40t/core/node/place_current.py +37 -40
- meerk40t/core/node/place_point.py +329 -126
- meerk40t/core/node/refnode.py +58 -47
- meerk40t/core/node/rootnode.py +225 -219
- meerk40t/core/node/util_console.py +48 -48
- meerk40t/core/node/util_goto.py +84 -65
- meerk40t/core/node/util_home.py +61 -61
- meerk40t/core/node/util_input.py +102 -102
- meerk40t/core/node/util_output.py +102 -102
- meerk40t/core/node/util_wait.py +65 -65
- meerk40t/core/parameters.py +709 -707
- meerk40t/core/planner.py +875 -785
- meerk40t/core/plotplanner.py +656 -652
- meerk40t/core/space.py +120 -113
- meerk40t/core/spoolers.py +706 -705
- meerk40t/core/svg_io.py +1836 -1549
- meerk40t/core/treeop.py +534 -445
- meerk40t/core/undos.py +278 -124
- meerk40t/core/units.py +784 -680
- meerk40t/core/view.py +393 -322
- meerk40t/core/webhelp.py +62 -62
- meerk40t/core/wordlist.py +513 -504
- meerk40t/cylinder/cylinder.py +247 -0
- meerk40t/cylinder/gui/cylindersettings.py +41 -0
- meerk40t/cylinder/gui/gui.py +24 -0
- meerk40t/device/__init__.py +1 -1
- meerk40t/device/basedevice.py +322 -123
- meerk40t/device/devicechoices.py +50 -0
- meerk40t/device/dummydevice.py +163 -128
- meerk40t/device/gui/defaultactions.py +618 -602
- meerk40t/device/gui/effectspanel.py +114 -0
- meerk40t/device/gui/formatterpanel.py +253 -290
- meerk40t/device/gui/warningpanel.py +337 -260
- meerk40t/device/mixins.py +13 -13
- meerk40t/dxf/__init__.py +1 -1
- meerk40t/dxf/dxf_io.py +766 -554
- meerk40t/dxf/plugin.py +47 -35
- meerk40t/external_plugins.py +79 -79
- meerk40t/external_plugins_build.py +28 -28
- meerk40t/extra/cag.py +112 -116
- meerk40t/extra/coolant.py +403 -0
- meerk40t/extra/encode_detect.py +204 -0
- meerk40t/extra/ezd.py +1165 -1165
- meerk40t/extra/hershey.py +834 -340
- meerk40t/extra/imageactions.py +322 -316
- meerk40t/extra/inkscape.py +628 -622
- meerk40t/extra/lbrn.py +424 -424
- meerk40t/extra/outerworld.py +283 -0
- meerk40t/extra/param_functions.py +1542 -1556
- meerk40t/extra/potrace.py +257 -253
- meerk40t/extra/serial_exchange.py +118 -0
- meerk40t/extra/updater.py +602 -453
- meerk40t/extra/vectrace.py +147 -146
- meerk40t/extra/winsleep.py +83 -83
- meerk40t/extra/xcs_reader.py +597 -0
- meerk40t/fill/fills.py +781 -335
- meerk40t/fill/patternfill.py +1061 -1061
- meerk40t/fill/patterns.py +614 -567
- meerk40t/grbl/control.py +87 -87
- meerk40t/grbl/controller.py +990 -903
- meerk40t/grbl/device.py +1084 -768
- meerk40t/grbl/driver.py +989 -771
- meerk40t/grbl/emulator.py +532 -497
- meerk40t/grbl/gcodejob.py +783 -767
- meerk40t/grbl/gui/grblconfiguration.py +373 -298
- meerk40t/grbl/gui/grblcontroller.py +485 -271
- meerk40t/grbl/gui/grblhardwareconfig.py +269 -153
- meerk40t/grbl/gui/grbloperationconfig.py +105 -0
- meerk40t/grbl/gui/gui.py +147 -116
- meerk40t/grbl/interpreter.py +44 -44
- meerk40t/grbl/loader.py +22 -22
- meerk40t/grbl/mock_connection.py +56 -56
- meerk40t/grbl/plugin.py +294 -264
- meerk40t/grbl/serial_connection.py +93 -88
- meerk40t/grbl/tcp_connection.py +81 -79
- meerk40t/grbl/ws_connection.py +112 -0
- meerk40t/gui/__init__.py +1 -1
- meerk40t/gui/about.py +2042 -296
- meerk40t/gui/alignment.py +1644 -1608
- meerk40t/gui/autoexec.py +199 -0
- meerk40t/gui/basicops.py +791 -670
- meerk40t/gui/bufferview.py +77 -71
- meerk40t/gui/busy.py +232 -133
- meerk40t/gui/choicepropertypanel.py +1662 -1469
- meerk40t/gui/consolepanel.py +706 -542
- meerk40t/gui/devicepanel.py +687 -581
- meerk40t/gui/dialogoptions.py +110 -107
- meerk40t/gui/executejob.py +316 -306
- meerk40t/gui/fonts.py +90 -90
- meerk40t/gui/functionwrapper.py +252 -0
- meerk40t/gui/gui_mixins.py +729 -0
- meerk40t/gui/guicolors.py +205 -182
- meerk40t/gui/help_assets/help_assets.py +218 -201
- meerk40t/gui/helper.py +154 -0
- meerk40t/gui/hersheymanager.py +1440 -846
- meerk40t/gui/icons.py +3422 -2747
- meerk40t/gui/imagesplitter.py +555 -508
- meerk40t/gui/keymap.py +354 -344
- meerk40t/gui/laserpanel.py +897 -806
- meerk40t/gui/laserrender.py +1470 -1232
- meerk40t/gui/lasertoolpanel.py +805 -793
- meerk40t/gui/magnetoptions.py +436 -0
- meerk40t/gui/materialmanager.py +2944 -0
- meerk40t/gui/materialtest.py +1722 -1694
- meerk40t/gui/mkdebug.py +646 -359
- meerk40t/gui/mwindow.py +163 -140
- meerk40t/gui/navigationpanels.py +2605 -2467
- meerk40t/gui/notes.py +143 -142
- meerk40t/gui/opassignment.py +414 -410
- meerk40t/gui/operation_info.py +310 -299
- meerk40t/gui/plugin.py +500 -328
- meerk40t/gui/position.py +714 -669
- meerk40t/gui/preferences.py +901 -650
- meerk40t/gui/propertypanels/attributes.py +1461 -1131
- meerk40t/gui/propertypanels/blobproperty.py +117 -114
- meerk40t/gui/propertypanels/consoleproperty.py +83 -80
- meerk40t/gui/propertypanels/gotoproperty.py +77 -0
- meerk40t/gui/propertypanels/groupproperties.py +223 -217
- meerk40t/gui/propertypanels/hatchproperty.py +489 -469
- meerk40t/gui/propertypanels/imageproperty.py +2244 -1384
- meerk40t/gui/propertypanels/inputproperty.py +59 -58
- meerk40t/gui/propertypanels/opbranchproperties.py +82 -80
- meerk40t/gui/propertypanels/operationpropertymain.py +1890 -1638
- meerk40t/gui/propertypanels/outputproperty.py +59 -58
- meerk40t/gui/propertypanels/pathproperty.py +389 -380
- meerk40t/gui/propertypanels/placementproperty.py +1214 -383
- meerk40t/gui/propertypanels/pointproperty.py +140 -136
- meerk40t/gui/propertypanels/propertywindow.py +313 -181
- meerk40t/gui/propertypanels/rasterwizardpanels.py +996 -912
- meerk40t/gui/propertypanels/regbranchproperties.py +76 -0
- meerk40t/gui/propertypanels/textproperty.py +770 -755
- meerk40t/gui/propertypanels/waitproperty.py +56 -55
- meerk40t/gui/propertypanels/warpproperty.py +121 -0
- meerk40t/gui/propertypanels/wobbleproperty.py +255 -204
- meerk40t/gui/ribbon.py +2471 -2210
- meerk40t/gui/scene/scene.py +1100 -1051
- meerk40t/gui/scene/sceneconst.py +22 -22
- meerk40t/gui/scene/scenepanel.py +439 -349
- meerk40t/gui/scene/scenespacewidget.py +365 -365
- meerk40t/gui/scene/widget.py +518 -505
- meerk40t/gui/scenewidgets/affinemover.py +215 -215
- meerk40t/gui/scenewidgets/attractionwidget.py +315 -309
- meerk40t/gui/scenewidgets/bedwidget.py +120 -97
- meerk40t/gui/scenewidgets/elementswidget.py +137 -107
- meerk40t/gui/scenewidgets/gridwidget.py +785 -745
- meerk40t/gui/scenewidgets/guidewidget.py +765 -765
- meerk40t/gui/scenewidgets/laserpathwidget.py +66 -66
- meerk40t/gui/scenewidgets/machineoriginwidget.py +86 -86
- meerk40t/gui/scenewidgets/nodeselector.py +28 -28
- meerk40t/gui/scenewidgets/rectselectwidget.py +592 -346
- meerk40t/gui/scenewidgets/relocatewidget.py +33 -33
- meerk40t/gui/scenewidgets/reticlewidget.py +83 -83
- meerk40t/gui/scenewidgets/selectionwidget.py +2958 -2756
- meerk40t/gui/simpleui.py +362 -333
- meerk40t/gui/simulation.py +2451 -2094
- meerk40t/gui/snapoptions.py +208 -203
- meerk40t/gui/spoolerpanel.py +1227 -1180
- meerk40t/gui/statusbarwidgets/defaultoperations.py +480 -353
- meerk40t/gui/statusbarwidgets/infowidget.py +520 -483
- meerk40t/gui/statusbarwidgets/opassignwidget.py +356 -355
- meerk40t/gui/statusbarwidgets/selectionwidget.py +172 -171
- meerk40t/gui/statusbarwidgets/shapepropwidget.py +754 -236
- meerk40t/gui/statusbarwidgets/statusbar.py +272 -260
- meerk40t/gui/statusbarwidgets/statusbarwidget.py +268 -270
- meerk40t/gui/statusbarwidgets/strokewidget.py +267 -251
- meerk40t/gui/themes.py +200 -78
- meerk40t/gui/tips.py +590 -0
- meerk40t/gui/toolwidgets/circlebrush.py +35 -35
- meerk40t/gui/toolwidgets/toolcircle.py +248 -242
- meerk40t/gui/toolwidgets/toolcontainer.py +82 -77
- meerk40t/gui/toolwidgets/tooldraw.py +97 -90
- meerk40t/gui/toolwidgets/toolellipse.py +219 -212
- meerk40t/gui/toolwidgets/toolimagecut.py +25 -132
- meerk40t/gui/toolwidgets/toolline.py +39 -144
- meerk40t/gui/toolwidgets/toollinetext.py +79 -236
- meerk40t/gui/toolwidgets/toollinetext_inline.py +296 -0
- meerk40t/gui/toolwidgets/toolmeasure.py +163 -216
- meerk40t/gui/toolwidgets/toolnodeedit.py +2088 -2074
- meerk40t/gui/toolwidgets/toolnodemove.py +92 -94
- meerk40t/gui/toolwidgets/toolparameter.py +754 -668
- meerk40t/gui/toolwidgets/toolplacement.py +108 -108
- meerk40t/gui/toolwidgets/toolpoint.py +68 -59
- meerk40t/gui/toolwidgets/toolpointlistbuilder.py +294 -0
- meerk40t/gui/toolwidgets/toolpointmove.py +183 -0
- meerk40t/gui/toolwidgets/toolpolygon.py +288 -403
- meerk40t/gui/toolwidgets/toolpolyline.py +38 -196
- meerk40t/gui/toolwidgets/toolrect.py +211 -207
- meerk40t/gui/toolwidgets/toolrelocate.py +72 -72
- meerk40t/gui/toolwidgets/toolribbon.py +598 -113
- meerk40t/gui/toolwidgets/tooltabedit.py +546 -0
- meerk40t/gui/toolwidgets/tooltext.py +98 -89
- meerk40t/gui/toolwidgets/toolvector.py +213 -204
- meerk40t/gui/toolwidgets/toolwidget.py +39 -39
- meerk40t/gui/usbconnect.py +98 -91
- meerk40t/gui/utilitywidgets/buttonwidget.py +18 -18
- meerk40t/gui/utilitywidgets/checkboxwidget.py +90 -90
- meerk40t/gui/utilitywidgets/controlwidget.py +14 -14
- meerk40t/gui/utilitywidgets/cyclocycloidwidget.py +343 -340
- meerk40t/gui/utilitywidgets/debugwidgets.py +148 -0
- meerk40t/gui/utilitywidgets/handlewidget.py +27 -27
- meerk40t/gui/utilitywidgets/harmonograph.py +450 -447
- meerk40t/gui/utilitywidgets/openclosewidget.py +40 -40
- meerk40t/gui/utilitywidgets/rotationwidget.py +54 -54
- meerk40t/gui/utilitywidgets/scalewidget.py +75 -75
- meerk40t/gui/utilitywidgets/seekbarwidget.py +183 -183
- meerk40t/gui/utilitywidgets/togglewidget.py +142 -142
- meerk40t/gui/utilitywidgets/toolbarwidget.py +8 -8
- meerk40t/gui/wordlisteditor.py +985 -931
- meerk40t/gui/wxmeerk40t.py +1447 -1169
- meerk40t/gui/wxmmain.py +5644 -4112
- meerk40t/gui/wxmribbon.py +1591 -1076
- meerk40t/gui/wxmscene.py +1631 -1453
- meerk40t/gui/wxmtree.py +2416 -2089
- meerk40t/gui/wxutils.py +1769 -1099
- meerk40t/gui/zmatrix.py +102 -102
- meerk40t/image/__init__.py +1 -1
- meerk40t/image/dither.py +429 -0
- meerk40t/image/imagetools.py +2793 -2269
- meerk40t/internal_plugins.py +150 -130
- meerk40t/kernel/__init__.py +63 -12
- meerk40t/kernel/channel.py +259 -212
- meerk40t/kernel/context.py +538 -538
- meerk40t/kernel/exceptions.py +41 -41
- meerk40t/kernel/functions.py +463 -414
- meerk40t/kernel/jobs.py +100 -100
- meerk40t/kernel/kernel.py +3828 -3571
- meerk40t/kernel/lifecycles.py +71 -71
- meerk40t/kernel/module.py +49 -49
- meerk40t/kernel/service.py +147 -147
- meerk40t/kernel/settings.py +383 -343
- meerk40t/lihuiyu/controller.py +883 -876
- meerk40t/lihuiyu/device.py +1181 -1069
- meerk40t/lihuiyu/driver.py +1466 -1372
- meerk40t/lihuiyu/gui/gui.py +127 -106
- meerk40t/lihuiyu/gui/lhyaccelgui.py +377 -363
- meerk40t/lihuiyu/gui/lhycontrollergui.py +741 -651
- meerk40t/lihuiyu/gui/lhydrivergui.py +470 -446
- meerk40t/lihuiyu/gui/lhyoperationproperties.py +238 -237
- meerk40t/lihuiyu/gui/tcpcontroller.py +226 -190
- meerk40t/lihuiyu/interpreter.py +53 -53
- meerk40t/lihuiyu/laserspeed.py +450 -450
- meerk40t/lihuiyu/loader.py +90 -90
- meerk40t/lihuiyu/parser.py +404 -404
- meerk40t/lihuiyu/plugin.py +101 -102
- meerk40t/lihuiyu/tcp_connection.py +111 -109
- meerk40t/main.py +231 -165
- meerk40t/moshi/builder.py +788 -781
- meerk40t/moshi/controller.py +505 -499
- meerk40t/moshi/device.py +495 -442
- meerk40t/moshi/driver.py +862 -696
- meerk40t/moshi/gui/gui.py +78 -76
- meerk40t/moshi/gui/moshicontrollergui.py +538 -522
- meerk40t/moshi/gui/moshidrivergui.py +87 -75
- meerk40t/moshi/plugin.py +43 -43
- meerk40t/network/console_server.py +140 -57
- meerk40t/network/kernelserver.py +10 -9
- meerk40t/network/tcp_server.py +142 -140
- meerk40t/network/udp_server.py +103 -77
- meerk40t/network/web_server.py +404 -0
- meerk40t/newly/controller.py +1158 -1144
- meerk40t/newly/device.py +874 -732
- meerk40t/newly/driver.py +540 -412
- meerk40t/newly/gui/gui.py +219 -188
- meerk40t/newly/gui/newlyconfig.py +116 -101
- meerk40t/newly/gui/newlycontroller.py +193 -186
- meerk40t/newly/gui/operationproperties.py +51 -51
- meerk40t/newly/mock_connection.py +82 -82
- meerk40t/newly/newly_params.py +56 -56
- meerk40t/newly/plugin.py +1214 -1246
- meerk40t/newly/usb_connection.py +322 -322
- meerk40t/rotary/gui/gui.py +52 -46
- meerk40t/rotary/gui/rotarysettings.py +240 -232
- meerk40t/rotary/rotary.py +202 -98
- meerk40t/ruida/control.py +291 -91
- meerk40t/ruida/controller.py +138 -1088
- meerk40t/ruida/device.py +676 -231
- meerk40t/ruida/driver.py +534 -472
- meerk40t/ruida/emulator.py +1494 -1491
- meerk40t/ruida/exceptions.py +4 -4
- meerk40t/ruida/gui/gui.py +71 -76
- meerk40t/ruida/gui/ruidaconfig.py +239 -72
- meerk40t/ruida/gui/ruidacontroller.py +187 -184
- meerk40t/ruida/gui/ruidaoperationproperties.py +48 -47
- meerk40t/ruida/loader.py +54 -52
- meerk40t/ruida/mock_connection.py +57 -109
- meerk40t/ruida/plugin.py +124 -87
- meerk40t/ruida/rdjob.py +2084 -945
- meerk40t/ruida/serial_connection.py +116 -0
- meerk40t/ruida/tcp_connection.py +146 -0
- meerk40t/ruida/udp_connection.py +73 -0
- meerk40t/svgelements.py +9671 -9669
- meerk40t/tools/driver_to_path.py +584 -579
- meerk40t/tools/geomstr.py +5583 -4680
- meerk40t/tools/jhfparser.py +357 -292
- meerk40t/tools/kerftest.py +904 -890
- meerk40t/tools/livinghinges.py +1168 -1033
- meerk40t/tools/pathtools.py +987 -949
- meerk40t/tools/pmatrix.py +234 -0
- meerk40t/tools/pointfinder.py +942 -942
- meerk40t/tools/polybool.py +941 -940
- meerk40t/tools/rasterplotter.py +1660 -547
- meerk40t/tools/shxparser.py +1047 -901
- meerk40t/tools/ttfparser.py +726 -446
- meerk40t/tools/zinglplotter.py +595 -593
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/LICENSE +21 -21
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/METADATA +150 -139
- meerk40t-0.9.7020.dist-info/RECORD +446 -0
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/WHEEL +1 -1
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/top_level.txt +0 -1
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/zip-safe +1 -1
- meerk40t/balormk/elementlightjob.py +0 -159
- meerk40t-0.9.3001.dist-info/RECORD +0 -437
- test/bootstrap.py +0 -63
- test/test_cli.py +0 -12
- test/test_core_cutcode.py +0 -418
- test/test_core_elements.py +0 -144
- test/test_core_plotplanner.py +0 -397
- test/test_core_viewports.py +0 -312
- test/test_drivers_grbl.py +0 -108
- test/test_drivers_lihuiyu.py +0 -443
- test/test_drivers_newly.py +0 -113
- test/test_element_degenerate_points.py +0 -43
- test/test_elements_classify.py +0 -97
- test/test_elements_penbox.py +0 -22
- test/test_file_svg.py +0 -176
- test/test_fill.py +0 -155
- test/test_geomstr.py +0 -1523
- test/test_geomstr_nodes.py +0 -18
- test/test_imagetools_actualize.py +0 -306
- test/test_imagetools_wizard.py +0 -258
- test/test_kernel.py +0 -200
- test/test_laser_speeds.py +0 -3303
- test/test_length.py +0 -57
- test/test_lifecycle.py +0 -66
- test/test_operations.py +0 -251
- test/test_operations_hatch.py +0 -57
- test/test_ruida.py +0 -19
- test/test_spooler.py +0 -22
- test/test_tools_rasterplotter.py +0 -29
- test/test_wobble.py +0 -133
- test/test_zingl.py +0 -124
- {test → meerk40t/cylinder}/__init__.py +0 -0
- /meerk40t/{core/element_commands.py → cylinder/gui/__init__.py} +0 -0
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/entry_points.txt +0 -0
meerk40t/kernel/context.py
CHANGED
@@ -1,538 +1,538 @@
|
|
1
|
-
from typing import Any, Callable, Dict, Generator, Optional, Tuple, Union
|
2
|
-
|
3
|
-
from .jobs import ConsoleFunction
|
4
|
-
from .lifecycles import *
|
5
|
-
|
6
|
-
|
7
|
-
class Context:
|
8
|
-
"""
|
9
|
-
Contexts serve as path-relevant snapshots of the kernel. These are the primary interaction between the modules
|
10
|
-
and the kernel. They permit getting other contexts of the kernel. This should serve as the primary interface
|
11
|
-
code between the kernel and the modules.
|
12
|
-
|
13
|
-
Contexts store the persistent settings and settings from at their path locations.
|
14
|
-
|
15
|
-
Contexts have attribute settings located at .<setting> and so long as this setting does not begin with _ it will be
|
16
|
-
reloaded when .setting() is called for the given attribute. This should be called by code that intends access
|
17
|
-
an attribute even if it was already called.
|
18
|
-
"""
|
19
|
-
|
20
|
-
def __init__(self, kernel: "Kernel", path: str):
|
21
|
-
self._kernel = kernel
|
22
|
-
self._path = path
|
23
|
-
self._state = "unknown"
|
24
|
-
self.opened = {}
|
25
|
-
|
26
|
-
def __repr__(self):
|
27
|
-
return f"Context('{self._path}')"
|
28
|
-
|
29
|
-
def __call__(self, data: str, **kwargs):
|
30
|
-
if len(data) and data[-1] != "\n":
|
31
|
-
data += "\n"
|
32
|
-
return self._kernel.console(data)
|
33
|
-
|
34
|
-
# ==========
|
35
|
-
# PATH INFORMATION
|
36
|
-
# ==========
|
37
|
-
|
38
|
-
def abs_path(self, subpath: str) -> str:
|
39
|
-
"""
|
40
|
-
The absolute path function determines the absolute path of the given subpath within the current path of the
|
41
|
-
context.
|
42
|
-
|
43
|
-
@param subpath: relative path to the path at this context
|
44
|
-
@return:
|
45
|
-
"""
|
46
|
-
subpath = str(subpath)
|
47
|
-
if subpath.startswith("/"):
|
48
|
-
return subpath[1:]
|
49
|
-
if self._path is None or self._path == "/":
|
50
|
-
return subpath
|
51
|
-
return f"{self._path}/{subpath}"
|
52
|
-
|
53
|
-
def derive(self, path: str) -> "Context":
|
54
|
-
"""
|
55
|
-
Derive a subpath context.
|
56
|
-
|
57
|
-
@param path:
|
58
|
-
@return:
|
59
|
-
"""
|
60
|
-
return self._kernel.get_context(self.abs_path(path))
|
61
|
-
|
62
|
-
@property
|
63
|
-
def root(self) -> "Context":
|
64
|
-
return self.get_context("/")
|
65
|
-
|
66
|
-
@property
|
67
|
-
def path(self) -> str:
|
68
|
-
return self._path
|
69
|
-
|
70
|
-
@property
|
71
|
-
def kernel(self) -> "Kernel":
|
72
|
-
return self._kernel
|
73
|
-
|
74
|
-
@property
|
75
|
-
def _(self):
|
76
|
-
return self._kernel.translation
|
77
|
-
|
78
|
-
def get_context(self, path) -> "Context":
|
79
|
-
"""
|
80
|
-
Get a context at a given path location.
|
81
|
-
|
82
|
-
@param path: path location to get a context.
|
83
|
-
@return:
|
84
|
-
"""
|
85
|
-
return self._kernel.get_context(path)
|
86
|
-
|
87
|
-
def subpaths(self) -> Generator["Context", None, None]:
|
88
|
-
"""
|
89
|
-
Generate all subpaths of the current context with their path name and the relevant context.
|
90
|
-
"""
|
91
|
-
for e in list(self._kernel.contexts):
|
92
|
-
if e.startswith(self._path):
|
93
|
-
yield e, self._kernel.contexts[e]
|
94
|
-
|
95
|
-
def close_subpaths(self) -> None:
|
96
|
-
"""
|
97
|
-
Find all subpaths of the current context and delete them.
|
98
|
-
|
99
|
-
This is not a maintenance operation. It's needed for rare instances during shutdown. All contexts will be
|
100
|
-
shutdown, this prevents normal shutdown procedure.
|
101
|
-
"""
|
102
|
-
for e in list(self._kernel.contexts):
|
103
|
-
if e.startswith(self._path):
|
104
|
-
del self._kernel.contexts[e]
|
105
|
-
|
106
|
-
def destroy(self):
|
107
|
-
self.clear_persistent()
|
108
|
-
self.close_subpaths()
|
109
|
-
|
110
|
-
# ==========
|
111
|
-
# PERSISTENT SETTINGS.
|
112
|
-
# ==========
|
113
|
-
|
114
|
-
def setting(self, setting_type, key, default=None) -> Any:
|
115
|
-
"""
|
116
|
-
Registers a setting to be used between modules.
|
117
|
-
|
118
|
-
If the setting exists, its value remains unchanged.
|
119
|
-
If the setting exists in the persistent storage that value is used.
|
120
|
-
If there is no settings value, the default will be used.
|
121
|
-
|
122
|
-
@param setting_type: int, float, str, bool, list or tuple value
|
123
|
-
@param key: name of the setting
|
124
|
-
@param default: default value for the setting to have.
|
125
|
-
@return: load_value
|
126
|
-
"""
|
127
|
-
if hasattr(self, key) and getattr(self, key) is not None:
|
128
|
-
return getattr(self, key)
|
129
|
-
|
130
|
-
# Key is not located in the attr. Load the value.
|
131
|
-
if not key.startswith("_"):
|
132
|
-
load_value = self._kernel.read_persistent(
|
133
|
-
setting_type, self._path, key, default
|
134
|
-
)
|
135
|
-
else:
|
136
|
-
load_value = default
|
137
|
-
if load_value is not None and not isinstance(load_value, setting_type):
|
138
|
-
load_value = setting_type(load_value)
|
139
|
-
setattr(self, key, load_value)
|
140
|
-
return load_value
|
141
|
-
|
142
|
-
def flush(self) -> None:
|
143
|
-
"""
|
144
|
-
Commit any and all values currently stored as attr for this object to persistent storage.
|
145
|
-
"""
|
146
|
-
self._kernel.write_persistent_attributes(self._path, self)
|
147
|
-
|
148
|
-
def write_persistent_attributes(self, obj: Any) -> None:
|
149
|
-
"""
|
150
|
-
Writes values of the object's attributes at this context
|
151
|
-
@param obj:
|
152
|
-
@return:
|
153
|
-
"""
|
154
|
-
self._kernel.write_persistent_attributes(self._path, obj)
|
155
|
-
|
156
|
-
def read_persistent(self, t: type, key: str) -> Any:
|
157
|
-
"""
|
158
|
-
Gets a specific value of the persistent attributes.
|
159
|
-
|
160
|
-
The attribute type of the value depends on the provided object value default values.
|
161
|
-
|
162
|
-
@param t: type of value
|
163
|
-
@param key: relative key
|
164
|
-
@return: the value associated with the key otherwise None
|
165
|
-
"""
|
166
|
-
return self._kernel.read_persistent(t, self._path, key)
|
167
|
-
|
168
|
-
def read_persistent_attributes(self, obj: Any) -> None:
|
169
|
-
"""
|
170
|
-
Loads values of the persistent attributes, at this context and assigns them to the provided object.
|
171
|
-
|
172
|
-
The attribute type of the value depends on the provided object value default values.
|
173
|
-
|
174
|
-
@param obj:
|
175
|
-
@return:
|
176
|
-
"""
|
177
|
-
self._kernel.read_persistent_attributes(self._path, obj)
|
178
|
-
|
179
|
-
def read_persistent_string_dict(
|
180
|
-
self, dictionary: Optional[Dict] = None, suffix: bool = False
|
181
|
-
) -> Dict:
|
182
|
-
"""
|
183
|
-
Delegate to kernel to get a local string of dictionary values.
|
184
|
-
|
185
|
-
@param dictionary: optional dictionary to be updated with values
|
186
|
-
@param suffix:
|
187
|
-
@return:
|
188
|
-
"""
|
189
|
-
return self._kernel.read_persistent_string_dict(
|
190
|
-
self._path, dictionary=dictionary, suffix=suffix
|
191
|
-
)
|
192
|
-
|
193
|
-
def clear_persistent(self) -> None:
|
194
|
-
"""
|
195
|
-
Delegate to Kernel to clear the persistent settings located at this context.
|
196
|
-
"""
|
197
|
-
self._kernel.clear_persistent(self._path)
|
198
|
-
|
199
|
-
def write_persistent(
|
200
|
-
self, key: str, value: Union[int, float, str, bool, list, tuple]
|
201
|
-
) -> None:
|
202
|
-
"""
|
203
|
-
Delegate to Kernel to write the given key at this context to persistent settings. This is typically done during
|
204
|
-
shutdown but there are a variety of reasons to force this call early.
|
205
|
-
|
206
|
-
If the persistence object is not yet established this function cannot succeed.
|
207
|
-
"""
|
208
|
-
self._kernel.write_persistent(self._path, key, value)
|
209
|
-
|
210
|
-
# ==========
|
211
|
-
# DELEGATES
|
212
|
-
# ==========
|
213
|
-
|
214
|
-
def register(self, path: str, obj: Any) -> None:
|
215
|
-
"""
|
216
|
-
Delegate to Kernel
|
217
|
-
"""
|
218
|
-
self._kernel.register(path, obj)
|
219
|
-
|
220
|
-
def unregister(self, path: str) -> None:
|
221
|
-
"""
|
222
|
-
Delegate to Kernel
|
223
|
-
"""
|
224
|
-
self._kernel.unregister(path)
|
225
|
-
|
226
|
-
def console_argument(self, *args, **kwargs) -> Callable:
|
227
|
-
"""
|
228
|
-
Delegate to Kernel
|
229
|
-
|
230
|
-
Uses current context to be passed to the console_argument being registered.
|
231
|
-
"""
|
232
|
-
return self._kernel.console_argument(*args, **kwargs)
|
233
|
-
|
234
|
-
def console_option(self, *args, **kwargs) -> Callable:
|
235
|
-
"""
|
236
|
-
Delegate to Kernel
|
237
|
-
|
238
|
-
Uses current context to be passed to the console_option being registered.
|
239
|
-
"""
|
240
|
-
return self._kernel.console_option(*args, **kwargs)
|
241
|
-
|
242
|
-
def console_command(self, *args, **kwargs) -> Callable:
|
243
|
-
"""
|
244
|
-
Delegate to Kernel
|
245
|
-
|
246
|
-
Uses current context to be passed to the console_command being registered.
|
247
|
-
"""
|
248
|
-
return self._kernel.console_command(*args, **kwargs)
|
249
|
-
|
250
|
-
def console_command_remove(self, *args, **kwargs) -> Callable:
|
251
|
-
"""
|
252
|
-
Delegate to Kernel
|
253
|
-
|
254
|
-
Uses current context to be passed to the console_command being removed.
|
255
|
-
"""
|
256
|
-
return self._kernel.console_command_remove(*args, **kwargs)
|
257
|
-
|
258
|
-
@property
|
259
|
-
def contexts(self) -> Dict[str, "Context"]:
|
260
|
-
return self._kernel.contexts
|
261
|
-
|
262
|
-
def has_feature(self, feature: str) -> bool:
|
263
|
-
"""
|
264
|
-
Return whether this is a registered feature within the kernel.
|
265
|
-
|
266
|
-
@param feature: feature to check if exists in kernel.
|
267
|
-
@return:
|
268
|
-
"""
|
269
|
-
return self.lookup(feature) is not None
|
270
|
-
|
271
|
-
def find(self, *args):
|
272
|
-
"""
|
273
|
-
Delegate of Kernel match.
|
274
|
-
|
275
|
-
@param args: arguments to be delegated
|
276
|
-
:yield: matched entries.
|
277
|
-
"""
|
278
|
-
yield from self._kernel.find(*args)
|
279
|
-
|
280
|
-
def match(self, matchtext: str, suffix: bool = False) -> Generator[str, None, None]:
|
281
|
-
"""
|
282
|
-
Delegate of Kernel match.
|
283
|
-
|
284
|
-
@param matchtext: regex matchtext to locate.
|
285
|
-
@param suffix: provide the suffix of the match only.
|
286
|
-
:yield: matched entries.
|
287
|
-
"""
|
288
|
-
yield from self._kernel.match(matchtext, suffix)
|
289
|
-
|
290
|
-
def lookup(self, *args) -> Any:
|
291
|
-
"""
|
292
|
-
Lookup a value in the kernel or services.
|
293
|
-
|
294
|
-
@param args: arguments
|
295
|
-
@return:
|
296
|
-
"""
|
297
|
-
return self._kernel.lookup(*args)
|
298
|
-
|
299
|
-
def lookup_all(self, *args) -> Any:
|
300
|
-
"""
|
301
|
-
Lookup all matching values in the kernel or services.
|
302
|
-
|
303
|
-
@param args: arguments
|
304
|
-
@return:
|
305
|
-
"""
|
306
|
-
yield from self._kernel.lookup_all(*args)
|
307
|
-
|
308
|
-
def console(self, data: str) -> None:
|
309
|
-
"""
|
310
|
-
Call the Kernel's Console with the given data.
|
311
|
-
|
312
|
-
Note: '\n' is usually used to execute these functions and this is not added by default.
|
313
|
-
"""
|
314
|
-
self._kernel.console(data)
|
315
|
-
|
316
|
-
def schedule(self, job: Union["Job", Any]) -> None:
|
317
|
-
"""
|
318
|
-
Call the Kernel's Scheduler with the given job.
|
319
|
-
"""
|
320
|
-
self._kernel.schedule(job)
|
321
|
-
|
322
|
-
def unschedule(self, job: Union["Job", Any]) -> None:
|
323
|
-
"""
|
324
|
-
Unschedule a given job.
|
325
|
-
|
326
|
-
This is often unneeded if the job completes on its own, it will be removed from the scheduler.
|
327
|
-
"""
|
328
|
-
self._kernel.unschedule(job)
|
329
|
-
|
330
|
-
def threaded(
|
331
|
-
self,
|
332
|
-
func: Callable,
|
333
|
-
*args,
|
334
|
-
thread_name: str = None,
|
335
|
-
result: Callable = None,
|
336
|
-
daemon: bool = False,
|
337
|
-
):
|
338
|
-
"""
|
339
|
-
Calls a thread to be registered in the kernel.
|
340
|
-
|
341
|
-
Registered threads must complete before shutdown can be completed. These will be told to stop and waited on until
|
342
|
-
completion.
|
343
|
-
|
344
|
-
The result function will be called with any returned result func.
|
345
|
-
"""
|
346
|
-
return self._kernel.threaded(
|
347
|
-
func,
|
348
|
-
*args,
|
349
|
-
thread_name=thread_name,
|
350
|
-
result=result,
|
351
|
-
daemon=daemon,
|
352
|
-
)
|
353
|
-
|
354
|
-
# ==========
|
355
|
-
# MODULES
|
356
|
-
# ==========
|
357
|
-
|
358
|
-
def get_open(self, path: str) -> Union["Module", None]:
|
359
|
-
"""
|
360
|
-
Finds a loaded instance. Or returns None if not such instance.
|
361
|
-
|
362
|
-
Note: 'name' is not necessarily the type of instance. It could be the named value of the instance.
|
363
|
-
|
364
|
-
@param path: The opened path to find the given instance.
|
365
|
-
@return: The instance, if found, otherwise None.
|
366
|
-
"""
|
367
|
-
try:
|
368
|
-
return self.opened[path]
|
369
|
-
except KeyError:
|
370
|
-
return None
|
371
|
-
|
372
|
-
def open(self, registered_path: str, *args, **kwargs) -> "Module":
|
373
|
-
"""
|
374
|
-
Opens a registered module with the same instance path as the registered path.
|
375
|
-
|
376
|
-
This is fairly standard but should not be used if the goal would be to open the same module several times.
|
377
|
-
Unless those modules are being opened at different contexts.
|
378
|
-
|
379
|
-
@param registered_path: registered path of the given module.
|
380
|
-
@param args: args to open the module with.
|
381
|
-
@param kwargs: kwargs to open the module with.
|
382
|
-
@return:
|
383
|
-
"""
|
384
|
-
return self.open_as(registered_path, registered_path, *args, **kwargs)
|
385
|
-
|
386
|
-
def open_as(
|
387
|
-
self, registered_path: str, instance_path: str, *args, **kwargs
|
388
|
-
) -> "Module":
|
389
|
-
"""
|
390
|
-
Opens a registered module. If that module already exists it returns the already open module.
|
391
|
-
|
392
|
-
Instance_name is the name under which this given module is opened.
|
393
|
-
|
394
|
-
If the module already exists, the restore function is called on that object (if restore() exists), with the same
|
395
|
-
args and kwargs that were intended for the init() routine.
|
396
|
-
|
397
|
-
@param registered_path: path of object being opened.
|
398
|
-
@param instance_path: instance_path of object.
|
399
|
-
@param args: Args to pass to newly opened module.
|
400
|
-
@param kwargs: Kwargs to pass to newly opened module.
|
401
|
-
@return: Opened module.
|
402
|
-
"""
|
403
|
-
try:
|
404
|
-
find = self.opened[instance_path]
|
405
|
-
try:
|
406
|
-
# Module found, attempt restore call.
|
407
|
-
find.restore(*args, **kwargs)
|
408
|
-
except AttributeError:
|
409
|
-
pass
|
410
|
-
return find
|
411
|
-
except KeyError:
|
412
|
-
# Module not found.
|
413
|
-
pass
|
414
|
-
|
415
|
-
open_object = self._kernel.lookup(registered_path)
|
416
|
-
if open_object is None:
|
417
|
-
raise ValueError
|
418
|
-
|
419
|
-
instance = open_object(self, instance_path, *args, **kwargs)
|
420
|
-
instance.registered_path = registered_path
|
421
|
-
self._module_delegate(instance)
|
422
|
-
|
423
|
-
# Call module_open lifecycle event.
|
424
|
-
self.kernel.set_module_lifecycle(instance, LIFECYCLE_MODULE_OPENED)
|
425
|
-
|
426
|
-
return instance
|
427
|
-
|
428
|
-
def _module_delegate(self, module, model=None, add=True):
|
429
|
-
"""
|
430
|
-
Recursively find any delegates for a module yielded under `.delegate()`
|
431
|
-
@param module:
|
432
|
-
@param model:
|
433
|
-
@param add:
|
434
|
-
@return:
|
435
|
-
"""
|
436
|
-
kernel = self.kernel
|
437
|
-
if model is None:
|
438
|
-
model = module
|
439
|
-
|
440
|
-
try:
|
441
|
-
if model is not module:
|
442
|
-
# We are the model we don't delegate to it.
|
443
|
-
if add:
|
444
|
-
kernel.add_delegate(model, module)
|
445
|
-
else:
|
446
|
-
kernel.remove_delegate(model, module)
|
447
|
-
for delegate in model.delegates():
|
448
|
-
self._module_delegate(module=module, model=delegate, add=add)
|
449
|
-
except AttributeError:
|
450
|
-
pass
|
451
|
-
|
452
|
-
def close(self, instance_path: str, *args, **kwargs) -> None:
|
453
|
-
"""
|
454
|
-
Closes an opened module instance. Located at the instance_path location.
|
455
|
-
|
456
|
-
This calls the close() function on the object (which may not exist). Then calls module_close() on the module,
|
457
|
-
which should exist.
|
458
|
-
|
459
|
-
@param instance_path: Instance path to close.
|
460
|
-
@return:
|
461
|
-
"""
|
462
|
-
try:
|
463
|
-
instance = self.opened[instance_path]
|
464
|
-
except KeyError:
|
465
|
-
return # Nothing to close.
|
466
|
-
# Call module_close lifecycle event.
|
467
|
-
self.kernel.set_module_lifecycle(instance, LIFECYCLE_MODULE_CLOSED)
|
468
|
-
|
469
|
-
# ==========
|
470
|
-
# SIGNALS DELEGATES
|
471
|
-
# ==========
|
472
|
-
|
473
|
-
def signal(self, code: str, *message) -> None:
|
474
|
-
"""
|
475
|
-
Send Signal to all registered listeners.
|
476
|
-
|
477
|
-
@param code: Code to delegate at this given context location.
|
478
|
-
@param message: Message to send.
|
479
|
-
@return:
|
480
|
-
"""
|
481
|
-
self._kernel.signal(code, self._path, *message)
|
482
|
-
|
483
|
-
def last_signal(self, signal: str) -> Tuple:
|
484
|
-
"""
|
485
|
-
Returns the last signal payload at the given code.
|
486
|
-
|
487
|
-
@param signal: Code to delegate at this given context location.
|
488
|
-
@return: message value of the last signal sent for that code.
|
489
|
-
"""
|
490
|
-
return self._kernel.last_signal(signal)
|
491
|
-
|
492
|
-
def listen(
|
493
|
-
self,
|
494
|
-
signal: str,
|
495
|
-
process: Callable,
|
496
|
-
lifecycle_object: Union["Service", "Module", None] = None,
|
497
|
-
) -> None:
|
498
|
-
"""
|
499
|
-
Listen at a particular signal with a given process.
|
500
|
-
|
501
|
-
@param signal: Signal code to listen for
|
502
|
-
@param process: listener to be attached
|
503
|
-
@param lifecycle_object: Object to use as a cookie to bind the listener.
|
504
|
-
@return:
|
505
|
-
"""
|
506
|
-
self._kernel.listen(signal, process, lifecycle_object)
|
507
|
-
|
508
|
-
def unlisten(self, signal: str, process: Callable):
|
509
|
-
"""
|
510
|
-
Unlisten to a particular signal with a given process.
|
511
|
-
|
512
|
-
This should be called on the ending of the lifecycle of whatever process listened to the given signal.
|
513
|
-
|
514
|
-
@param signal: Signal to unlisten for.
|
515
|
-
@param process: listener that is to be detached.
|
516
|
-
@return:
|
517
|
-
"""
|
518
|
-
self._kernel.unlisten(signal, process)
|
519
|
-
|
520
|
-
# ==========
|
521
|
-
# CHANNEL DELEGATES
|
522
|
-
# ==========
|
523
|
-
|
524
|
-
def channel(self, channel: str, *args, **kwargs) -> "Channel":
|
525
|
-
"""
|
526
|
-
Return a channel from the kernel location
|
527
|
-
|
528
|
-
@param channel: Channel to be opened.
|
529
|
-
@return: Channel object that is opened.
|
530
|
-
"""
|
531
|
-
return self._kernel.channel(channel, *args, **kwargs)
|
532
|
-
|
533
|
-
def console_function(self, data: str) -> "ConsoleFunction":
|
534
|
-
"""
|
535
|
-
Returns a function that calls a console command. This serves as a Job to be used in Scheduler or simply a
|
536
|
-
function with the command as the str form.
|
537
|
-
"""
|
538
|
-
return ConsoleFunction(self, data)
|
1
|
+
from typing import Any, Callable, Dict, Generator, Optional, Tuple, Union
|
2
|
+
|
3
|
+
from .jobs import ConsoleFunction
|
4
|
+
from .lifecycles import *
|
5
|
+
|
6
|
+
|
7
|
+
class Context:
|
8
|
+
"""
|
9
|
+
Contexts serve as path-relevant snapshots of the kernel. These are the primary interaction between the modules
|
10
|
+
and the kernel. They permit getting other contexts of the kernel. This should serve as the primary interface
|
11
|
+
code between the kernel and the modules.
|
12
|
+
|
13
|
+
Contexts store the persistent settings and settings from at their path locations.
|
14
|
+
|
15
|
+
Contexts have attribute settings located at .<setting> and so long as this setting does not begin with _ it will be
|
16
|
+
reloaded when .setting() is called for the given attribute. This should be called by code that intends access
|
17
|
+
an attribute even if it was already called.
|
18
|
+
"""
|
19
|
+
|
20
|
+
def __init__(self, kernel: "Kernel", path: str):
|
21
|
+
self._kernel = kernel
|
22
|
+
self._path = path
|
23
|
+
self._state = "unknown"
|
24
|
+
self.opened = {}
|
25
|
+
|
26
|
+
def __repr__(self):
|
27
|
+
return f"Context('{self._path}')"
|
28
|
+
|
29
|
+
def __call__(self, data: str, **kwargs):
|
30
|
+
if len(data) and data[-1] != "\n":
|
31
|
+
data += "\n"
|
32
|
+
return self._kernel.console(data)
|
33
|
+
|
34
|
+
# ==========
|
35
|
+
# PATH INFORMATION
|
36
|
+
# ==========
|
37
|
+
|
38
|
+
def abs_path(self, subpath: str) -> str:
|
39
|
+
"""
|
40
|
+
The absolute path function determines the absolute path of the given subpath within the current path of the
|
41
|
+
context.
|
42
|
+
|
43
|
+
@param subpath: relative path to the path at this context
|
44
|
+
@return:
|
45
|
+
"""
|
46
|
+
subpath = str(subpath)
|
47
|
+
if subpath.startswith("/"):
|
48
|
+
return subpath[1:]
|
49
|
+
if self._path is None or self._path == "/":
|
50
|
+
return subpath
|
51
|
+
return f"{self._path}/{subpath}"
|
52
|
+
|
53
|
+
def derive(self, path: str) -> "Context":
|
54
|
+
"""
|
55
|
+
Derive a subpath context.
|
56
|
+
|
57
|
+
@param path:
|
58
|
+
@return:
|
59
|
+
"""
|
60
|
+
return self._kernel.get_context(self.abs_path(path))
|
61
|
+
|
62
|
+
@property
|
63
|
+
def root(self) -> "Context":
|
64
|
+
return self.get_context("/")
|
65
|
+
|
66
|
+
@property
|
67
|
+
def path(self) -> str:
|
68
|
+
return self._path
|
69
|
+
|
70
|
+
@property
|
71
|
+
def kernel(self) -> "Kernel":
|
72
|
+
return self._kernel
|
73
|
+
|
74
|
+
@property
|
75
|
+
def _(self):
|
76
|
+
return self._kernel.translation
|
77
|
+
|
78
|
+
def get_context(self, path) -> "Context":
|
79
|
+
"""
|
80
|
+
Get a context at a given path location.
|
81
|
+
|
82
|
+
@param path: path location to get a context.
|
83
|
+
@return:
|
84
|
+
"""
|
85
|
+
return self._kernel.get_context(path)
|
86
|
+
|
87
|
+
def subpaths(self) -> Generator["Context", None, None]:
|
88
|
+
"""
|
89
|
+
Generate all subpaths of the current context with their path name and the relevant context.
|
90
|
+
"""
|
91
|
+
for e in list(self._kernel.contexts):
|
92
|
+
if e.startswith(self._path):
|
93
|
+
yield e, self._kernel.contexts[e]
|
94
|
+
|
95
|
+
def close_subpaths(self) -> None:
|
96
|
+
"""
|
97
|
+
Find all subpaths of the current context and delete them.
|
98
|
+
|
99
|
+
This is not a maintenance operation. It's needed for rare instances during shutdown. All contexts will be
|
100
|
+
shutdown, this prevents normal shutdown procedure.
|
101
|
+
"""
|
102
|
+
for e in list(self._kernel.contexts):
|
103
|
+
if e.startswith(self._path):
|
104
|
+
del self._kernel.contexts[e]
|
105
|
+
|
106
|
+
def destroy(self):
|
107
|
+
self.clear_persistent()
|
108
|
+
self.close_subpaths()
|
109
|
+
|
110
|
+
# ==========
|
111
|
+
# PERSISTENT SETTINGS.
|
112
|
+
# ==========
|
113
|
+
|
114
|
+
def setting(self, setting_type, key, default=None) -> Any:
|
115
|
+
"""
|
116
|
+
Registers a setting to be used between modules.
|
117
|
+
|
118
|
+
If the setting exists, its value remains unchanged.
|
119
|
+
If the setting exists in the persistent storage that value is used.
|
120
|
+
If there is no settings value, the default will be used.
|
121
|
+
|
122
|
+
@param setting_type: int, float, str, bool, list or tuple value
|
123
|
+
@param key: name of the setting
|
124
|
+
@param default: default value for the setting to have.
|
125
|
+
@return: load_value
|
126
|
+
"""
|
127
|
+
if hasattr(self, key) and getattr(self, key) is not None:
|
128
|
+
return getattr(self, key)
|
129
|
+
|
130
|
+
# Key is not located in the attr. Load the value.
|
131
|
+
if not key.startswith("_"):
|
132
|
+
load_value = self._kernel.read_persistent(
|
133
|
+
setting_type, self._path, key, default
|
134
|
+
)
|
135
|
+
else:
|
136
|
+
load_value = default
|
137
|
+
if load_value is not None and not isinstance(load_value, setting_type):
|
138
|
+
load_value = setting_type(load_value)
|
139
|
+
setattr(self, key, load_value)
|
140
|
+
return load_value
|
141
|
+
|
142
|
+
def flush(self) -> None:
|
143
|
+
"""
|
144
|
+
Commit any and all values currently stored as attr for this object to persistent storage.
|
145
|
+
"""
|
146
|
+
self._kernel.write_persistent_attributes(self._path, self)
|
147
|
+
|
148
|
+
def write_persistent_attributes(self, obj: Any) -> None:
|
149
|
+
"""
|
150
|
+
Writes values of the object's attributes at this context
|
151
|
+
@param obj:
|
152
|
+
@return:
|
153
|
+
"""
|
154
|
+
self._kernel.write_persistent_attributes(self._path, obj)
|
155
|
+
|
156
|
+
def read_persistent(self, t: type, key: str) -> Any:
|
157
|
+
"""
|
158
|
+
Gets a specific value of the persistent attributes.
|
159
|
+
|
160
|
+
The attribute type of the value depends on the provided object value default values.
|
161
|
+
|
162
|
+
@param t: type of value
|
163
|
+
@param key: relative key
|
164
|
+
@return: the value associated with the key otherwise None
|
165
|
+
"""
|
166
|
+
return self._kernel.read_persistent(t, self._path, key)
|
167
|
+
|
168
|
+
def read_persistent_attributes(self, obj: Any) -> None:
|
169
|
+
"""
|
170
|
+
Loads values of the persistent attributes, at this context and assigns them to the provided object.
|
171
|
+
|
172
|
+
The attribute type of the value depends on the provided object value default values.
|
173
|
+
|
174
|
+
@param obj:
|
175
|
+
@return:
|
176
|
+
"""
|
177
|
+
self._kernel.read_persistent_attributes(self._path, obj)
|
178
|
+
|
179
|
+
def read_persistent_string_dict(
|
180
|
+
self, dictionary: Optional[Dict] = None, suffix: bool = False
|
181
|
+
) -> Dict:
|
182
|
+
"""
|
183
|
+
Delegate to kernel to get a local string of dictionary values.
|
184
|
+
|
185
|
+
@param dictionary: optional dictionary to be updated with values
|
186
|
+
@param suffix:
|
187
|
+
@return:
|
188
|
+
"""
|
189
|
+
return self._kernel.read_persistent_string_dict(
|
190
|
+
self._path, dictionary=dictionary, suffix=suffix
|
191
|
+
)
|
192
|
+
|
193
|
+
def clear_persistent(self) -> None:
|
194
|
+
"""
|
195
|
+
Delegate to Kernel to clear the persistent settings located at this context.
|
196
|
+
"""
|
197
|
+
self._kernel.clear_persistent(self._path)
|
198
|
+
|
199
|
+
def write_persistent(
|
200
|
+
self, key: str, value: Union[int, float, str, bool, list, tuple]
|
201
|
+
) -> None:
|
202
|
+
"""
|
203
|
+
Delegate to Kernel to write the given key at this context to persistent settings. This is typically done during
|
204
|
+
shutdown but there are a variety of reasons to force this call early.
|
205
|
+
|
206
|
+
If the persistence object is not yet established this function cannot succeed.
|
207
|
+
"""
|
208
|
+
self._kernel.write_persistent(self._path, key, value)
|
209
|
+
|
210
|
+
# ==========
|
211
|
+
# DELEGATES
|
212
|
+
# ==========
|
213
|
+
|
214
|
+
def register(self, path: str, obj: Any) -> None:
|
215
|
+
"""
|
216
|
+
Delegate to Kernel
|
217
|
+
"""
|
218
|
+
self._kernel.register(path, obj)
|
219
|
+
|
220
|
+
def unregister(self, path: str) -> None:
|
221
|
+
"""
|
222
|
+
Delegate to Kernel
|
223
|
+
"""
|
224
|
+
self._kernel.unregister(path)
|
225
|
+
|
226
|
+
def console_argument(self, *args, **kwargs) -> Callable:
|
227
|
+
"""
|
228
|
+
Delegate to Kernel
|
229
|
+
|
230
|
+
Uses current context to be passed to the console_argument being registered.
|
231
|
+
"""
|
232
|
+
return self._kernel.console_argument(*args, **kwargs)
|
233
|
+
|
234
|
+
def console_option(self, *args, **kwargs) -> Callable:
|
235
|
+
"""
|
236
|
+
Delegate to Kernel
|
237
|
+
|
238
|
+
Uses current context to be passed to the console_option being registered.
|
239
|
+
"""
|
240
|
+
return self._kernel.console_option(*args, **kwargs)
|
241
|
+
|
242
|
+
def console_command(self, *args, **kwargs) -> Callable:
|
243
|
+
"""
|
244
|
+
Delegate to Kernel
|
245
|
+
|
246
|
+
Uses current context to be passed to the console_command being registered.
|
247
|
+
"""
|
248
|
+
return self._kernel.console_command(*args, **kwargs)
|
249
|
+
|
250
|
+
def console_command_remove(self, *args, **kwargs) -> Callable:
|
251
|
+
"""
|
252
|
+
Delegate to Kernel
|
253
|
+
|
254
|
+
Uses current context to be passed to the console_command being removed.
|
255
|
+
"""
|
256
|
+
return self._kernel.console_command_remove(*args, **kwargs)
|
257
|
+
|
258
|
+
@property
|
259
|
+
def contexts(self) -> Dict[str, "Context"]:
|
260
|
+
return self._kernel.contexts
|
261
|
+
|
262
|
+
def has_feature(self, feature: str) -> bool:
|
263
|
+
"""
|
264
|
+
Return whether this is a registered feature within the kernel.
|
265
|
+
|
266
|
+
@param feature: feature to check if exists in kernel.
|
267
|
+
@return:
|
268
|
+
"""
|
269
|
+
return self.lookup(feature) is not None
|
270
|
+
|
271
|
+
def find(self, *args):
|
272
|
+
"""
|
273
|
+
Delegate of Kernel match.
|
274
|
+
|
275
|
+
@param args: arguments to be delegated
|
276
|
+
:yield: matched entries.
|
277
|
+
"""
|
278
|
+
yield from self._kernel.find(*args)
|
279
|
+
|
280
|
+
def match(self, matchtext: str, suffix: bool = False) -> Generator[str, None, None]:
|
281
|
+
"""
|
282
|
+
Delegate of Kernel match.
|
283
|
+
|
284
|
+
@param matchtext: regex matchtext to locate.
|
285
|
+
@param suffix: provide the suffix of the match only.
|
286
|
+
:yield: matched entries.
|
287
|
+
"""
|
288
|
+
yield from self._kernel.match(matchtext, suffix)
|
289
|
+
|
290
|
+
def lookup(self, *args) -> Any:
|
291
|
+
"""
|
292
|
+
Lookup a value in the kernel or services.
|
293
|
+
|
294
|
+
@param args: arguments
|
295
|
+
@return:
|
296
|
+
"""
|
297
|
+
return self._kernel.lookup(*args)
|
298
|
+
|
299
|
+
def lookup_all(self, *args) -> Any:
|
300
|
+
"""
|
301
|
+
Lookup all matching values in the kernel or services.
|
302
|
+
|
303
|
+
@param args: arguments
|
304
|
+
@return:
|
305
|
+
"""
|
306
|
+
yield from self._kernel.lookup_all(*args)
|
307
|
+
|
308
|
+
def console(self, data: str) -> None:
|
309
|
+
"""
|
310
|
+
Call the Kernel's Console with the given data.
|
311
|
+
|
312
|
+
Note: '\n' is usually used to execute these functions and this is not added by default.
|
313
|
+
"""
|
314
|
+
self._kernel.console(data)
|
315
|
+
|
316
|
+
def schedule(self, job: Union["Job", Any]) -> None:
|
317
|
+
"""
|
318
|
+
Call the Kernel's Scheduler with the given job.
|
319
|
+
"""
|
320
|
+
self._kernel.schedule(job)
|
321
|
+
|
322
|
+
def unschedule(self, job: Union["Job", Any]) -> None:
|
323
|
+
"""
|
324
|
+
Unschedule a given job.
|
325
|
+
|
326
|
+
This is often unneeded if the job completes on its own, it will be removed from the scheduler.
|
327
|
+
"""
|
328
|
+
self._kernel.unschedule(job)
|
329
|
+
|
330
|
+
def threaded(
|
331
|
+
self,
|
332
|
+
func: Callable,
|
333
|
+
*args,
|
334
|
+
thread_name: str = None,
|
335
|
+
result: Callable = None,
|
336
|
+
daemon: bool = False,
|
337
|
+
):
|
338
|
+
"""
|
339
|
+
Calls a thread to be registered in the kernel.
|
340
|
+
|
341
|
+
Registered threads must complete before shutdown can be completed. These will be told to stop and waited on until
|
342
|
+
completion.
|
343
|
+
|
344
|
+
The result function will be called with any returned result func.
|
345
|
+
"""
|
346
|
+
return self._kernel.threaded(
|
347
|
+
func,
|
348
|
+
*args,
|
349
|
+
thread_name=thread_name,
|
350
|
+
result=result,
|
351
|
+
daemon=daemon,
|
352
|
+
)
|
353
|
+
|
354
|
+
# ==========
|
355
|
+
# MODULES
|
356
|
+
# ==========
|
357
|
+
|
358
|
+
def get_open(self, path: str) -> Union["Module", None]:
|
359
|
+
"""
|
360
|
+
Finds a loaded instance. Or returns None if not such instance.
|
361
|
+
|
362
|
+
Note: 'name' is not necessarily the type of instance. It could be the named value of the instance.
|
363
|
+
|
364
|
+
@param path: The opened path to find the given instance.
|
365
|
+
@return: The instance, if found, otherwise None.
|
366
|
+
"""
|
367
|
+
try:
|
368
|
+
return self.opened[path]
|
369
|
+
except KeyError:
|
370
|
+
return None
|
371
|
+
|
372
|
+
def open(self, registered_path: str, *args, **kwargs) -> "Module":
|
373
|
+
"""
|
374
|
+
Opens a registered module with the same instance path as the registered path.
|
375
|
+
|
376
|
+
This is fairly standard but should not be used if the goal would be to open the same module several times.
|
377
|
+
Unless those modules are being opened at different contexts.
|
378
|
+
|
379
|
+
@param registered_path: registered path of the given module.
|
380
|
+
@param args: args to open the module with.
|
381
|
+
@param kwargs: kwargs to open the module with.
|
382
|
+
@return:
|
383
|
+
"""
|
384
|
+
return self.open_as(registered_path, registered_path, *args, **kwargs)
|
385
|
+
|
386
|
+
def open_as(
|
387
|
+
self, registered_path: str, instance_path: str, *args, **kwargs
|
388
|
+
) -> "Module":
|
389
|
+
"""
|
390
|
+
Opens a registered module. If that module already exists it returns the already open module.
|
391
|
+
|
392
|
+
Instance_name is the name under which this given module is opened.
|
393
|
+
|
394
|
+
If the module already exists, the restore function is called on that object (if restore() exists), with the same
|
395
|
+
args and kwargs that were intended for the init() routine.
|
396
|
+
|
397
|
+
@param registered_path: path of object being opened.
|
398
|
+
@param instance_path: instance_path of object.
|
399
|
+
@param args: Args to pass to newly opened module.
|
400
|
+
@param kwargs: Kwargs to pass to newly opened module.
|
401
|
+
@return: Opened module.
|
402
|
+
"""
|
403
|
+
try:
|
404
|
+
find = self.opened[instance_path]
|
405
|
+
try:
|
406
|
+
# Module found, attempt restore call.
|
407
|
+
find.restore(*args, **kwargs)
|
408
|
+
except AttributeError:
|
409
|
+
pass
|
410
|
+
return find
|
411
|
+
except KeyError:
|
412
|
+
# Module not found.
|
413
|
+
pass
|
414
|
+
|
415
|
+
open_object = self._kernel.lookup(registered_path)
|
416
|
+
if open_object is None:
|
417
|
+
raise ValueError
|
418
|
+
|
419
|
+
instance = open_object(self, instance_path, *args, **kwargs)
|
420
|
+
instance.registered_path = registered_path
|
421
|
+
self._module_delegate(instance)
|
422
|
+
|
423
|
+
# Call module_open lifecycle event.
|
424
|
+
self.kernel.set_module_lifecycle(instance, LIFECYCLE_MODULE_OPENED)
|
425
|
+
|
426
|
+
return instance
|
427
|
+
|
428
|
+
def _module_delegate(self, module, model=None, add=True):
|
429
|
+
"""
|
430
|
+
Recursively find any delegates for a module yielded under `.delegate()`
|
431
|
+
@param module:
|
432
|
+
@param model:
|
433
|
+
@param add:
|
434
|
+
@return:
|
435
|
+
"""
|
436
|
+
kernel = self.kernel
|
437
|
+
if model is None:
|
438
|
+
model = module
|
439
|
+
|
440
|
+
try:
|
441
|
+
if model is not module:
|
442
|
+
# We are the model we don't delegate to it.
|
443
|
+
if add:
|
444
|
+
kernel.add_delegate(model, module)
|
445
|
+
else:
|
446
|
+
kernel.remove_delegate(model, module)
|
447
|
+
for delegate in model.delegates():
|
448
|
+
self._module_delegate(module=module, model=delegate, add=add)
|
449
|
+
except AttributeError:
|
450
|
+
pass
|
451
|
+
|
452
|
+
def close(self, instance_path: str, *args, **kwargs) -> None:
|
453
|
+
"""
|
454
|
+
Closes an opened module instance. Located at the instance_path location.
|
455
|
+
|
456
|
+
This calls the close() function on the object (which may not exist). Then calls module_close() on the module,
|
457
|
+
which should exist.
|
458
|
+
|
459
|
+
@param instance_path: Instance path to close.
|
460
|
+
@return:
|
461
|
+
"""
|
462
|
+
try:
|
463
|
+
instance = self.opened[instance_path]
|
464
|
+
except KeyError:
|
465
|
+
return # Nothing to close.
|
466
|
+
# Call module_close lifecycle event.
|
467
|
+
self.kernel.set_module_lifecycle(instance, LIFECYCLE_MODULE_CLOSED)
|
468
|
+
|
469
|
+
# ==========
|
470
|
+
# SIGNALS DELEGATES
|
471
|
+
# ==========
|
472
|
+
|
473
|
+
def signal(self, code: str, *message) -> None:
|
474
|
+
"""
|
475
|
+
Send Signal to all registered listeners.
|
476
|
+
|
477
|
+
@param code: Code to delegate at this given context location.
|
478
|
+
@param message: Message to send.
|
479
|
+
@return:
|
480
|
+
"""
|
481
|
+
self._kernel.signal(code, self._path, *message)
|
482
|
+
|
483
|
+
def last_signal(self, signal: str) -> Tuple:
|
484
|
+
"""
|
485
|
+
Returns the last signal payload at the given code.
|
486
|
+
|
487
|
+
@param signal: Code to delegate at this given context location.
|
488
|
+
@return: message value of the last signal sent for that code.
|
489
|
+
"""
|
490
|
+
return self._kernel.last_signal(signal)
|
491
|
+
|
492
|
+
def listen(
|
493
|
+
self,
|
494
|
+
signal: str,
|
495
|
+
process: Callable,
|
496
|
+
lifecycle_object: Union["Service", "Module", None] = None,
|
497
|
+
) -> None:
|
498
|
+
"""
|
499
|
+
Listen at a particular signal with a given process.
|
500
|
+
|
501
|
+
@param signal: Signal code to listen for
|
502
|
+
@param process: listener to be attached
|
503
|
+
@param lifecycle_object: Object to use as a cookie to bind the listener.
|
504
|
+
@return:
|
505
|
+
"""
|
506
|
+
self._kernel.listen(signal, process, lifecycle_object)
|
507
|
+
|
508
|
+
def unlisten(self, signal: str, process: Callable):
|
509
|
+
"""
|
510
|
+
Unlisten to a particular signal with a given process.
|
511
|
+
|
512
|
+
This should be called on the ending of the lifecycle of whatever process listened to the given signal.
|
513
|
+
|
514
|
+
@param signal: Signal to unlisten for.
|
515
|
+
@param process: listener that is to be detached.
|
516
|
+
@return:
|
517
|
+
"""
|
518
|
+
self._kernel.unlisten(signal, process)
|
519
|
+
|
520
|
+
# ==========
|
521
|
+
# CHANNEL DELEGATES
|
522
|
+
# ==========
|
523
|
+
|
524
|
+
def channel(self, channel: str, *args, **kwargs) -> "Channel":
|
525
|
+
"""
|
526
|
+
Return a channel from the kernel location
|
527
|
+
|
528
|
+
@param channel: Channel to be opened.
|
529
|
+
@return: Channel object that is opened.
|
530
|
+
"""
|
531
|
+
return self._kernel.channel(channel, *args, **kwargs)
|
532
|
+
|
533
|
+
def console_function(self, data: str) -> "ConsoleFunction":
|
534
|
+
"""
|
535
|
+
Returns a function that calls a console command. This serves as a Job to be used in Scheduler or simply a
|
536
|
+
function with the command as the str form.
|
537
|
+
"""
|
538
|
+
return ConsoleFunction(self, data)
|