_info.py 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. from __future__ import annotations
  2. import typing
  3. from datetime import datetime, timezone
  4. from ._errors import MissingInfoNamespace
  5. if typing.TYPE_CHECKING:
  6. from collections.abc import Mapping
  7. from typing import Any
  8. def epoch_to_datetime(t: int | None) -> datetime | None:
  9. """Convert epoch time to a UTC datetime."""
  10. if t is None:
  11. return None
  12. return datetime.fromtimestamp(t, tz=timezone.utc)
  13. class Info:
  14. __slots__ = ["raw", "namespaces"]
  15. def __init__(self, raw_info: Mapping[str, Any]):
  16. self.raw = raw_info
  17. self.namespaces = frozenset(raw_info.keys())
  18. def get(self, namespace: str, key: str, default: Any | None = None) -> Any | None:
  19. try:
  20. return self.raw[namespace].get(key, default)
  21. except KeyError:
  22. raise MissingInfoNamespace(f"Namespace {namespace!r} does not exist")
  23. @property
  24. def name(self) -> str:
  25. return self.get("basic", "name")
  26. @property
  27. def is_dir(self) -> bool:
  28. return self.get("basic", "is_dir")
  29. @property
  30. def is_file(self) -> bool:
  31. return not self.is_dir
  32. @property
  33. def accessed(self) -> datetime | None:
  34. return epoch_to_datetime(self.get("details", "accessed"))
  35. @property
  36. def modified(self) -> datetime | None:
  37. return epoch_to_datetime(self.get("details", "modified"))
  38. @property
  39. def size(self) -> int | None:
  40. return self.get("details", "size")
  41. @property
  42. def type(self) -> int | None:
  43. return self.get("details", "type")
  44. @property
  45. def created(self) -> datetime | None:
  46. return epoch_to_datetime(self.get("details", "created"))
  47. @property
  48. def metadata_changed(self) -> datetime | None:
  49. return epoch_to_datetime(self.get("details", "metadata_changed"))
  50. def __str__(self) -> str:
  51. if self.is_dir:
  52. return "<dir '{}'>".format(self.name)
  53. else:
  54. return "<file '{}'>".format(self.name)
  55. __repr__ = __str__