Coverage for icloudpy/services/ubiquity.py: 43%

75 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2024-04-12 14:26 +0000

1"""File service.""" 

2from datetime import datetime 

3 

4from six import PY2 

5 

6 

7class UbiquityService: 

8 """The 'Ubiquity' iCloud service.""" 

9 

10 def __init__(self, service_root, session, params): 

11 self.session = session 

12 self.params = params 

13 

14 self._root = None 

15 self._node_url = service_root + "/ws/%s/%s/%s" 

16 

17 @property 

18 def root(self): 

19 """Gets the root node.""" 

20 if not self._root: 

21 self._root = self.get_node(0) 

22 return self._root 

23 

24 def get_node_url(self, node_id, variant="item"): 

25 """Returns a node URL.""" 

26 return self._node_url % (self.params["dsid"], variant, node_id) 

27 

28 def get_node(self, node_id): 

29 """Returns a node.""" 

30 request = self.session.get(self.get_node_url(node_id)) 

31 return UbiquityNode(self, request.json()) 

32 

33 def get_children(self, node_id): 

34 """Returns a node children.""" 

35 request = self.session.get(self.get_node_url(node_id, "parent")) 

36 items = request.json()["item_list"] 

37 return [UbiquityNode(self, item) for item in items] 

38 

39 def get_file(self, node_id, **kwargs): 

40 """Returns a node file.""" 

41 return self.session.get(self.get_node_url(node_id, "file"), **kwargs) 

42 

43 def __getattr__(self, attr): 

44 return getattr(self.root, attr) 

45 

46 def __getitem__(self, key): 

47 return self.root[key] 

48 

49 

50class UbiquityNode: 

51 """Ubiquity node.""" 

52 

53 def __init__(self, conn, data): 

54 self.data = data 

55 self.connection = conn 

56 

57 self._children = None 

58 

59 @property 

60 def item_id(self): 

61 """Gets the node id.""" 

62 return self.data.get("item_id") 

63 

64 @property 

65 def name(self): 

66 """Gets the node name.""" 

67 return self.data.get("name") 

68 

69 @property 

70 def type(self): 

71 """Gets the node type.""" 

72 return self.data.get("type") 

73 

74 @property 

75 def size(self): 

76 """Gets the node size.""" 

77 try: 

78 return int(self.data.get("size")) 

79 except ValueError: 

80 return None 

81 

82 @property 

83 def modified(self): 

84 """Gets the node modified date.""" 

85 return datetime.strptime(self.data.get("modified"), "%Y-%m-%dT%H:%M:%SZ") 

86 

87 def open(self, **kwargs): 

88 """Returns the node file.""" 

89 return self.connection.get_file(self.item_id, **kwargs) 

90 

91 def get_children(self): 

92 """Returns the node children.""" 

93 if not self._children: 

94 self._children = self.connection.get_children(self.item_id) 

95 return self._children 

96 

97 def dir(self): 

98 """Returns children node directories by their names.""" 

99 return [child.name for child in self.get_children()] 

100 

101 def get(self, name): 

102 """Returns a child node by its name.""" 

103 return [child for child in self.get_children() if child.name == name][0] 

104 

105 def __getitem__(self, key): 

106 try: 

107 return self.get(key) 

108 except IndexError as error: 

109 raise KeyError(f"No child named {key} exists") from error 

110 

111 def __unicode__(self): 

112 return self.name 

113 

114 def __str__(self): 

115 as_unicode = self.__unicode__() 

116 if PY2: 

117 return as_unicode.encode("utf-8", "ignore") 

118 return as_unicode 

119 

120 def __repr__(self): 

121 return f"<{self.type.capitalize()}: '{self}'>"