micrOSDevToolKit 2.11.0__py3-none-any.whl → 2.13.1__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.

Potentially problematic release.


This version of micrOSDevToolKit might be problematic. Click here for more details.

Files changed (85) hide show
  1. micrOS/release_info/micrOS_ReleaseInfo/system_analysis_sum.json +25 -25
  2. micrOS/source/Common.py +34 -14
  3. micrOS/source/Config.py +7 -7
  4. micrOS/source/Debug.py +9 -9
  5. micrOS/source/Espnow.py +6 -6
  6. micrOS/source/Files.py +5 -3
  7. micrOS/source/Hooks.py +5 -5
  8. micrOS/source/InterConnect.py +5 -5
  9. micrOS/source/Interrupts.py +2 -2
  10. micrOS/source/LM_dashboard_be.py +2 -2
  11. micrOS/source/LM_neomatrix.py +42 -12
  12. micrOS/source/LM_pacman.py +16 -3
  13. micrOS/source/Logger.py +1 -1
  14. micrOS/source/Network.py +6 -6
  15. micrOS/source/Notify.py +2 -2
  16. micrOS/source/Scheduler.py +5 -5
  17. micrOS/source/Server.py +6 -6
  18. micrOS/source/Shell.py +4 -4
  19. micrOS/source/Tasks.py +13 -13
  20. micrOS/source/Time.py +7 -7
  21. micrOS/source/Types.py +2 -2
  22. micrOS/source/Web.py +20 -13
  23. micrOS/source/__pycache__/Common.cpython-312.pyc +0 -0
  24. micrOS/source/__pycache__/Debug.cpython-312.pyc +0 -0
  25. micrOS/source/__pycache__/Logger.cpython-312.pyc +0 -0
  26. micrOS/source/__pycache__/Server.cpython-312.pyc +0 -0
  27. micrOS/source/micrOS.py +5 -5
  28. micrOS/source/micrOSloader.py +6 -6
  29. micrOS/source/urequests.py +4 -4
  30. {microsdevtoolkit-2.11.0.dist-info → microsdevtoolkit-2.13.1.dist-info}/METADATA +23 -22
  31. {microsdevtoolkit-2.11.0.dist-info → microsdevtoolkit-2.13.1.dist-info}/RECORD +85 -80
  32. toolkit/DevEnvCompile.py +20 -15
  33. toolkit/DevEnvOTA.py +29 -8
  34. toolkit/DevEnvUSB.py +47 -10
  35. toolkit/MicrOSDevEnv.py +10 -2
  36. toolkit/MicrosFiles.py +26 -0
  37. toolkit/lib/LocalMachine.py +6 -1
  38. toolkit/lib/file_extensions.py +9 -3
  39. toolkit/lib/pip_package_installer.py +5 -2
  40. toolkit/micrOSlint.py +3 -1
  41. toolkit/workspace/precompiled/Common.cpython-312.pyc +0 -0
  42. toolkit/workspace/precompiled/Common.mpy +0 -0
  43. toolkit/workspace/precompiled/Config.mpy +0 -0
  44. toolkit/workspace/precompiled/Debug.mpy +0 -0
  45. toolkit/workspace/precompiled/Espnow.mpy +0 -0
  46. toolkit/workspace/precompiled/Files.mpy +0 -0
  47. toolkit/workspace/precompiled/Hooks.mpy +0 -0
  48. toolkit/workspace/precompiled/InterConnect.mpy +0 -0
  49. toolkit/workspace/precompiled/Interrupts.mpy +0 -0
  50. toolkit/workspace/precompiled/LM_dashboard_be.py +2 -2
  51. toolkit/workspace/precompiled/LM_neomatrix.mpy +0 -0
  52. toolkit/workspace/precompiled/LM_pacman.mpy +0 -0
  53. toolkit/workspace/precompiled/Logger.cpython-312.pyc +0 -0
  54. toolkit/workspace/precompiled/Logger.mpy +0 -0
  55. toolkit/workspace/precompiled/Network.mpy +0 -0
  56. toolkit/workspace/precompiled/Notify.mpy +0 -0
  57. toolkit/workspace/precompiled/Scheduler.mpy +0 -0
  58. toolkit/workspace/precompiled/Server.cpython-312.pyc +0 -0
  59. toolkit/workspace/precompiled/Server.mpy +0 -0
  60. toolkit/workspace/precompiled/Shell.mpy +0 -0
  61. toolkit/workspace/precompiled/Tasks.mpy +0 -0
  62. toolkit/workspace/precompiled/Time.mpy +0 -0
  63. toolkit/workspace/precompiled/Types.mpy +0 -0
  64. toolkit/workspace/precompiled/Web.mpy +0 -0
  65. toolkit/workspace/precompiled/micrOS.mpy +0 -0
  66. toolkit/workspace/precompiled/micrOSloader.mpy +0 -0
  67. toolkit/workspace/precompiled/urequests.mpy +0 -0
  68. /micrOS/source/{dashboard.html → web/dashboard.html} +0 -0
  69. /micrOS/source/{index.html → web/index.html} +0 -0
  70. /micrOS/source/{uapi.js → web/uapi.js} +0 -0
  71. /micrOS/source/{udashboard.js → web/udashboard.js} +0 -0
  72. /micrOS/source/{ustyle.css → web/ustyle.css} +0 -0
  73. /micrOS/source/{uwidgets.js → web/uwidgets.js} +0 -0
  74. /micrOS/source/{uwidgets_pro.js → web/uwidgets_pro.js} +0 -0
  75. {microsdevtoolkit-2.11.0.data → microsdevtoolkit-2.13.1.data}/scripts/devToolKit.py +0 -0
  76. {microsdevtoolkit-2.11.0.dist-info → microsdevtoolkit-2.13.1.dist-info}/WHEEL +0 -0
  77. {microsdevtoolkit-2.11.0.dist-info → microsdevtoolkit-2.13.1.dist-info}/licenses/LICENSE +0 -0
  78. {microsdevtoolkit-2.11.0.dist-info → microsdevtoolkit-2.13.1.dist-info}/top_level.txt +0 -0
  79. /toolkit/workspace/precompiled/{dashboard.html → web/dashboard.html} +0 -0
  80. /toolkit/workspace/precompiled/{index.html → web/index.html} +0 -0
  81. /toolkit/workspace/precompiled/{uapi.js → web/uapi.js} +0 -0
  82. /toolkit/workspace/precompiled/{udashboard.js → web/udashboard.js} +0 -0
  83. /toolkit/workspace/precompiled/{ustyle.css → web/ustyle.css} +0 -0
  84. /toolkit/workspace/precompiled/{uwidgets.js → web/uwidgets.js} +0 -0
  85. /toolkit/workspace/precompiled/{uwidgets_pro.js → web/uwidgets_pro.js} +0 -0
