From 3ff7197077a192382557896e9a3c4bb7784eb436 Mon Sep 17 00:00:00 2001 From: Neradoc Date: Mon, 20 Jun 2022 00:27:41 +0200 Subject: [PATCH 1/2] detect bad mpy files and suggest replacing them --- circup/__init__.py | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/circup/__init__.py b/circup/__init__.py index d0e128b..8defc38 100644 --- a/circup/__init__.py +++ b/circup/__init__.py @@ -61,6 +61,8 @@ PLATFORMS = {"py": "py", "7mpy": "7.x-mpy", "8mpy": "7.x-mpy"} #: Commands that do not require an attached board BOARDLESS_COMMANDS = ["show", "bundle-add", "bundle-remove", "bundle-show"] +#: Version identifier for a bad MPY file format +BAD_FILE_FORMAT = "Bad format" # Ensure DATA_DIR / LOG_DIR related directories and files exist. if not os.path.exists(DATA_DIR): # pragma: no cover @@ -296,6 +298,11 @@ def outofdate(self): logger.warning(ex) return True # Assume out of date to try to update. + @property + def bad_format(self): + """A boolean indicating that the mpy file format could not be identified""" + return self.mpy and self.device_version == BAD_FILE_FORMAT + @property def mpy_mismatch(self): """ @@ -524,6 +531,7 @@ def extract_metadata(path): # Track the MPY version number mpy_version = content[0:2] compatibility = None + loc = -1 # Find the start location of the __version__ if mpy_version == b"M\x03": # One byte for the length of "__version__" @@ -546,11 +554,14 @@ def extract_metadata(path): end = loc # Up to the start of the __version__. version = content[start:end] # Slice the version number. # Create a string version as metadata in the result. - result = {"__version__": version.decode("utf-8"), "mpy": True} + result["__version__"] = version.decode("utf-8") break # Nothing more to do. offset += 1 # ...and again but backtrack by one. if compatibility: result["compatibility"] = compatibility + else: + # not a valid MPY file + result["__version__"] = BAD_FILE_FORMAT return result @@ -946,19 +957,20 @@ def get_modules(path): result[os.path.basename(sfm).replace(".py", "").replace(".mpy", "")] = metadata for dm in directory_mods: name = os.path.basename(os.path.dirname(dm)) - metadata = {} py_files = glob.glob(os.path.join(dm, "*.py")) mpy_files = glob.glob(os.path.join(dm, "*.mpy")) all_files = py_files + mpy_files + # default value + result[name] = {"path": dm, "mpy": bool(mpy_files)} + # explore all the submodules to detect bad ones for source in [f for f in all_files if not os.path.basename(f).startswith(".")]: metadata = extract_metadata(source) if "__version__" in metadata: metadata["path"] = dm result[name] = metadata - break - else: - # No version metadata found. - result[name] = {"path": dm, "mpy": bool(mpy_files)} + # break now if any of the submodules has a bad format + if metadata["__version__"] == BAD_FILE_FORMAT: + break return result @@ -1375,6 +1387,9 @@ def uninstall(ctx, module): # pragma: no cover click.echo("Module '{}' not found on device.".format(name)) +# pylint: disable=too-many-branches + + @main.command( short_help=( "Update modules on the device. " @@ -1421,7 +1436,14 @@ def update(ctx, all): # pragma: no cover if module.repo: click.secho(f"\t{module.repo}", fg="yellow") if not update_flag: - if module.mpy_mismatch: + if module.bad_format: + click.secho( + f"WARNING: '{module.name}': module corrupted or in an" + "unknown mpy format. Updating is required.", + fg="yellow", + ) + update_flag = click.confirm("Do you want to update?") + elif module.mpy_mismatch: click.secho( f"WARNING: '{module.name}': mpy format doesn't match the" " device's Circuitpython version. Updating is required.", @@ -1452,6 +1474,9 @@ def update(ctx, all): # pragma: no cover click.echo("None of the modules found on the device need an update.") +# pylint: enable=too-many-branches + + @main.command("bundle-show") @click.option("--modules", is_flag=True, help="List all the modules per bundle.") def bundle_show(modules): From 41c36cb368783d7deeebb8aa17bc830d34bd24be Mon Sep 17 00:00:00 2001 From: Neradoc Date: Tue, 5 Jul 2022 03:26:25 +0200 Subject: [PATCH 2/2] change Bad format to Invalid --- circup/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/circup/__init__.py b/circup/__init__.py index 8defc38..5681fc1 100644 --- a/circup/__init__.py +++ b/circup/__init__.py @@ -62,7 +62,7 @@ #: Commands that do not require an attached board BOARDLESS_COMMANDS = ["show", "bundle-add", "bundle-remove", "bundle-show"] #: Version identifier for a bad MPY file format -BAD_FILE_FORMAT = "Bad format" +BAD_FILE_FORMAT = "Invalid" # Ensure DATA_DIR / LOG_DIR related directories and files exist. if not os.path.exists(DATA_DIR): # pragma: no cover @@ -1439,7 +1439,7 @@ def update(ctx, all): # pragma: no cover if module.bad_format: click.secho( f"WARNING: '{module.name}': module corrupted or in an" - "unknown mpy format. Updating is required.", + " unknown mpy format. Updating is required.", fg="yellow", ) update_flag = click.confirm("Do you want to update?")