Coverage for src/hods/config/feature.py: 100.00%

Shortcuts on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

60 statements  

1"""hods - home directory synchronization. 

2 

3Copyright (C) 2016-2020 Mathias Stelzer <knoppo@rolln.de> 

4 

5hods is free software: you can redistribute it and/or modify 

6it under the terms of the GNU General Public License as published by 

7the Free Software Foundation, either version 3 of the License, or 

8(at your option) any later version. 

9 

10hods is distributed in the hope that it will be useful, 

11but WITHOUT ANY WARRANTY; without even the implied warranty of 

12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

13GNU General Public License for more details. 

14 

15You should have received a copy of the GNU General Public License 

16along with this program. If not, see <http://www.gnu.org/licenses/>. 

17""" 

18import logging 

19 

20from hods.config.hooks import Hooks 

21from hods.config.sources import Source, get_source_class 

22from hods.node import DirectoryNode 

23from hods.utils import Sortable 

24 

25logger = logging.getLogger(__name__) 

26 

27 

28class Feature(Sortable, DirectoryNode): 

29 """Source container that can be installed per hods installation.""" 

30 

31 child_directory_class = Source 

32 

33 child_file_class = None 

34 

35 children_key = 'sources' 

36 

37 sort_children = False 

38 

39 clear_on_scan = False 

40 

41 def __init__(self, tree, name, default=False, installed=False, **kwargs): 

42 """Initialize feature instance. 

43 

44 :param tree: parent `hods.config.tree.SourceTree` instance 

45 :param name: `str` - name for this feature 

46 :param installed: `bool` - Mark the feature as installed. 

47 Ignored if `default` is `True`. (Default: False) 

48 :param default: `bool` - Install the feature by default. 

49 Overwrites `default` argument. (Default: False) 

50 """ 

51 super().__init__(tree, name, **kwargs) 

52 self.tree = tree 

53 

54 self.default = default 

55 

56 # `installed` is kept on the object itself to store it in 

57 # `Settings.tree` for comparison. The `Config` loads and saves it 

58 # to `Settings.installed_features` for the `SourceTree` to keep it local. 

59 self.installed = default or installed 

60 

61 self.hooks = Hooks(self, 'update', 'push') 

62 

63 @classmethod 

64 def from_data(cls, *args, **data): 

65 """Recreate instance from a stored `dict`.""" 

66 hooks = data.pop('hooks', {}) 

67 obj = super().from_data(*args, **data) 

68 obj.hooks.load(hooks) 

69 return obj 

70 

71 @property 

72 def sources(self): 

73 """List the sources in this feature (children alias).""" 

74 return self.children 

75 

76 @sources.setter 

77 def sources(self, value): 

78 """Set the list of sources in this feature (children alias).""" 

79 self.children[:] = value 

80 

81 def collect_sources_to_pull(self): 

82 """Collect all sources to pull from the server.""" 

83 for source in self.sources: 

84 if self.tree.settings.is_master and source.stored_on_master: 

85 logger.info('pull: skip on master: %s', source.basename) 

86 continue 

87 if source.is_ignored(): 

88 logger.debug('pull: ignored: %s', source.basename) 

89 continue 

90 yield source 

91 

92 def collect_sources_to_push(self): 

93 """Collect all sources to push from the server.""" 

94 for source in self.sources: 

95 if source.pull_only: 

96 logger.info('push: skip pull only: %s', source.basename) 

97 continue 

98 if self.tree.settings.is_master and source.stored_on_master: 

99 logger.info('push: skip on master: %s', source.basename) 

100 continue 

101 if source.is_ignored(): 

102 logger.debug('push: ignored: %s', source.basename) 

103 continue 

104 yield source 

105 

106 def load_child_class(self, data): 

107 """Get the source class for the given stored data.""" 

108 source_type = data.pop('type', None) 

109 return get_source_class(source_type) 

110 

111 def as_dict(self): 

112 """Return a `dict` to store and recreate this instance.""" 

113 data = super().as_dict() 

114 data['default'] = self.default 

115 data['installed'] = self.installed 

116 data['hooks'] = self.hooks.as_dict() 

117 return data