toolkit/DevEnvOTA.py CHANGED
@@ -5,22 +5,26 @@ MYPATH = os.path.dirname(__file__)
5
5
  print("Module [DevEnvOTA] path: {} __package__: {} __name__: {} __file__: {}".format(
6
6
  sys.path[0], __package__, __name__, MYPATH))
7
7
 
8
+ from pprint import pprint
9
+
8
10
  try:
9
11
  from .DevEnvCompile import Compile
10
12
  from . import socketClient
11
13
  from .lib import LocalMachine
12
14
  from .lib.TerminalColors import Colors
13
15
  from .lib.SafeInput import input_with_timeout
14
- from .lib.file_extensions import check_all_extensions
16
+ from .lib.file_extensions import check_all_extensions, check_web_extensions, check_python_extensions
15
17
  from .lib.Repository import git_clone_archive, git_clone
18
+ from .MicrosFiles import micros_resource_list
16
19
  except Exception as e:
17
20
  print("Import warning __name__:{}: {}".format(__name__, e))
18
21
  from DevEnvCompile import Compile
19
22
  from lib import LocalMachine
20
23
  from lib.TerminalColors import Colors
21
24
  from lib.SafeInput import input_with_timeout
22
- from lib.file_extensions import check_all_extensions
25
+ from lib.file_extensions import check_all_extensions, check_web_extensions, check_python_extensions
23
26
  from lib.Repository import git_clone_archive, git_clone
