コード例 #1
0
def _parse_contents(content, parser):
    is_attr = False
    is_node = False
    res = None
    for c in content:
        if ':' in c:
            outs = c.split(':')
            if len(outs) != 2:
                parser.error('incorrect format for content "%s"' % c)
            if is_attr:
                parser.error('cannot mix node-type contents '
                             'with attribute-type contents')
            is_node = True
            if res is None:
                res = OrderedDict()
            outs = map(lambda x: x.strip(), outs)
            key, value = outs
            if key not in res:
                res[key] = value
            else:
                parser.error('duplicate name "%s" for node-type content' % key)
        else:
            if is_node:
                parser.error('cannot mix node-type contents '
                             'with attribute-type contents')
            is_attr = True
            if res is None:
                res = []
            res.append(c)

    if isinstance(res, list):
        if len(res) == 1:
            res = res[0]
    return res
コード例 #2
0
 def elems(self):
     """
     Get elements of this node.
     """
     if self._elems is None:
         this_is_dir = False
         this_is_file = False
         self._elems = OrderedDict()
         if not isinstance(self.content, dict):
             raise NodeError('invalid content format')
         for name in self.content:
             content = self.content[name]
             elem, this_is_dir, this_is_file = self._make_elem(
                 name, content)
             self._elems[name] = elem
         self._update_class(this_is_dir, this_is_file)
         self._vals = self._elems.values()
     return self._elems
コード例 #3
0
ファイル: cli.py プロジェクト: shichao-an/momo
def _parse_contents(content, parser):
    is_attr = False
    is_node = False
    res = None
    for c in content:
        if ':' in c:
            outs = c.split(':')
            if len(outs) != 2:
                parser.error('incorrect format for content "%s"' % c)
            if is_attr:
                parser.error(
                    'cannot mix node-type contents '
                    'with attribute-type contents')
            is_node = True
            if res is None:
                res = OrderedDict()
            outs = map(lambda x: x.strip(), outs)
            key, value = outs
            if key not in res:
                res[key] = value
            else:
                parser.error(
                    'duplicate name "%s" for node-type content' % key)
        else:
            if is_node:
                parser.error(
                    'cannot mix node-type contents '
                    'with attribute-type contents')
            is_attr = True
            if res is None:
                res = []
            res.append(c)

    if isinstance(res, list):
        if len(res) == 1:
            res = res[0]
    return res
コード例 #4
0
def do_add_path(bucket, args, parser):
    root = bucket.root
    indexer = Indexer(
        elem=root,
        parser=parser,
        names=args.names,
        unordered=True,
        cache_lines=False,
        no_output=True,
    )
    elem = indexer.get()
    path = eval_path(args.path)
    name = args.name or os.path.basename(path)
    content = OrderedDict([('path', path)])
    elem.add(name, content)
    print('file "%s" added to %s "%s"' % (name, elem.type.lower(), elem))
コード例 #5
0
    def get_elems(self, elem_type=None):
        """
        The generic method to get elements.

        :param elem_type: the element type.  If None, then all types are
                          included. Otherwise, it is one of "file",
                          "directory", "node", and "attribute".
        """
        elems = self.elems
        if elem_type is not None:
            items = self.elems.items()
            if elem_type not in ('file', 'directory', 'node', 'attribute'):
                raise NodeError('unknown element type')
            elem_class = getattr(sys.modules[__name__], elem_type.title())
            items = filter(lambda x: isinstance(x[1], elem_class), items)
            elems = OrderedDict(items)
        return elems
コード例 #6
0
ファイル: core.py プロジェクト: shichao-an/momo
 def elems(self):
     """
     Get elements of this node.
     """
     if self._elems is None:
         this_is_dir = False
         this_is_file = False
         self._elems = OrderedDict()
         if not isinstance(self.content, dict):
             raise NodeError('invalid content format')
         for name in self.content:
             content = self.content[name]
             elem, this_is_dir, this_is_file = self._make_elem(name,
                                                               content)
             self._elems[name] = elem
         self._update_class(this_is_dir, this_is_file)
         self._vals = self._elems.values()
     return self._elems
