eric6/MicroPython/MicroPythonFileSystem.py

branch
micropython
changeset 7088
e29b0ee86b29
parent 7084
3eddfc540614
child 7089
9f9816b19aa4
equal deleted inserted replaced
7087:2ca7fb61a82f 7088:e29b0ee86b29
18 18
19 from .MicroPythonSerialPort import MicroPythonSerialPort 19 from .MicroPythonSerialPort import MicroPythonSerialPort
20 from .MicroPythonFileSystemUtilities import ( 20 from .MicroPythonFileSystemUtilities import (
21 mtime2string, mode2string, decoratedName, listdirStat 21 mtime2string, mode2string, decoratedName, listdirStat
22 ) 22 )
23
24 import Preferences
23 25
24 26
25 class MicroPythonFileSystem(QObject): 27 class MicroPythonFileSystem(QObject):
26 """ 28 """
27 Class implementing some file system commands for MicroPython. 29 Class implementing some file system commands for MicroPython.
486 out = out.replace(b"\r", b"\n") 488 out = out.replace(b"\r", b"\n")
487 with open(hostFileName, "wb") as hostFile: 489 with open(hostFileName, "wb") as hostFile:
488 hostFile.write(out) 490 hostFile.write(out)
489 return True 491 return True
490 492
493 def fileSystemInfo(self):
494 """
495 Public method to obtain information about the currently mounted file
496 systems.
497
498 @return tuple of tuples containing the file system name, the total
499 size, the used size and the free size
500 @rtype tuple of tuples of (str, int, int, int)
501 """
502 commands = [
503 "import os",
504 "\n".join([
505 "def fsinfo():",
506 " infolist = []",
507 " fsnames = os.listdir('/')",
508 " for fs in fsnames:",
509 " fs = '/' + fs",
510 " infolist.append((fs, os.statvfs(fs)))",
511 " return infolist",
512 ]),
513 "print(fsinfo())",
514 ]
515 out, err = self.__execute(commands)
516 if err:
517 raise IOError(self.__shortError(err))
518 infolist = ast.literal_eval(out.decode("utf-8"))
519 if infolist is None:
520 return None
521 else:
522 filesystemInfos = []
523 for fs, info in infolist:
524 totalSize = info[2] * info[1]
525 freeSize = info[4] * info[1]
526 usedSize = totalSize - freeSize
527 filesystemInfos.append((fs, totalSize, usedSize, freeSize))
528
529 return tuple(filesystemInfos)
530
531 ##################################################################
532 ## non-filesystem related methods below
533 ##################################################################
534
491 def version(self): 535 def version(self):
492 """ 536 """
493 Public method to get the MicroPython version information of the 537 Public method to get the MicroPython version information of the
494 connected device. 538 connected device.
495 539
496 @return dictionary containing the version information 540 @return dictionary containing the version information
497 @rtype dict 541 @rtype dict
498 @exception ValueError raised to indicate that the device might not be 542 @exception IOError raised to indicate an issue with the device
499 running MicroPython or there was an issue parsing the output
500 """ 543 """
501 commands = [ 544 commands = [
502 "import os", 545 "import os",
503 "print(os.uname())", 546 "print(os.uname())",
504 ] 547 ]
505 try: 548 out, err = self.__execute(commands)
506 out, err = self.__execute(commands) 549 if err:
507 if err: 550 raise IOError(self.__shortError(err))
508 raise ValueError(self.__shortError(err))
509 except ValueError:
510 # just re-raise it
511 raise
512 except Exception:
513 # Raise a value error to indicate being unable to find something
514 # on the device that will return parseable information about the
515 # version. It doesn't matter what the error is, it just needs to
516 # report a failure with the expected ValueError exception.
517 raise ValueError("Unable to determine version information.")
518 551
519 rawOutput = out.decode("utf-8").strip() 552 rawOutput = out.decode("utf-8").strip()
520 rawOutput = rawOutput[1:-1] 553 rawOutput = rawOutput[1:-1]
521 items = rawOutput.split(",") 554 items = rawOutput.split(",")
522 result = {} 555 result = {}
523 for item in items: 556 for item in items:
524 key, value = item.strip().split("=") 557 key, value = item.strip().split("=")
525 result[key.strip()] = value.strip()[1:-1] 558 result[key.strip()] = value.strip()[1:-1]
526 return result 559 return result
560
561 def getImplementation(self):
562 """
563 Public method to get some implementation information of the connected
564 device.
565
566 @return dictionary containing the implementation information
567 @rtype dict
568 @exception IOError raised to indicate an issue with the device
569 """
570 commands = [
571 "import sys",
572 "res = {}",
573 "\n".join([
574 "try:",
575 " res['name'] = sys.implementation.name",
576 "except AttributeError:",
577 " res['name'] = 'unknown'",
578 ]),
579 "\n".join([
580 "try:",
581 " res['version'] = '.'.join((str(i) for i in"
582 " sys.implementation.version))",
583 "except AttributeError:",
584 " res['version'] = 'unknown'",
585 ]),
586 "print(res)",
587 ]
588 out, err = self.__execute(commands)
589 if err:
590 raise IOError(self.__shortError(err))
591 return ast.literal_eval(out.decode("utf-8"))
527 592
528 def syncTime(self): 593 def syncTime(self):
529 """ 594 """
530 Public method to set the time of the connected device to the local 595 Public method to set the time of the connected device to the local
531 computer's time. 596 computer's time.
609 has been completed 674 has been completed
610 @signal rsyncProgressMessage(msg) emitted to send a message about what 675 @signal rsyncProgressMessage(msg) emitted to send a message about what
611 rsync is doing 676 rsync is doing
612 @signal removeDirectoryDone() emitted after a directory has been deleted 677 @signal removeDirectoryDone() emitted after a directory has been deleted
613 @signal createDirectoryDone() emitted after a directory was created 678 @signal createDirectoryDone() emitted after a directory was created
679 @signal fsinfoDone(fsinfo) emitted after the file system information was
680 obtained
681
614 @signal synchTimeDone() emitted after the time was synchronizde to the 682 @signal synchTimeDone() emitted after the time was synchronizde to the
615 device 683 device
616 @signal showTimeDone(dateTime) emitted after the date and time was fetched 684 @signal showTimeDone(dateTime) emitted after the date and time was fetched
617 from the connected device 685 from the connected device
618 @signal showVersionDone(versionInfo) emitted after the version information 686 @signal showVersionDone(versionInfo) emitted after the version information
619 was fetched from the connected device 687 was fetched from the connected device
688 @signal showImplementationDone(name,version) emitted after the
689 implementation information has been obtained
620 690
621 @signal error(exc) emitted with a failure message to indicate a failure 691 @signal error(exc) emitted with a failure message to indicate a failure
622 during the most recent operation 692 during the most recent operation
623 """ 693 """
624 longListFiles = pyqtSignal(tuple) 694 longListFiles = pyqtSignal(tuple)
629 deleteFileDone = pyqtSignal(str) 699 deleteFileDone = pyqtSignal(str)
630 rsyncDone = pyqtSignal(str, str) 700 rsyncDone = pyqtSignal(str, str)
631 rsyncProgressMessage = pyqtSignal(str) 701 rsyncProgressMessage = pyqtSignal(str)
632 removeDirectoryDone = pyqtSignal() 702 removeDirectoryDone = pyqtSignal()
633 createDirectoryDone = pyqtSignal() 703 createDirectoryDone = pyqtSignal()
704 fsinfoDone = pyqtSignal(tuple)
705
634 synchTimeDone = pyqtSignal() 706 synchTimeDone = pyqtSignal()
635 showTimeDone = pyqtSignal(str) 707 showTimeDone = pyqtSignal(str)
636 showVersionDone = pyqtSignal(dict) 708 showVersionDone = pyqtSignal(dict)
709 showImplementationDone = pyqtSignal(str, str)
637 710
638 error = pyqtSignal(str, str) 711 error = pyqtSignal(str, str)
639 712
640 def __init__(self, port, parent=None): 713 def __init__(self, port, parent=None):
641 """ 714 """
647 @type QObject 720 @type QObject
648 """ 721 """
649 super(MicroPythonFileManager, self).__init__(parent) 722 super(MicroPythonFileManager, self).__init__(parent)
650 723
651 self.__serialPort = port 724 self.__serialPort = port
652 self.__serial = MicroPythonSerialPort(parent=self) 725 self.__serial = MicroPythonSerialPort(
726 timeout=Preferences.getMicroPython("SerialTimeout"),
727 parent=self)
653 self.__fs = MicroPythonFileSystem(parent=self) 728 self.__fs = MicroPythonFileSystem(parent=self)
654 729
655 @pyqtSlot() 730 @pyqtSlot()
656 def connect(self): 731 def connectToDevice(self):
657 """ 732 """
658 Public slot to start the manager. 733 Public slot to start the manager.
659 """ 734 """
660 self.__serial.openSerialLink(self.__serialPort) 735 self.__serial.openSerialLink(self.__serialPort)
661 self.__fs.setSerial(self.__serial) 736 self.__fs.setSerial(self.__serial)
662 737
663 @pyqtSlot() 738 @pyqtSlot()
664 def disconnect(self): 739 def disconnectFromDevice(self):
665 """ 740 """
666 Public slot to stop the thread. 741 Public slot to stop the thread.
667 """ 742 """
668 self.__serial.closeSerialLink() 743 self.__serial.closeSerialLink()
744
745 @pyqtSlot()
746 def handlePreferencesChanged(self):
747 """
748 Public slot to handle a change of the preferences.
749 """
750 self.__serial.setTimeout(Preferences.getMicroPython("SerialTimeout"))
669 751
670 @pyqtSlot(str) 752 @pyqtSlot(str)
671 def lls(self, dirname): 753 def lls(self, dirname):
672 """ 754 """
673 Public slot to get a long listing of the given directory. 755 Public slot to get a long listing of the given directory.
943 self.__fs.rmdir(dirname) 1025 self.__fs.rmdir(dirname)
944 self.removeDirectoryDone.emit() 1026 self.removeDirectoryDone.emit()
945 except Exception as exc: 1027 except Exception as exc:
946 self.error.emit("rmdir", str(exc)) 1028 self.error.emit("rmdir", str(exc))
947 1029
1030 def fileSystemInfo(self):
1031 """
1032 Public method to obtain information about the currently mounted file
1033 systems.
1034 """
1035 try:
1036 fsinfo = self.__fs.fileSystemInfo()
1037 self.fsinfoDone.emit(fsinfo)
1038 except Exception as exc:
1039 self.error.emit("fileSystemInfo", str(exc))
1040
948 ################################################################## 1041 ##################################################################
949 ## some non-filesystem related methods below 1042 ## some non-filesystem related methods below
950 ################################################################## 1043 ##################################################################
951 1044
952 @pyqtSlot() 1045 @pyqtSlot()
981 try: 1074 try:
982 versionInfo = self.__fs.version() 1075 versionInfo = self.__fs.version()
983 self.showVersionDone.emit(versionInfo) 1076 self.showVersionDone.emit(versionInfo)
984 except Exception as exc: 1077 except Exception as exc:
985 self.error.emit("showVersion", str(exc)) 1078 self.error.emit("showVersion", str(exc))
1079
1080 @pyqtSlot()
1081 def showImplementation(self):
1082 """
1083 Public slot to obtain some implementation related information.
1084 """
1085 try:
1086 impInfo = self.__fs.getImplementation()
1087 if impInfo["name"] == "micropython":
1088 name = "MicroPython"
1089 elif impInfo["name"] == "circuitpython":
1090 name = "CircuitPython"
1091 elif impInfo["name"] == "unknown":
1092 name = self.tr("unknown")
1093 else:
1094 name = impInfo["name"]
1095 if impInfo["version"] == "unknown":
1096 version = self.tr("unknown")
1097 else:
1098 version = impInfo["version"]
1099 self.showImplementationDone.emit(name, version)
1100 except Exception as exc:
1101 self.error.emit("showVersion", str(exc))

eric ide

mercurial