27
+ from MicrosFiles import micros_resource_list
24
28
 
25
29
  sys.path.append(MYPATH)
26
30
  import socketClient
@@ -241,9 +245,9 @@ class OTA(Compile):
241
245
  self.console(" loader update: {}".format(force_mode), state='OK')
242
246
 
243
247
  # Parse files from precompiled dir
244
- resource_list_to_upload = [os.path.join(self.precompiled_micrOS_dir_path, pysource) for pysource in
245
- LocalMachine.FileHandler.list_dir(self.precompiled_micrOS_dir_path)
246
- if check_all_extensions(pysource)]
248
+ resource_list_to_upload, dir_list_to_create = micros_resource_list(self.precompiled_micrOS_dir_path)
249
+ # LIMITATION: WEBREPL Cannot create directories with remote command...
250
+
247
251
  # Apply upload settings on parsed resources
248
252
  for index, source in enumerate(resource_list_to_upload):
249
253
  source_name = os.path.basename(source)
@@ -268,7 +272,8 @@ class OTA(Compile):
268
272
  # Add source to upload
269
273
  upload_path_list.append(source)
270
274
  # Upload files / sources
271
- return self.ota_webrepl_update_core(device, upload_path_list=upload_path_list, ota_password=webrepl_password)
275
+ return self.ota_webrepl_update_core(device, upload_path_list=upload_path_list,
276
+ ota_password=webrepl_password, upload_root_dir=self.precompiled_micrOS_dir_path)
272
277
 
273
278
  def _enable_micros_ota_update_via_webrepl(self, device=None, ota_password=None):
274
279
  # Get specific device from device list
@@ -401,7 +406,8 @@ class OTA(Compile):
401
406
  print(f"[SIM] 'OTA' COPY FILES... {source} -> {target}")
402
407
  LocalMachine.FileHandler().copy(source, target)
403
408
 
404
- def ota_webrepl_update_core(self, device=None, upload_path_list=[], ota_password='ADmin123', force_lm=False):
409
+ def ota_webrepl_update_core(self, device=None, upload_path_list=None, ota_password='ADmin123',
410
+ force_lm=False, upload_root_dir=None):
405
411
  """
406
412
  Generic file uploader for micrOS - over webrepl
407
413
  info: https://techoverflow.net/2020/02/22/how-to-upload-files-to-micropython-using-webrepl-using-webrepl_cli-py/
@@ -410,7 +416,11 @@ class OTA(Compile):
410
416
  upload_path_list: file path list to upload
411
417
  ota_password - accessing webrepl to upload files
412
418
  force_lm - use prefix as 'LM_' for every file - for user file upload / GUI drag n drop
419
+ upload_root_dir - root directory to upload files (subdir support)
413
420
  """
421
+ if upload_path_list is None:
422
+ upload_path_list = []
423
+
414
424
  if device[0] == "__simulator__":
415
425
  OTA.sim_ota_update(upload_path_list, force_lm)
416
426
  return
@@ -457,7 +467,18 @@ class OTA(Compile):
457
467
  # Copy retry mechanism
458
468
  exitcode = -1
459
469
  source_name = os.path.basename(source)
460
- source_name_target = source_name
470
+ if upload_root_dir is None:
471
+ # Drag-n-Drop file upload file type check and folder adjustment
472
+ if check_web_extensions(source_name):
473
+ source_name_target = os.path.join('web', source_name)
474
+ elif not check_python_extensions(source_name) and not source_name.endswith("node_config.json"):
475
+ source_name_target = os.path.join('data', source_name)
476
+ else:
477
+ # Copy file to micrOS root folder (.mpy and .py or node_config.json)
478
+ source_name_target = source_name
479
+ else:
480
+ # MAIN USE-CASE
481
+ source_name_target = source.replace(upload_root_dir, '')
461
482
 
462
483
  # Force LM update - user load modules - drag n drop files
463
484
  if force_lm and not source_name.startswith('LM_') and source_name.endswith('.py'):
