~ubuntu-branches/ubuntu/utopic/pywbem/utopic-updates

« back to all changes in this revision

Viewing changes to cim_types.py

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2009-07-28 17:23:55 UTC
  • Revision ID: james.westby@ubuntu.com-20090728172355-f9kv7x14t3ya4ifb
Tags: upstream-0.7.0
ImportĀ upstreamĀ versionĀ 0.7.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# (C) Copyright 2003, 2004 Hewlett-Packard Development Company, L.P.
 
3
# (C) Copyright 2006, 2007 Novell, Inc. 
 
4
#
 
5
# This program is free software; you can redistribute it and/or modify
 
6
# it under the terms of the GNU Lesser General Public License as
 
7
# published by the Free Software Foundation; either version 2 of the
 
8
# License.
 
9
#   
 
10
# This program is distributed in the hope that it will be useful, but
 
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
# Lesser General Public License for more details.
 
14
#   
 
15
# You should have received a copy of the GNU Lesser General Public
 
16
# License along with this program; if not, write to the Free Software
 
17
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
18
#
 
19
 
 
20
# Author: Tim Potter <tpot@hp.com>
 
21
# Author: Bart Whiteley <bwhiteley@suse.de>
 
22
 
 
23
"""
 
24
Subclasses of builtin Python types to remember CIM types.  This is
 
25
necessary as we need to remember whether an integer property is a
 
26
uint8, uint16, uint32 etc, while still being able to treat it as a
 
27
integer.
 
28
"""
 
29
 
 
30
from datetime import tzinfo, datetime, timedelta
 
31
import re
 
32
 
 
33
class MinutesFromUTC(tzinfo):
 
34
    """Fixed offset in minutes from UTC."""
 
35
    def __init__(self, offset):
 
36
        self.__offset = timedelta(minutes = offset)
 
37
    def utcoffset(self, dt):
 
38
        return self.__offset
 
39
    def dst(self, dt):
 
40
        return timedelta(0)
 
41
 
 
42
class CIMType(object):
 
43
    """Base type for all CIM types."""
 
44
    
 
45
class CIMDateTime(CIMType) :
 
46
    """A CIM DateTime."""
 
47
 
 
48
    def __init__(self, dtarg):
 
49
        """Construct a new CIMDateTime
 
50
 
 
51
        Arguments:
 
52
        dtarg -- Can be a string in CIM datetime format, a datetime.datetime, 
 
53
            or a datetime.timedelta. 
 
54
 
 
55
        """
 
56
 
 
57
        self.cimtype = 'datetime'
 
58
        self.__timedelta = None
 
59
        self.__datetime = None
 
60
        if isinstance(dtarg, basestring):
 
61
            date_pattern = re.compile(r'^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\.(\d{6})([+|-])(\d{3})')
 
62
            s = date_pattern.search(dtarg)
 
63
            if s is not None:
 
64
                g = s.groups()
 
65
                offset = int(g[8])
 
66
                if g[7] == '-':
 
67
                    offset = -offset
 
68
                self.__datetime = datetime(int(g[0]), int(g[1]), 
 
69
                                           int(g[2]), int(g[3]), 
 
70
                                           int(g[4]), int(g[5]), 
 
71
                                           int(g[6]), MinutesFromUTC(offset))
 
72
            else:
 
73
                tv_pattern = re.compile(r'^(\d{8})(\d{2})(\d{2})(\d{2})\.(\d{6})(:)(000)')
 
74
                s = tv_pattern.search(dtarg)
 
75
                if s is None:
 
76
                    raise ValueError('Invalid Datetime format "%s"' % dtarg)
 
77
                else:
 
78
                    g = s.groups()
 
79
                    self.__timedelta =  timedelta(days=int(g[0]),
 
80
                                                  hours=int(g[1]),
 
81
                                                  minutes=int(g[2]),
 
82
                                                  seconds=int(g[3]),
 
83
                                                  microseconds=int(g[4]))
 
84
        elif isinstance(dtarg, datetime):
 
85
            self.__datetime = dtarg; 
 
86
        elif isinstance(dtarg, timedelta):
 
87
            self.__timedelta = dtarg
 
88
        elif isinstance(dtarg, CIMDateTime):
 
89
            self.__datetime = dtarg.__datetime
 
90
            self.__timedelta = dtarg.__timedelta
 
91
        else:
 
92
            raise ValueError('Expected datetime, timedelta, or string')
 
93
 
 
94
    @property
 
95
    def minutes_from_utc(self):
 
96
        """Return the timezone as +/- minutes from UTC"""
 
97
        offset = 0
 
98
        if self.__datetime is not None and \
 
99
                self.__datetime.utcoffset() is not None:
 
100
            offset = self.__datetime.utcoffset().seconds / 60
 
101
            if self.__datetime.utcoffset().days == -1:
 
102
                offset = -(60*24 - offset)
 
103
        return offset
 
104
 
 
105
    @property
 
106
    def datetime(self):
 
107
        return self.__datetime
 
108
 
 
109
    @property
 
110
    def timedelta(self):
 
111
        return self.__timedelta
 
112
 
 
113
    @property
 
114
    def is_interval(self):
 
115
        return self.__timedelta is not None
 
116
 
 
117
    @staticmethod
 
118
    def get_local_utcoffset():
 
119
        """Return minutes +/- UTC for the local timezone"""
 
120
        utc = datetime.utcnow()
 