コード例 #7
0
class Node(Element):
    """
    The Node class.
    """
    def __init__(self, name, bucket, parent, content, *args, **kwargs):
        super(Node, self).__init__(name, bucket, parent, content, *args,
                                   **kwargs)
        self._elems = None
        self._vals = None
        self._i = 0
        self._len = None
        if not self.bucket.settings.lazy_bucket:
            # self.elems is called here so that the next-level elements are
            # loaded and the classes of the current elements are updated
            self._len = len(self.elems)
        self._action = NodeAction(self)

    @property
    def is_root(self):
        return self.parent is None

    @property
    def elems(self):
        """
        Get elements of this node.
        """
        if self._elems is None:
            this_is_dir = False
            this_is_file = False
            self._elems = OrderedDict()
            if not isinstance(self.content, dict):
                raise NodeError('invalid content format')
            for name in self.content:
                content = self.content[name]
                elem, this_is_dir, this_is_file = self._make_elem(
                    name, content)
                self._elems[name] = elem
            self._update_class(this_is_dir, this_is_file)
            self._vals = self._elems.values()
        return self._elems

    def _update_class(self, this_is_dir, this_is_file):
        """Update node's class to Directory or File."""
        if this_is_dir is True:
            self.__class__ = Directory
        elif this_is_file is True:
            self.__class__ = File

    def _make_elem(self, name, content):
        """
        Make a proper element based on the content.

        :return: new child element, whether self should be a file, and whether
                 self should be a directory.
        """
        this_is_dir = self.is_dir
        this_is_file = self.is_file
        is_dict = isinstance(content, dict)
        if not is_dict:
            this_is_file = True
            elem = (Attribute(name=name,
                              bucket=self.bucket,
                              parent=self,
                              content=content))
        else:
            this_is_dir = True
            elem = Node(name=name,
                        bucket=self.bucket,
                        parent=self,
                        content=content)
        return elem, this_is_dir, this_is_file

    @property
    def svals(self):
        """Shortcut to get sorted element values."""
        self.get_sorted_vals()

    @property
    def vals(self):
        """Shortcut to get unordered element values."""
        if self._elems is None:
            self._vals = self.elems.values()
        return self._vals

    @property
    def attrs(self):
        return self.get_elems(elem_type='attribute')

    @property
    def attr_vals(self):
        return self.get_vals(unordered=True, elem_type='attribute')

    @property
    def attr_svals(self):
        return self.get_vals(elem_type='attribute')

    @property
    def nodes(self):
        return self.get_elems(elem_type='node')

    @property
    def node_vals(self):
        return self.get_vals(unordered=True, elem_type='node')

    @property
    def node_svals(self):
        return self.get_vals(elem_type='node')

    def __iter__(self):
        return self

    def __next__(self):
        if self._i < self.len:
            i = self._i
            self._i += 1
            return self.vals[i]
        else:
            raise StopIteration

    next = __next__

    @property
    def len(self):
        if self._len is None:
            self._len = len(self.elems)
        return self._len

    def get_elem_by_name(self, name):
        try:
            return self.elems[name]
        except KeyError:
            raise ElemError('element "%s" does not exist in this %s' %
                            (name, self.type.lower()))

    def get_elem_by_num(self, num, sort_by, unordered, elem_type):
        vals = self.get_vals(sort_by, unordered, elem_type)
        try:
            return vals[num - 1] if vals else None
        except IndexError:
            raise ElemError('element index out of range (1-%d)' % len(vals))

    def get_elems(self, elem_type=None):
        """
        The generic method to get elements.

        :param elem_type: the element type.  If None, then all types are
                          included. Otherwise, it is one of "file",
                          "directory", "node", and "attribute".
        """
        elems = self.elems
        if elem_type is not None:
            items = self.elems.items()
            if elem_type not in ('file', 'directory', 'node', 'attribute'):
                raise NodeError('unknown element type')
            elem_class = getattr(sys.modules[__name__], elem_type.title())
            items = filter(lambda x: isinstance(x[1], elem_class), items)
            elems = OrderedDict(items)
        return elems

    def get_vals(self, sort_by=None, unordered=False, elem_type=None):
        """
        The generic method to get element values.

        :param sort_by: the name of the sorting key.  If it is None and
                        `unordered` is False, then the sorting key is the
                        element name.  If it is a name, then the content of the
                        attribute with this name is used as the key.
        :param unordered: whether to present elements unordered.  If it is
                          True, the original order in the document is used, and
                          `sort_by` has no effect.
        :param elem_type: the element type.  If None, then all types are
                          included. Otherwise, it is one of "file",
                          "directory", "node", and "attribute".
        """
        vals = self.vals
        if elem_type is not None:
            if elem_type not in ('file', 'directory', 'node', 'attribute'):
                raise NodeError('unknown element type')
            elem_class = getattr(sys.modules[__name__], elem_type.title())
            vals = filter(lambda elem: isinstance(elem, elem_class), vals)

        if unordered:
            return vals

        if sort_by is None:
            return sorted(vals, key=attrgetter('name'))

        def sort_key(elem):
            if getattr(elem, 'attrs'):
                return elem.attrs.get(sort_by)
            return None

        return sorted(self.vals, key=sort_key)

    def add(self, name, content):
        """
        Create an element with name and content and add it to this node.
        """
        if name not in self.elems:
            self.content[name] = content
            elem, this_is_dir, this_is_file = self._make_elem(name, content)
            self._elems[name] = elem
            self._update_class(this_is_dir, this_is_file)
            # update vals
            self._vals = self.elems.values()
        else:
            raise NodeError('element "%s" already exists in this %s' %
                            (name, self.type.lower()))

    def delete(self, name):
        """Delete an element with name in this node."""
        if name in self.elems:
            this_is_dir, this_is_file = self._delete_elem(name)
            self._update_class(this_is_dir, this_is_file)
            # update vals
            self._vals = self.elems.values()
        else:
            raise NodeError('element "%s" does not exist in this %s' %
                            (name, self.type.lower()))

    def _delete_elem(self, name):
        this_is_dir = self.is_dir
        this_is_file = self.is_file

        del self._elems[name]
        del self.content[name]

        if not self.content:
            # add a placeholder to keep this node as a file
            self.add(PLACEHOLDER, True)

        # check remaining elements
        for elem in self.elems:
            if self.elems[elem].is_attr:
                this_is_file = True
            if self.elems[elem].is_node:
                this_is_dir = True

        return this_is_dir, this_is_file
