Hot-keys 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

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

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

# -*- coding: utf-8 -*- 

""" 

Various types used in ObsPy. 

 

:copyright: 

    The ObsPy Development Team (devs@obspy.org) 

:license: 

    GNU Lesser General Public License, Version 3 

    (http://www.gnu.org/copyleft/lesser.html) 

""" 

 

# try native OrderDict implementations first (Python >= 2.7.x) 

try: 

    from collections import OrderedDict 

except ImportError: 

    # Copyright (c) 2009 Raymond Hettinger 

    # 

    # Permission is hereby granted, free of charge, to any person 

    # obtaining a copy of this software and associated documentation files 

    # (the "Software"), to deal in the Software without restriction, 

    # including without limitation the rights to use, copy, modify, merge, 

    # publish, distribute, sublicense, and/or sell copies of the Software, 

    # and to permit persons to whom the Software is furnished to do so, 

    # subject to the following conditions: 

    # 

    #     The above copyright notice and this permission notice shall be 

    #     included in all copies or substantial portions of the Software. 

    # 

    #     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 

    #     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 

    #     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 

    #     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 

    #     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 

    #     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 

    #     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 

    #     OTHER DEALINGS IN THE SOFTWARE. 

    from UserDict import DictMixin 

 

    class OrderedDict(dict, DictMixin): 

        """ 

        Dictionary that remembers insertion order. 

        """ 

        def __init__(self, *args, **kwds): 

            if len(args) > 1: 

                msg = 'expected at most 1 arguments, got %d' 

                raise TypeError(msg % len(args)) 

            try: 

                self.__end 

            except AttributeError: 

                self.clear() 

            self.update(*args, **kwds) 

 

        def clear(self): 

            self.__end = end = [] 

            end += [None, end, end]      # sentinel node for doubly linked list 

            self.__map = {}              # key --> [key, prev, next] 

            dict.clear(self) 

 

        def __setitem__(self, key, value): 

            if key not in self: 

                end = self.__end 

                curr = end[1] 

                curr[2] = end[1] = self.__map[key] = [key, curr, end] 

            dict.__setitem__(self, key, value) 

 

        def __delitem__(self, key): 

            dict.__delitem__(self, key) 

            key, prev, next = self.__map.pop(key) 

            prev[2] = next 

            next[1] = prev 

 

        def __iter__(self): 

            end = self.__end 

            curr = end[2] 

            while curr is not end: 

                yield curr[0] 

                curr = curr[2] 

 

        def __reversed__(self): 

            end = self.__end 

            curr = end[1] 

            while curr is not end: 

                yield curr[0] 

                curr = curr[1] 

 

        def popitem(self, last=True): 

            if not self: 

                raise KeyError('dictionary is empty') 

            if last: 

                key = reversed(self).next() 

            else: 

                key = iter(self).next() 

            value = self.pop(key) 

            return key, value 

 

        def __reduce__(self): 

            items = [[k, self[k]] for k in self] 

            tmp = self.__map, self.__end 

            del self.__map, self.__end 

            inst_dict = vars(self).copy() 

            self.__map, self.__end = tmp 

            if inst_dict: 

                return (self.__class__, (items,), inst_dict) 

            return self.__class__, (items,) 

 

        def keys(self): 

            return list(self) 

 

        setdefault = DictMixin.setdefault 

        update = DictMixin.update 

        pop = DictMixin.pop 

        values = DictMixin.values 

        items = DictMixin.items 

        iterkeys = DictMixin.iterkeys 

        itervalues = DictMixin.itervalues 

        iteritems = DictMixin.iteritems 

 

        def __repr__(self): 

            if not self: 

                return '%s()' % (self.__class__.__name__,) 

            return '%s(%r)' % (self.__class__.__name__, self.items()) 

 

        def copy(self): 

            return self.__class__(self) 

 

        @classmethod 

        def fromkeys(cls, iterable, value=None): 

            d = cls() 

            for key in iterable: 

                d[key] = value 

            return d 

 

        def __eq__(self, other): 

            if isinstance(other, OrderedDict): 

                if len(self) != len(other): 

                    return False 

                for p, q in  zip(self.items(), other.items()): 

                    if p != q: 

                        return False 

                return True 

            return dict.__eq__(self, other) 

 

        def __ne__(self, other): 

            return not self == other 

 

 

class Enum(object): 

    """ 

    Enumerated type (enum) implementation for Python. 

 

    :type enums: list of str 

 

    .. rubric:: Example 

 

    >>> from obspy.core.util import Enum 

    >>> units = Enum(["m", "s", "m/s", "m/(s*s)", "m*s", "other"]) 

 

    There are different ways to access the correct enum values: 

 

        >>> units.get('m/s') 

        'm/s' 

        >>> units['S'] 

        's' 

        >>> units.OTHER 

        'other' 

        >>> units[3] 

        'm/(s*s)' 

        >>> units.xxx  # doctest: +ELLIPSIS 

        Traceback (most recent call last): 

        ... 

        KeyError: 'xxx' 

 

    Changing enum values will not work: 

 

        >>> units.m = 5  # doctest: +ELLIPSIS 

        Traceback (most recent call last): 

        ... 

        NotImplementedError 

        >>> units['m'] = 'xxx'  # doctest: +ELLIPSIS 

        Traceback (most recent call last): 

        ... 

        NotImplementedError 

 

    Calling with a value will either return the mapped enum value or ``None``: 

 

        >>> units("M*s") 

        'm*s' 

        >>> units('xxx') 

        >>> units(5) 

        'other' 

    """ 

    # marker needed for for usage within ABC classes 

    __isabstractmethod__ = False 

 

    def __init__(self, enums): 

        self.__enums = OrderedDict(zip([str(e).lower() for e in enums], enums)) 

 

    def __call__(self, enum): 

        try: 

            return self.get(enum) 

        except: 

            return None 

 

    def get(self, key): 

        if isinstance(key, int): 

            return self.__enums.values()[key] 

        return self.__enums.__getitem__(key.lower()) 

 

    __getattr__ = get 

    __getitem__ = get 

 

    def set(self, name, value): 

        if name == '_Enum__enums': 

            self.__dict__[name] = value 

            return 

        raise NotImplementedError 

 

    __setattr__ = set 

    __setitem__ = set 

 

    def __contains__(self, value): 

        return value.lower() in self.__enums 

 

    def values(self): 

        return self.__enums.values() 

 

    def keys(self): 

        return self.__enums.keys() 

 

    def items(self): 

        return self.__enums.items() 

 

    def iteritems(self): 

        return self.__enums.iteritems() 

 

    def __str__(self): 

        """ 

        >>> enum = Enum(["c", "a", "b"]) 

        >>> print enum 

        Enum(["c", "a", "b"]) 

        """ 

        keys = self.__enums.keys() 

        return "Enum([%s])" % ", ".join(['"%s"' % _i for _i in keys]) 

 

 

if __name__ == '__main__': 

    import doctest 

    doctest.testmod(exclude_empty=True)