toolkit/DevEnvUSB.py CHANGED
@@ -13,12 +13,14 @@ try:
13
13
  from .lib import LocalMachine
14
14
  from .lib.TerminalColors import Colors
15
15
  from .lib.SerialDriverHandler import install_usb_serial_driver
16
+ from .MicrosFiles import micros_resource_list
16
17
  except Exception as e:
17
18
  print("Import warning __name__:{}: {}".format(__name__, e))
18
19
  from DevEnvCompile import Compile
19
20
  from lib import LocalMachine
20
21
  from lib.TerminalColors import Colors
21
22
  from lib.SerialDriverHandler import install_usb_serial_driver
23
+ from MicrosFiles import micros_resource_list
22
24
 
23
25
 
24
26
  class USB(Compile):
@@ -207,6 +209,38 @@ class USB(Compile):
207
209
  self.console("Deployment failed.\n{} - {}".format(stdout, stderr), state='err')
208
210
  return False
209
211
 
212
+ def _mkdir_on_dev(self, folders:list):
213
+ mpremote_cmd = self.dev_types_and_cmds[self.selected_device_type]['mpremote_cmd']
214
+ device = self.get_devices()[0]
215
+ if mpremote_cmd is None:
216
+ # Legacy ampy command (esp32 auto reboot tolerance...)
217
+ mkdir_cmd = self.dev_types_and_cmds[self.selected_device_type]['ampy_cmd'].format(dev=device, args=f'mkdir')
218
+ else:
219
+ mkdir_cmd = f'{mpremote_cmd} fs mkdir'
220
+
221
+ status = 0
222
+ for folder in folders:
223
+ _mkdir_cmd = f"{mkdir_cmd} {folder}"
224
+ self.console(f"Create directory on device: {_mkdir_cmd}")
225
+ if self.dry_run:
226
+ pass
227
+ else:
228
+ try:
229
+ exitcode, stdout, stderr = LocalMachine.CommandHandler.run_command(_mkdir_cmd, shell=True)
230
+ if exitcode != 0:
231
+ verdict = stdout + stderr
232
+ if "File exists" in verdict or "Directory already exists" in verdict:
233
+ exitcode = 0
234
+ else:
235
+ self.console(f"MKDIR ERROR:\n{stdout}\n{stderr}", state="err")
236
+ except Exception as e:
237
+ self.console(f"MKDIR ERROR {_mkdir_cmd}: {e}", state="err")
238
+ exitcode = 1
239
+ status += exitcode
240
+
241
+ return True if status == 0 else False
242
+
243
+
210
244
  def put_micros_to_dev(self):
211
245
  self.select_board_n_micropython()
212
246
  status = True
@@ -223,17 +257,20 @@ class USB(Compile):
223
257
  self.console(f"... wait for reset {10-k} sec", state='imp')
224
258
  time.sleep(1)
225
259
 
226
- mpremote_cmd = self.dev_types_and_cmds[self.selected_device_type]['mpremote_cmd']
227
- device = self.get_devices()[0]
228
- source_to_put_device = LocalMachine.FileHandler.list_dir(self.precompiled_micrOS_dir_path)
260
+ # Parse micrOS resources with folders
261
+ _source_to_put_device, dir_list_to_create = micros_resource_list(self.precompiled_micrOS_dir_path)
262
+ self.console(f"CREATE FOLDERS: {dir_list_to_create}", state="ok")
263
+ # Create sub folders
264
+ if not self._mkdir_on_dev(dir_list_to_create):
265
+ self.console(f"Error creating directories on device: {dir_list_to_create}")
266
+ sys.exit(1)
267
+ # Generate resource list to be put on the device
268
+ source_to_put_device = list([s.replace(self.precompiled_micrOS_dir_path + "/", '') for s in _source_to_put_device])
229
269
  # Set source order - main, boot
230
- source_to_put_device.append(source_to_put_device.pop(source_to_put_device.index('main.py')))
231
- try:
232
- # PIP deployment generates this ...
233
- source_to_put_device.remove('__pycache__') # remove if accidentally left here
234
- except:
235
- pass
270
+ source_to_put_device.append(source_to_put_device.pop(source_to_put_device.index("main.py")))
236
271
 