コード例 #8
0
ファイル: core.py プロジェクト: shichao-an/momo
class Node(Element):
    """
    The Node class.
    """
    def __init__(self, name, bucket, parent, content, *args, **kwargs):
        super(Node, self).__init__(name, bucket, parent, content,
                                   *args, **kwargs)
        self._elems = None
        self._vals = None
        self._i = 0
        self._len = None
        if not self.bucket.settings.lazy_bucket:
            # self.elems is called here so that the next-level elements are
            # loaded and the classes of the current elements are updated
            self._len = len(self.elems)
        self._action = NodeAction(self)

    @property
    def is_root(self):
        return self.parent is None

    @property
    def elems(self):
        """
        Get elements of this node.
        """
        if self._elems is None:
            this_is_dir = False
            this_is_file = False
            self._elems = OrderedDict()
            if not isinstance(self.content, dict):
                raise NodeError('invalid content format')
            for name in self.content:
                content = self.content[name]
                elem, this_is_dir, this_is_file = self._make_elem(name,
                                                                  content)
                self._elems[name] = elem
            self._update_class(this_is_dir, this_is_file)
            self._vals = self._elems.values()
        return self._elems

    def _update_class(self, this_is_dir, this_is_file):
        """Update node's class to Directory or File."""
        if this_is_dir is True:
            self.__class__ = Directory
        elif this_is_file is True:
            self.__class__ = File

    def _make_elem(self, name, content):
        """
        Make a proper element based on the content.

        :return: new child element, whether self should be a file, and whether
                 self should be a directory.
        """
        this_is_dir = self.is_dir
        this_is_file = self.is_file
        is_dict = isinstance(content, dict)
        if not is_dict:
            this_is_file = True
            elem = (
                Attribute(name=name,
                          bucket=self.bucket,
                          parent=self,
                          content=content)
            )
        else:
            this_is_dir = True
            elem = Node(name=name,
                        bucket=self.bucket,
                        parent=self,
                        content=content)
        return elem, this_is_dir, this_is_file

    @property
    def svals(self):
        """Shortcut to get sorted element values."""
        self.get_sorted_vals()

    @property
    def vals(self):
        """Shortcut to get unordered element values."""
        if self._elems is None:
            self._vals = self.elems.values()
        return self._vals

    @property
    def attrs(self):
        return self.get_elems(elem_type='attribute')

    @property
    def attr_vals(self):
        return self.get_vals(unordered=True, elem_type='attribute')

    @property
    def attr_svals(self):
        return self.get_vals(elem_type='attribute')

    @property
    def nodes(self):
        return self.get_elems(elem_type='node')

    @property
    def node_vals(self):
        return self.get_vals(unordered=True, elem_type='node')

    @property
    def node_svals(self):
        return self.get_vals(elem_type='node')

    def __iter__(self):
        return self

    def __next__(self):
        if self._i < self.len:
            i = self._i
            self._i += 1
            return self.vals[i]
        else:
            raise StopIteration

    next = __next__

    def ls(self, name_or_num=None, show_path=False, sort_by=None,
           unordered=False, elem_type=None, **kwargs):
        """
        List and print elements of the Node object.  If `name_or_num` is not
        None, then return the element that matches.

        :param name_or_num: element name or number.  The name has higher
                            precedence than number.
        :param show_path: whether to show path to the element.
        :param sort_by: the name of the sorting key.  If it is None, then the
                        sorting key is the element name.  If it is a name, then
                        the content of the attribute with this name is used as
                        the key.
        :param unordered: whether to present elements unordered.  If it is
                          True, the original order in the document is used.
        :param elem_type: the element type.  If None, then all types are
                          included. Otherwise, it is one of "file",
                          "directory", "node", and "attribute".

        :return: the element that matches `name_or_num` (if it is not None)
        """
        if show_path and not self.is_root:
            self._print_path()
        if name_or_num is None:
            self._ls_all(show_path, sort_by, unordered, elem_type)
        else:
            elem = None
            try:
                name_or_num = int(name_or_num)
            except ValueError:
                pass
            if isinstance(name_or_num, int):
                if str(name_or_num) in self.elems:
                    elem = self.get_elem_by_name(name_or_num)
                else:
                    elem = self.get_elem_by_num(
                        name_or_num, sort_by, unordered, elem_type)
            else:
                elem = self.get_elem_by_name(name_or_num)
            return elem

    def _ls_all(self, show_path, sort_by, unordered, elem_type):
        try:
            indent = ''
            if show_path:
                indent = INDENT_UNIT * self.level
            vals = self.get_vals(sort_by, unordered, elem_type)
            width = len(str(len(vals)))
            fmt = '%s%{}d [%s] %s'.format(width)
            for num, elem in enumerate(vals, start=1):
                if not configs.short_output:
                    self.lines.append(
                        fmt % (indent, num, elem.type[0], elem.name))
                else:
                    self.lines.append(elem.name)
        finally:
            self.flush_lines()

    @property
    def len(self):
        if self._len is None:
            self._len = len(self.elems)
        return self._len

    def get_elem_by_name(self, name):
        try:
            return self.elems[name]
        except KeyError:
            raise ElemError(
                'element "%s" does not exist in this %s' % (
                    name, self.type.lower()))

    def get_elem_by_num(self, num, sort_by, unordered, elem_type):
        vals = self.get_vals(sort_by, unordered, elem_type)
        try:
            return vals[num - 1] if vals else None
        except IndexError:
            raise ElemError(
                'element index out of range (1-%d)' % len(vals))

    def _print_path(self):
        indent = INDENT_UNIT * (self.level - 1)
        self.lines.append('%s%s' % (indent, self.name))

    def get_elems(self, elem_type=None):
        """
        The generic method to get elements.

        :param elem_type: the element type.  If None, then all types are
                          included. Otherwise, it is one of "file",
                          "directory", "node", and "attribute".
        """
        elems = self.elems
        if elem_type is not None:
            items = self.elems.items()
            if elem_type not in ('file', 'directory', 'node', 'attribute'):
                raise NodeError('unknown element type')
            elem_class = getattr(sys.modules[__name__], elem_type.title())
            items = filter(lambda x: isinstance(x[1], elem_class), items)
            elems = OrderedDict(items)
        return elems

    def get_vals(self, sort_by=None, unordered=False, elem_type=None):
        """
        The generic method to get element values.

        :param sort_by: the name of the sorting key.  If it is None and
                        `unordered` is False, then the sorting key is the
                        element name.  If it is a name, then the content of the
                        attribute with this name is used as the key.
        :param unordered: whether to present elements unordered.  If it is
                          True, the original order in the document is used, and
                          `sort_by` has no effect.
        :param elem_type: the element type.  If None, then all types are
                          included. Otherwise, it is one of "file",
                          "directory", "node", and "attribute".
        """
        vals = self.vals
        if elem_type is not None:
            if elem_type not in ('file', 'directory', 'node', 'attribute'):
                raise NodeError('unknown element type')
            elem_class = getattr(sys.modules[__name__], elem_type.title())
            vals = filter(lambda elem: isinstance(elem, elem_class), vals)

        if unordered:
            return vals

        if sort_by is None:
            return sorted(vals, key=attrgetter('name'))

        def sort_key(elem):
            if getattr(elem, 'attrs'):
                return elem.attrs.get(sort_by)
            return None

        return sorted(self.vals, key=sort_key)

    def add(self, name, content):
        """
        Create an element with name and content and add it to this node.
        """
        if name not in self.elems:
            self.content[name] = content
            elem, this_is_dir, this_is_file = self._make_elem(name, content)
            self._elems[name] = elem
            self._update_class(this_is_dir, this_is_file)
            # update vals
            self._vals = self.elems.values()
        else:
            raise NodeError(
                'element "%s" already exists in this %s' % (
                    name, self.type.lower()))

    def delete(self, name):
        """Delete an element with name in this node."""
        if name in self.elems:
            this_is_dir, this_is_file = self._delete_elem(name)
            self._update_class(this_is_dir, this_is_file)
            # update vals
            self._vals = self.elems.values()
        else:
            raise NodeError(
                'element "%s" does not exist in this %s' % (
                    name, self.type.lower()))

    def _delete_elem(self, name):
        this_is_dir = self.is_dir
        this_is_file = self.is_file

        del self._elems[name]
        del self.content[name]

        if not self.content:
            # add a placeholder to keep this node as a file
            self.add(PLACEHOLDER, True)

        # check remaining elements
        for elem in self.elems:
            if self.elems[elem].is_attr:
                this_is_file = True
            if self.elems[elem].is_node:
                this_is_dir = True

        return this_is_dir, this_is_file