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
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
1"""hods - home directory synchronization.
3Copyright (C) 2016-2020 Mathias Stelzer <knoppo@rolln.de>
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.
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.
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
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
25logger = logging.getLogger(__name__)
28class Feature(Sortable, DirectoryNode):
29 """Source container that can be installed per hods installation."""
31 child_directory_class = Source
33 child_file_class = None
35 children_key = 'sources'
37 sort_children = False
39 clear_on_scan = False
41 def __init__(self, tree, name, default=False, installed=False, **kwargs):
42 """Initialize feature instance.
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
54 self.default = default
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
61 self.hooks = Hooks(self, 'update', 'push')
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
71 @property
72 def sources(self):
73 """List the sources in this feature (children alias)."""
74 return self.children
76 @sources.setter
77 def sources(self, value):
78 """Set the list of sources in this feature (children alias)."""
79 self.children[:] = value
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
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
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)
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