def _set_kind(self, kind): if hasattr(self, '_kind'): raise NodeError("Cannot change node's kind") else: self._kind = kind # Post setter check (path's trailing slash) if self.path.endswith('/'): raise NodeError("Node's path cannot end with slash")
def __init__(self, path, kind): if path.startswith('/'): raise NodeError( "Cannot initialize Node objects with slash at " "the beginning as only relative paths are supported") self.path = path.rstrip('/') if path == '' and kind != NodeKind.DIR: raise NodeError("Only DirNode and its subclasses may be " "initialized with empty path") self.kind = kind #self.dirs, self.files = [], [] if self.is_root() and not self.is_dir(): raise NodeError("Root node cannot be FILE kind")
def annotate(self): """ Returns a list of three element tuples with lineno,changeset and line """ if self.changeset is None: raise NodeError('Unable to get changeset for this FileNode') return self.changeset.get_file_annotate(self.path)
def history(self): """ Returns a list of changeset for this file in which the file was changed """ if self.changeset is None: raise NodeError('Unable to get changeset for this FileNode') return self.changeset.get_file_history(self.path)
def get_mimetype(self): """ Mimetype is calculated based on the file's content. If ``_mimetype`` attribute is available, it will be returned (backends which store mimetypes or can easily recognize them, should set this private attribute to indicate that type should *NOT* be calculated). """ if hasattr(self, '_mimetype'): if (isinstance(self._mimetype, ( tuple, list, )) and len(self._mimetype) == 2): return self._mimetype else: raise NodeError('given _mimetype attribute must be an 2 ' 'element list or tuple') mtype, encoding = mimetypes.guess_type(self.name) if mtype is None: if self.is_binary: mtype = 'application/octet-stream' encoding = None else: mtype = 'text/plain' encoding = None return mtype, encoding
def state(self): if not self.changeset: raise NodeError("Cannot check state of the node if it's not " "linked with changeset") elif self.path in (node.path for node in self.changeset.added): return NodeState.ADDED elif self.path in (node.path for node in self.changeset.changed): return NodeState.CHANGED else: return NodeState.NOT_CHANGED
def get_node(self, path): """ Returns node from within this particular ``DirNode``, so it is now allowed to fetch, i.e. node located at 'docs/api/index.rst' from node 'docs'. In order to access deeper nodes one must fetch nodes between them first - this would work:: docs = root.get_node('docs') docs.get_node('api').get_node('index.rst') :param: path - relative to the current node .. note:: To access lazily (as in example above) node have to be initialized with related changeset object - without it node is out of context and may know nothing about anything else than nearest (located at same level) nodes. """ try: path = path.rstrip('/') if path == '': raise NodeError("Cannot retrieve node without path") self.nodes # access nodes first in order to set _nodes_dict paths = path.split('/') if len(paths) == 1: if not self.is_root(): path = '/'.join((self.path, paths[0])) else: path = paths[0] return self._nodes_dict[path] elif len(paths) > 1: if self.changeset is None: raise NodeError("Cannot access deeper " "nodes without changeset") else: path1, path2 = paths[0], '/'.join(paths[1:]) return self.get_node(path1).get_node(path2) else: raise KeyError except KeyError: raise NodeError("Node does not exist at %s" % path)
def __init__(self, path, nodes=(), changeset=None): """ Only one of ``nodes`` and ``changeset`` may be given. Passing both would raise ``NodeError`` exception. :param path: relative path to the node :param nodes: content may be passed to constructor :param changeset: if given, will use it to lazily fetch content :param size: always 0 for ``DirNode`` """ if nodes and changeset: raise NodeError("Cannot use both nodes and changeset") super(DirNode, self).__init__(path, NodeKind.DIR) self.changeset = changeset self._nodes = nodes
def __init__(self, path, content=None, changeset=None, mode=None): """ Only one of ``content`` and ``changeset`` may be given. Passing both would raise ``NodeError`` exception. :param path: relative path to the node :param content: content may be passed to constructor :param changeset: if given, will use it to lazily fetch content :param mode: octal representation of ST_MODE (i.e. 0100644) """ if content and changeset: raise NodeError("Cannot use both content and changeset") super(FileNode, self).__init__(path, kind=NodeKind.FILE) self.changeset = changeset self._content = content self._mode = mode or 0100644
def state(self): raise NodeError("Cannot access state of DirNode")
def content(self): raise NodeError( "%s represents a dir and has no ``content`` attribute" % self)
def last_changeset(self): if self.changeset: return self.changeset.get_file_changeset(self.path) raise NodeError("Cannot retrieve last changeset of the file without " "related changeset attribute")
def message(self): if self.changeset: return self.last_changeset.message raise NodeError("Cannot retrieve message of the file without related " "changeset attribute")
def size(self): if self.changeset: return self.changeset.get_file_size(self.path) raise NodeError("Cannot retrieve size of the file without related " "changeset attribute")