def test_monkey_in_tree(): """Ask tester to share a folder with this account and ensure that the node is created. Note: The share needs to be accepted and added to the account being tested. """ init_storage = init_onedrive() input( termcolor.colored( 'Please share a folder called "monkey" to this accout and hit [ENTER]', 'green', attrs=['blink', 'bold'])) tree = init_storage.storage.model monkey = bushn.Node('monkey') assert monkey in tree, 'monkeys live in trees.' monkey = tree.get_node(['monkey']) logger.info(monkey.props) # assert some expected props assert monkey.props[IS_DIR] is True assert monkey.props['_remote_item'] is True assert monkey.props[VERSION_ID] == IS_DIR assert '_id' in monkey.props # test iter_share_roots share_roots = list(onedrive.iter_share_roots(init_storage.storage.model)) assert monkey in share_roots
def root(request): """Create a default Root node TODO: Copy pasted during move to jars. Is there a better place? :return: Node """ if request.param: return bushn.Node(name=None) else: return bushn.IndexingNode(name=None, indexes=['_id'])
def test_dropbox_tree_to_sync_engine_adapter_transform_path(): """Ensure that the custom dropbox adapter properly transforms given paths.""" root = bushn.Node("root", parent=None, props={'cursor': None}) adapter = DropboxTreeToSyncEngineAdapter(node=root, sync_engine=None, storage_id='test') assert root.parent is None assert adapter.transform_path(root) == [] node_a = bushn.Node("a", parent=root, props={'_path_display_node': 'a', '_id': 'id:1'}) assert '_path_display_node' in node_a.props assert adapter.transform_path(node_a) == ['a'] node_b = bushn.Node("b", parent=node_a, props={'_path_display_node': 'b', '_id': 'id:2'}) assert '_path_display_node' in node_b.props assert adapter.transform_path(node_b) == ['a', 'b'] node_c = bushn.Node("c", parent=node_b, props={'_path_display_node': 'c', '_id': 'id:3'}) assert adapter.transform_path(node_c) == ['a', 'b', 'c']
def tree_adapter(): """ simple tree adapter with one node in the root """ tree_root = bushn.Node(None) se_mock = mock.Mock() adapter = jars.TreeToSyncEngineEngineAdapter(tree_root, se_mock, storage_id=TEST_STORAGE_ID) with adapter: tree_root.add_child('Hello', props=TEST_PROPS) return tree_root, se_mock, adapter
def get_tree(self, cached=False): """This will fetch and return the full tree and its metadata. Should return the root node for the tree. This basic implementation will use`get_children`. ..Note. get_tree should never modify the storage's state. if cached is False, no internal state may be used to create the tree. Else a filtered copy of self.model can be returned :param cached: whether to use internal state to return tree. :param parent: The path from which children are returned. If None its done from the root. :throws: :class:`InvalidOperationError` if no subtree with parent exists. :throws: :class:`CurrentlyNotPossibleError` if operation can currently not be executed. :throws: :class:`UnavailableError` if storage is not reachable. :throws: :class:`AuthenticationError` if storage is not authenticated properly. :throws: :class:`SevereError` if storage is not valid. :returns: :class:`bushn.Node` object """ # pylint:disable=unused-argument root = bushn.Node(name=None) working_stack = [root] while working_stack: parent = working_stack.pop() try: # children_to_add [(recurse, child)] filter_node = self.filter_tree.get_node(parent.path) # if we have a filter node see if it has children, if yes, only deliver # non-dirs if children is set to true if filter_node.children: children_to_add = \ [(child, True) for child in self.get_tree_children(parent.path) if not child[1]['is_dir'] or filter_node.has_child(child[0])] else: # it has no children just recurse children_to_add = \ [(child, True) for child in self.get_tree_children(parent.path)] except KeyError: children_to_add = \ [(child, True) for child in self.get_tree_children(parent.path)] for (name, props), recurse in children_to_add: child = parent.add_child(name, props) if props.get('is_dir') and recurse: working_stack.append(child) return root
def base_tree(): """Simple tree with 4 nodes. a +-b +-a c """ tree = bushn.Node(None) a_node = tree.add_child('a', props={'_inode': 'a_node'}) c_node = tree.add_child('c', props={'_inode': 'c_node'}) a_node.add_child('b', props={'_inode': 'b_node'}) a_node.add_child('a', props={'_inode': 'aa_node'}) logger.info('base_tree fixture\n%s', bushn.tree_to_str(tree, prop_key='_inode')) return tree
def __init__(self, event_sink, storage_id, storage_cache_dir=None, storage_cache_version=None, default_model=None): """ :param event_sink: In productive use this is the SyncEngine. Might be any other class implementing the event handling methods. :param storage_id: The storage_id of this storage. :param storage_cache_dir the directory to store model caches in :param storage_cache_version the version of the storage cache to load (older versions will be ignored if present = new model with new version will be generated :raise bushn.AuthenticationError in case the authentication data is wrong :raise """ # settig storage id and events sink self.storage_id = storage_id self._event_sink = event_sink # The display name for the user, if available a username should be displayed, otherwise # default to email address. self._storage_user_name = None # setting cache dir (will be used to store model caches) self.cache_dir = storage_cache_dir # None permutable default model if default_model is None: default_model = Node(name=None) # read model cache if present and set it as internal model -> if no model is # present: generate new nodel using default node passed (e.g. Node, # or IndexedNode) dependent on what the specific service needs self.tree = load_model(cache_dir=self.cache_dir, default=default_model, version=storage_cache_version) # private member for offline handling # DO NOT ACCESS DIRECTLY - use self.offline instead self._offline = False # directories to sync self.filter_tree = bushn.Node(name=None)
def __init__(self, event_sink, storage_id, storage_cache_dir, storage_cred_reader, storage_cred_writer, polling_interval=30): # pylint: disable=too-many-arguments,unused-argument # getting credentials from store self._credentials = json.loads(storage_cred_reader()) super(CifsFileSystem, self).__init__(self._credentials['unc_path'], event_sink, storage_id) try: net_use(self._credentials) except WindowsError: self._offline = False logger.debug('Cant access windows share at the moment', exc_info=True) self.storage_cache_dir = storage_cache_dir self._event_sink = ModelUpdatingEventSink( next_event_sync=self._event_sink, root_node=jars.load_model(storage_cache_dir, bushn.Node(None)))
def test_on_shared_state_changed(encryption_wrapper_mock, mocker): """check for issue CC-409. The bug was that it propagated the wrong properties for the children of a node """ mocker.patch('cc.encryption.storage_wrapper.get_key_subjects', return_value=('abc', )) new_props = { 'c': { 'version_id': 'is_dir', 'share_id': 1 }, FILESYSTEM_ID: { 'version_id': 'is_dir', 'is_dir': True } } new_props_child = { 'c': { 'version_id': 123, 'share_id': 1 }, FILESYSTEM_ID: { 'version_id': 123 } } sender = mock.Mock() sender.root_node = bushn.Node(name=None) changed_node = sender.root_node.add_child('a', {STORAGE: new_props}) changed_node.add_child('xyz', {STORAGE: new_props_child}) sender.query_shared_state = mock.Mock(return_value=('v', 1, None)) encryption_wrapper_mock.on_shared_state_changed( sender, old_props={STORAGE: { 'c': { 'version_id': 'is_dir' } }}, node=changed_node, storage_id='c') new_props_with_enc_tag = deepcopy(new_props[FILESYSTEM_ID]) new_props_with_enc_tag['version_id'] = EncryptedVersionTag( version_id='is_dir', key_subjects=('abc', )) new_props_with_enc_tag_child = deepcopy(new_props_child[FILESYSTEM_ID]) new_props_with_enc_tag_child['version_id'] = EncryptedVersionTag( version_id=123, key_subjects=('abc', )) expected = [ mock.call(storage_id=FILESYSTEM_ID, path=['a'], event_props=new_props_with_enc_tag), mock.call(storage_id=FILESYSTEM_ID, path=['a', 'xyz'], event_props=new_props_with_enc_tag_child) ] encryption_wrapper_mock._syncengine.storage_modify.has_calls( expected, any_order=True)