272
+ mpremote_cmd = self.dev_types_and_cmds[self.selected_device_type]['mpremote_cmd']
273
+ device = self.get_devices()[0]
237
274
  # Change workdir
238
275
  workdir_handler = LocalMachine.SimplePopPushd()
239
276
  workdir_handler.pushd(self.precompiled_micrOS_dir_path)
@@ -243,7 +280,7 @@ class USB(Compile):
243
280
  self.console("[{}%] micrOS deploy via USB - {}".format(percent, device))
244
281
  if mpremote_cmd is None:
245
282
  # Legacy ampy command (esp32 auto reboot tolerance...)
246
- command = self.dev_types_and_cmds[self.selected_device_type]['ampy_cmd'].format(dev=device, args=f'put {source}')
283
+ command = self.dev_types_and_cmds[self.selected_device_type]['ampy_cmd'].format(dev=device, args=f'put {source} /{source}')
247
284
  else:
248
285
  command = f'{mpremote_cmd} fs cp {source} :{source}' # new mpremote <1.24.1
249
286
  if ' ' in source:
toolkit/MicrOSDevEnv.py CHANGED
@@ -62,8 +62,16 @@ class MicrOSDevTool(OTA, USB):
62
62
  if f.endswith('.json'):
63
63
  continue
64
64
  f_path = os.path.join(self.micrOS_dir_path, f)
65
- self.console("[SIM] Copy micrOS resources: {} -> {}".format(f_path, self.micros_sim_workspace))
66
- LocalMachine.FileHandler().copy(f_path, self.micros_sim_workspace)
65
+ if f.startswith("_") or f.startswith("."):
66
+ # SKIP files startswith `_` and `.`
67
+ continue
68
+ _, f_type = LocalMachine.FileHandler.path_is_exists(f_path)
69
+ target_dir = self.micros_sim_workspace
70
+ if f_type == "d":
71
+ target_dir = os.path.join(self.micros_sim_workspace, f)
72
+ self.console(f"[SIM] Copy micrOS resources: {f_path} -> {target_dir}")
73
+ if not LocalMachine.FileHandler().copy(f_path, target_dir):
74
+ self.console(f"[ERROR] Failed to copy: {f_path}")
67
75
 
68
76
  if prepare_only:
69
77
  # In case of automatic node_conf creation
toolkit/MicrosFiles.py ADDED
@@ -0,0 +1,26 @@
1
+ import os
2
+
3
+ try:
4
+ from .lib import LocalMachine
5
+ from .lib.file_extensions import check_all_extensions, check_web_extensions
6
+ except Exception as e:
7
+ print("Import warning __name__:{}: {}".format(__name__, e))
8
+ from lib import LocalMachine
9
+ from lib.file_extensions import check_all_extensions, check_web_extensions
10
+
11
+ def micros_resource_list(root_folder):
12
+ resources_path = []
13
+ subfolders = []
14
+ for source in LocalMachine.FileHandler.list_dir(root_folder):
15
+ source_full_path = os.path.join(root_folder, source)
16
+ # [1] / Root directory source files and folders.
17
+ if check_all_extensions(source):
18
+ resources_path.append(source_full_path)
19
+ # [2] /dir Handle sub dictionary sources
20
+ elif LocalMachine.FileHandler.path_is_exists(source_full_path)[1] == 'd':
21
+ subfolders.append(source)
22
+ for sub_source in LocalMachine.FileHandler.list_dir(source_full_path):
23
+ sub_source_full_path = os.path.join(source_full_path, sub_source)
24
+ if check_all_extensions(sub_source):
25
+ resources_path.append(sub_source_full_path)
26
+ return resources_path, subfolders
@@ -186,11 +186,13 @@ class FileHandler:
186
186
  os.remove(path)
187
187
  elif type_ == 'd':
188
188
  shutil.rmtree(path)
189
+ return True
189
190
  except Exception as e:
190
191
  if ignore:
191
192
  debug_print("[DEBUG] Removing " + path + " is forced to ignore failure: " + str(e))
192
193
  else:
