OSXRemovableDrivePlugin.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. # Copyright (c) 2015 Ultimaker B.V.
  2. # Copyright (c) 2013 David Braam
  3. # Uranium is released under the terms of the LGPLv3 or higher.
  4. from . import RemovableDrivePlugin
  5. import subprocess
  6. import os
  7. import plistlib
  8. class OSXRemovableDrivePlugin(RemovableDrivePlugin.RemovableDrivePlugin):
  9. """Support for removable devices on Mac OSX"""
  10. def checkRemovableDrives(self):
  11. drives = {}
  12. p = subprocess.Popen(["system_profiler", "SPUSBDataType", "-xml"], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
  13. plist = plistlib.loads(p.communicate()[0])
  14. result = self._recursiveSearch(plist, "removable_media")
  15. p = subprocess.Popen(["system_profiler", "SPCardReaderDataType", "-xml"], stdout=subprocess.PIPE, stderr = subprocess.PIPE)
  16. plist = plistlib.loads(p.communicate()[0])
  17. result.extend(self._recursiveSearch(plist, "removable_media"))
  18. for drive in result:
  19. # Ignore everything not explicitly marked as removable
  20. if drive["removable_media"] != "yes":
  21. continue
  22. # Ignore any removable device that does not have an actual volume
  23. if "volumes" not in drive or not drive["volumes"]:
  24. continue
  25. for volume in drive["volumes"]:
  26. if not "mount_point" in volume:
  27. continue
  28. mount_point = volume["mount_point"]
  29. if "_name" in volume:
  30. drive_name = volume["_name"]
  31. else:
  32. drive_name = os.path.basename(mount_point)
  33. drives[mount_point] = drive_name
  34. return drives
  35. def performEjectDevice(self, device):
  36. p = subprocess.Popen(["diskutil", "eject", device.getId()], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
  37. p.communicate()
  38. return_code = p.wait()
  39. if return_code != 0:
  40. return False
  41. else:
  42. return True
  43. # Recursively search for key in a plist parsed by plistlib
  44. def _recursiveSearch(self, plist, key):
  45. result = []
  46. for entry in plist:
  47. if key in entry:
  48. result.append(entry)
  49. continue
  50. if "_items" in entry:
  51. result.extend(self._recursiveSearch(entry["_items"], key))
  52. if "Media" in entry:
  53. result.extend(self._recursiveSearch(entry["Media"], key))
  54. return result