121
        local = datetime.now()
 
122
        if local < utc:
 
123
            return - int(float((utc - local).seconds) / 60 + .5)
 
124
        else:
 
125
            return int(float((local - utc).seconds) / 60 + .5)
 
126
 
 
127
    @classmethod
 
128
    def now(cls, tzi=None):
 
129
        if tzi is None:
 
130
            tzi = MinutesFromUTC(cls.get_local_utcoffset())
 
131
        return cls(datetime.now(tzi))
 
132
 
 
133
    @classmethod
 
134
    def fromtimestamp(cls, ts, tzi=None):
 
135
        if tzi is None:
 
136
            tzi = MinutesFromUTC(cls.get_local_utcoffset())
 
137
        return cls(datetime.fromtimestamp(ts, tzi))
 
138
 
 
139
    def __str__ (self):
 
140
        if self.is_interval:
 
141
            hour = self.__timedelta.seconds / 3600
 
142
            minute = (self.__timedelta.seconds - hour * 3600) / 60
 
143
            second = self.__timedelta.seconds - hour * 3600 - minute * 60
 
144
            return '%08d%02d%02d%02d.%06d:000' % \
 
145
                    (self.__timedelta.days, hour, minute, second, 
 
146
                            self.__timedelta.microseconds)
 
147
        else:
 
148
            offset = self.minutes_from_utc
 
149
            sign = '+'
 
150
            if offset < 0:
 
151
                sign = '-'
 
152
                offset = -offset
 
153
            return '%d%02d%02d%02d%02d%02d.%06d%s%03d' % \
 
154
                   (self.__datetime.year, self.__datetime.month, 
 
155
                    self.__datetime.day, self.__datetime.hour,
 
156
                    self.__datetime.minute, self.__datetime.second, 
 
157
                    self.__datetime.microsecond, sign, offset)
 
158
 
 
159
    def __repr__ (self):
 
160
        return '%s(%s)'%(self.__class__.__name__, `str(self)`)
 
161
 
 
162
    def __getstate__(self):
 
163
        return str(self)
 
164
 
 
165
    def __setstate__(self, arg):
 
166
        self.__init__(arg)
 
167
 
 
168
    def __cmp__(self, other):
 
169
        if self is other:
 
170
            return 0
 
171
        elif not isinstance(other, CIMDateTime):
 
172
            return 1
 
173
        return (cmp(self.__datetime, other.__datetime) or 
 
174
                cmp(self.__timedelta, other.__timedelta))
 
175
 
 
176
 
 
177
# CIM integer types
 
178
 
 
179
class CIMInt(CIMType, long):
 
180
    pass
 
181
 
 
182
class Uint8(CIMInt):
 
183
    cimtype = 'uint8'
 
184
 
 
185
class Sint8(CIMInt):
 
186
    cimtype = 'sint8'
 
187
 
 
188
class Uint16(CIMInt):
 
189
    cimtype = 'uint16'
 
190
 
 
191
class Sint16(CIMInt):
 
192
    cimtype = 'sint16'
 
193
 
 
194
class Uint32(CIMInt):
 
195
    cimtype = 'uint32'
 
196
 
 
197
class Sint32(CIMInt):
 
198
    cimtype = 'sint32'
 
199
 
 
200
class Uint64(CIMInt):
 
201
    cimtype = 'uint64'
 
202
 
 
203
class Sint64(CIMInt):
 
204
    cimtype = 'sint64'
 
205
 
 
206
# CIM float types
 
207
 
 
208
class CIMFloat(CIMType, float):
 
209
    pass
 
210
 
 
211
class Real32(CIMFloat):
 
212
    cimtype = 'real32'
 
213
 
 
214
class Real64(CIMFloat):
 
215
    cimtype = 'real64'
 
216
 
 
217
def cimtype(obj):
 
218
    """Return the CIM type name of an object as a string.  For a list, the
 
219
    type is the type of the first element as CIM arrays must be
 
220
    homogeneous."""
 
221
    
 
222
    if isinstance(obj, CIMType):
 
223
        return obj.cimtype
 
224
 
 
225
    if isinstance(obj, bool):
 
226
        return 'boolean'
 
227
 
 
228
    if isinstance(obj, (str, unicode)):
 
229
        return 'string'
 
230
 
 
231
    if isinstance(obj, list):
 
232
        return cimtype(obj[0])
 
233
 
 
234
    if isinstance(obj, (datetime, timedelta)):
 
235
        return 'datetime'
 
236
 
 
237
    raise TypeError("Invalid CIM type for %s" % str(obj))
 
238
 
 
239
 
 
240
 
 
241
def atomic_to_cim_xml(obj):
 
242
    """Convert an atomic type to CIM external form"""
 
243
    if isinstance(obj, bool):
 
244
        if obj:
 
245
            return "true"
 
246
        else:
 
247
            return "false"
 
248
 
 
249
    elif isinstance(obj, CIMDateTime):
 
250
        return unicode(obj)
 
251
 
 
252
    elif isinstance(obj, datetime):
 
253
        return unicode(CIMDateTime(obj))
 
254
 
 
255
    elif obj is None:
 
256
        return obj
 
257
    elif cimtype(obj) == 'real32':
 
258
        return u'%.8E' % obj
 
259
    elif cimtype(obj) == 'real64':
 
260
        return u'%.16E' % obj
 
261
    else:
 
262
        return unicode(obj)
 
263