193
194
  raise Exception("Cannot remove " + path + ": " + str(e))
195
+ return False
194
196
 
195
197
  @staticmethod
196
198
  def extract_tar(targz, extract_path):
@@ -210,7 +212,10 @@ class FileHandler:
210
212
  def copy(from_path, to_path):
211
213
  debug_print("[DEBUG] Copy " + from_path + " to " + to_path)
212
214
  try:
213
- shutil.copy(from_path, to_path)
215
+ if os.path.isdir(from_path):
216
+ shutil.copytree(from_path, to_path, dirs_exist_ok=True)
217
+ else:
218
+ shutil.copy(from_path, to_path)
214
219
  return True
215
220
  except Exception as e:
216
221
  debug_print("Copy error: {}".format(e))
@@ -1,7 +1,7 @@
1
1
 
2
-
3
- ENABLED_EXTENSIONS = ('py', 'mpy', 'js', 'css', 'html')
4
- WEB_ONLY = ('js', 'html', 'css')
2
+ PYTHON_EXTENSIONS = ('py', 'mpy')
3
+ WEB_ONLY = ('js', 'html', 'css', 'json', 'ico', 'jpeg', 'png')
4
+ ENABLED_EXTENSIONS = PYTHON_EXTENSIONS + WEB_ONLY
5
5
 
6
6
  def check_all_extensions(path):
7
7
  extension = path.split('.')[-1]
@@ -13,4 +13,10 @@ def check_web_extensions(path):
13
13
  extension = path.split('.')[-1]
14
14
  if extension in WEB_ONLY:
15
15
  return True
16
+ return False
17
+
18
+ def check_python_extensions(path):
19
+ extension = path.split('.')[-1]
20
+ if extension in PYTHON_EXTENSIONS:
21
+ return True
16
22
  return False
@@ -66,8 +66,11 @@ def install_package(name, additional_pip_param=None):
66
66
  print(f"{TerminalColors.Colors.OK}[PIP] install {name} OK{TerminalColors.Colors.NC}")
67
67
  else:
68
68
  print(f"{TerminalColors.Colors.WARN}[PIP] install {name} NOK{TerminalColors.Colors.NC}")
69
- # Support brew installed python
70
- if "This environment is externally managed" in out:
69
+ if "--break-system-packages" in out:
70
+ # (Retry) Support system wide package install
71
+ install_package(name, additional_pip_param="--break-system-packages")
72
+ elif "This environment is externally managed" in out:
73
+ # (Retry-Fallback) Support brew installed python
71
74
  if "brew install" in out:
72
75
  print(f"Install optional dependency (brew): {name}")
73
76
  state, out = run_subprocess(["brew", "install", name])
toolkit/micrOSlint.py CHANGED
@@ -222,7 +222,9 @@ def _run_pylint(file_name):
222
222
  '--disable=broad-exception-caught', # Disable BROAD exception
223
223
  '--disable=broad-exception-raised', # Disable BROAD exception
224
224
  '--disable=too-many-return-statements', # :D I don't think so :D
225
- '--disable=too-many-branches' # :D I don't think so :D
225
+ '--disable=too-many-branches', # :D I don't think so :D
226
+ '--disable=too-many-positional-arguments', # :D I don't think so :D
227
+ '--disable=too-many-instance-attributes' # :D I don't think so :D
226
228
  ]
227
229
  if file_name in ['Tasks.py', 'microIO.py', 'Types.py']:
228
230
  pylint_opts.append('--disable=exec-used') # Disable micrOS execution core exec/eval warning
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,4 +1,4 @@
1
- from Common import web_endpoint, syslog
1
+ from Common import web_dir, web_endpoint, syslog
2
2
 
3
3
  ENDPOINT_INITED = False
4
4
 
@@ -8,7 +8,7 @@ def load():
8
8
 
9
9
  def _dashboard_clb():
10
10
  try:
11
- with open('dashboard.html', 'r') as html:
11
+ with open(web_dir('dashboard.html'), 'r') as html:
12
12
  html_content = html.read()
13
13
  return 'text/html', html_content
14
14
  except Exception as e:
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes