File: attributes.py

package info (click to toggle)
python-gffutils 0.13-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 10,164 kB
  • sloc: python: 5,557; makefile: 57; sh: 13
file content (104 lines) | stat: -rw-r--r-- 2,821 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import collections

try:
    collectionsAbc = collections.abc
except AttributeError:
    collectionsAbc = collections
from gffutils import constants


# collections.MutableMapping is apparently the best way to provide dict-like
# interface (http://stackoverflow.com/a/3387975)
class Attributes(collectionsAbc.MutableMapping):
    def __init__(self, *args, **kwargs):
        """
        An Attributes object acts much like a dictionary.  However, values are
        always stored internally as lists, even if a single value is provided.

        Whether or not you get a list back depends on the
        `constants.always_return_list` setting, which can be set on-the-fly.
        If True, then one-item lists are returned.  This is best shown with an
        example:

        Set up an Attributes object:

            >>> attr = Attributes()

        Set the "Name" attribute with a string:

            >>> attr['Name'] = 'gene1'

        This is stored internally as a list, and by default, we'll get a list
        back:

            >>> assert attr['Name'] == ['gene1']

        The same thing happens if we set it with a list in the first place:

            >>> attr['Name'] = ['gene1']
            >>> assert attr['Name'] == ['gene1']

        Now, change the setting so that upon access, single-value lists are
        returned as the first item.

            >>> constants.always_return_list = False
            >>> assert attr['Name'] == 'gene1'

        Change it back again:

            >>> constants.always_return_list = True
            >>> assert attr['Name'] == ['gene1']

        """
        self._d = dict()
        self.update(*args, **kwargs)

    def __setitem__(self, k, v):
        if not isinstance(v, (list, tuple)):
            v = [v]
        self._d[k] = v

    def __getitem__(self, k):
        v = self._d[k]
        if constants.always_return_list:
            return v
        if isinstance(v, list) and len(v) == 1:
            v = v[0]
        return v

    def __delitem__(self, key):
        del self._d[key]

    def __iter__(self):
        return iter(self.keys())

    def __len__(self):
        return len(self._d)

    def keys(self):
        return self._d.keys()

    def values(self):
        return [self.__getitem__(k) for k in self.keys()]

    def items(self):
        r = []
        for k in self.keys():
            r.append((k, self.__getitem__(k)))
        return r

    def __str__(self):
        s = []
        for i in self.items():
            s.append("%s: %s" % i)
        return "\n".join(s)

    def update(self, *args, **kwargs):
        for k, v in dict(*args, **kwargs).items():
            self[k] = v


# Useful for profiling: which dictionary-like class to store attributes in.
# This is used in Feature below and in parser.py

dict_class = Attributes