src/eric7/MicroPython/Devices/DeviceBase.py

branch
eric7
changeset 11190
f5ffdf0164ab
parent 11186
c2d18aefef6b
child 11219
72ff8c49919e
diff -r 289c7150ec4b -r f5ffdf0164ab src/eric7/MicroPython/Devices/DeviceBase.py
--- a/src/eric7/MicroPython/Devices/DeviceBase.py	Mon Mar 24 14:16:32 2025 +0100
+++ b/src/eric7/MicroPython/Devices/DeviceBase.py	Wed Mar 26 19:46:41 2025 +0100
@@ -11,6 +11,7 @@
 import ast
 import contextlib
 import copy
+import hashlib
 import os
 import time
 
@@ -924,7 +925,6 @@
         @rtype bool
         @exception OSError raised to indicate an issue with the device
         """
-        # TODO: micro:bit with old MPy does not support leading '/'
         if not deviceFileName:
             raise OSError("Missing device file name")
 
@@ -987,7 +987,6 @@
         @rtype bytes
         @exception OSError raised to indicate an issue with the device
         """
-        # TODO: micro:bit with old MPy does not support leading '/'
         if not deviceFileName:
             raise OSError("Missing device file name")
 
@@ -1029,6 +1028,118 @@
 
         return out
 
+    def touch(self, deviceFileName):
+        """
+        Public method to touch a file on the connected device.
+
+        @param deviceFileName name of the file to be touched
+        @type str
+        @exception OSError raised to indicate an issue with the device
+        """
+        if not deviceFileName:
+            raise OSError("Missing device file name")
+
+        command = """
+def touch():
+    f = open('{0}', 'a')
+    f.close()
+
+touch()
+del touch
+""".format(
+            deviceFileName
+        )
+        out, err = self.executeCommands(command, mode=self._submitMode)
+        if err:
+            raise OSError(self._shortError(err))
+
+    def __supportsHash(self, algorithm):
+        """
+        Private method to sheck, if the connected device supports hashing with
+        the hashlib module and the given algorithm.
+
+        @param algorithm hashing algorithm to be used
+        @type str
+        @return flag indicating hashing support
+        @rtype bool
+        """
+        command = """
+def supportsHash():
+    try:
+        import hashlib
+    except ImportError:
+        return 'False - hashlib not available'
+    try:
+        h = hashlib.{0}()
+    except AttributeError:
+        return 'False - hashlib.{0} not supported'
+
+    return 'True'
+
+print(supportsHash())
+del supportsHash
+""".format(
+            algorithm
+        )
+
+        out, err = self.executeCommands(command, mode=self._submitMode)
+        if err:
+            return False
+
+        return out.decode("utf-8").strip() == "True"
+
+    def hash(self, deviceFileName, algorithm="sha256", chunkSize=256):
+        """
+        Public method to calculate the hash value of a file on the connected device.
+
+        @param deviceFileName name of the file to be touched
+        @type str
+        @param algorithm hashing algorithm to be used (defaults to "sha256")
+        @type str (optional)
+        @param chunkSize size of data chunks to be sent to the algorithm
+            (defaults to 256)
+        @type int (optional)
+        @return calculate hash digest
+        @rtype bytes
+        @exception OSError raised to indicate an issue with the device
+        """
+        if not deviceFileName:
+            raise OSError("Missing device file name")
+
+        command = """
+def hash():
+    import hashlib
+
+    h = hashlib.{1}()
+    buf = memoryview(bytearray({2}))
+    with open('{0}', 'rb') as f:
+        while True:
+            n = f.readinto(buf)
+            if n == 0:
+                break
+            h.update(buf if n == {2} else buf[:n])
+
+    return h.digest()
+
+print(hash())
+del hash
+""".format(
+            deviceFileName, algorithm, chunkSize
+        )
+
+        if self.__supportsHash(algorithm=algorithm):
+            out, err = self.executeCommands(command, mode=self._submitMode)
+            if err:
+                raise OSError(self._shortError(err))
+            digest = ast.literal_eval(out.decode("utf-8"))
+        else:
+            # The board does not support hash calculation. Get the data and do
+            # the calculation locally.
+            data = self.getData(deviceFileName=deviceFileName)
+            digest = getattr(hashlib, algorithm)(data).digest()
+
+        return digest
+
     def fileSystemInfo(self):
         """
         Public method to obtain information about the currently mounted file

eric ide

mercurial