summaryrefslogtreecommitdiff
path: root/sleekxmpp/thirdparty
diff options
context:
space:
mode:
authorLance Stout <lancestout@gmail.com>2011-08-04 20:20:22 -0700
committerLance Stout <lancestout@gmail.com>2011-08-04 20:22:07 -0700
commit4d8933abdf4a190493f2762d423f469f6d8b30a9 (patch)
treee538d4b0c390b54e411e3d67f8fb09ff3ab28bd5 /sleekxmpp/thirdparty
parent6eac0606cf5cd0b7777eb86b77ed1b061dd4b658 (diff)
downloadslixmpp-4d8933abdf4a190493f2762d423f469f6d8b30a9.tar.gz
slixmpp-4d8933abdf4a190493f2762d423f469f6d8b30a9.tar.bz2
slixmpp-4d8933abdf4a190493f2762d423f469f6d8b30a9.tar.xz
slixmpp-4d8933abdf4a190493f2762d423f469f6d8b30a9.zip
Actually, we can work around needing dateutil.
If dateutil is present, we'll use that. If not, we'll use some regexes from the fixed_datetime module.
Diffstat (limited to 'sleekxmpp/thirdparty')
-rw-r--r--sleekxmpp/thirdparty/__init__.py1
-rw-r--r--sleekxmpp/thirdparty/mini_dateutil.py267
2 files changed, 268 insertions, 0 deletions
diff --git a/sleekxmpp/thirdparty/__init__.py b/sleekxmpp/thirdparty/__init__.py
index 3eb6ad73..1c7bf651 100644
--- a/sleekxmpp/thirdparty/__init__.py
+++ b/sleekxmpp/thirdparty/__init__.py
@@ -4,3 +4,4 @@ except:
from sleekxmpp.thirdparty.ordereddict import OrderedDict
from sleekxmpp.thirdparty import suelta
+from sleekxmpp.thirdparty.mini_dateutil import tzutc, tzoffset, parse_iso
diff --git a/sleekxmpp/thirdparty/mini_dateutil.py b/sleekxmpp/thirdparty/mini_dateutil.py
new file mode 100644
index 00000000..bfb86305
--- /dev/null
+++ b/sleekxmpp/thirdparty/mini_dateutil.py
@@ -0,0 +1,267 @@
+# This module is a very stripped down version of the dateutil
+# package for when dateutil has not been installed. As a replacement
+# for dateutil.parser.parse, the parsing methods from
+# http://blog.mfabrik.com/2008/06/30/relativity-of-time-shortcomings-in-python-datetime-and-workaround/
+
+#As such, the following copyrights and licenses applies:
+
+
+# dateutil - Extensions to the standard python 2.3+ datetime module.
+#
+# Copyright (c) 2003-2011 - Gustavo Niemeyer <gustavo@niemeyer.net>
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+# fixed_dateime
+#
+# Copyright (c) 2008, Red Innovation Ltd., Finland
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Red Innovation nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY RED INNOVATION ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL RED INNOVATION BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+import re
+import datetime
+
+
+ZERO = datetime.timedelta(0)
+
+
+try:
+ from dateutil.parser import parse as parse_iso
+ from dateutil.tz import tzoffset, tzutc
+except:
+ # As a stopgap, define the two timezones here based
+ # on the dateutil code.
+
+ class tzutc(datetime.tzinfo):
+
+ def utcoffset(self, dt):
+ return ZERO
+
+ def dst(self, dt):
+ return ZERO
+
+ def tzname(self, dt):
+ return "UTC"
+
+ def __eq__(self, other):
+ return (isinstance(other, tzutc) or
+ (isinstance(other, tzoffset) and other._offset == ZERO))
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __repr__(self):
+ return "%s()" % self.__class__.__name__
+
+ __reduce__ = object.__reduce__
+
+ class tzoffset(datetime.tzinfo):
+
+ def __init__(self, name, offset):
+ self._name = name
+ self._offset = datetime.timedelta(seconds=offset)
+
+ def utcoffset(self, dt):
+ return self._offset
+
+ def dst(self, dt):
+ return ZERO
+
+ def tzname(self, dt):
+ return self._name
+
+ def __eq__(self, other):
+ return (isinstance(other, tzoffset) and
+ self._offset == other._offset)
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __repr__(self):
+ return "%s(%s, %s)" % (self.__class__.__name__,
+ repr(self._name),
+ self._offset.days*86400+self._offset.seconds)
+
+ __reduce__ = object.__reduce__
+
+
+ _fixed_offset_tzs = { }
+ UTC = tzutc()
+
+ def _get_fixed_offset_tz(offsetmins):
+ """For internal use only: Returns a tzinfo with
+ the given fixed offset. This creates only one instance
+ for each offset; the zones are kept in a dictionary"""
+
+ if offsetmins == 0:
+ return UTC
+
+ if not _fixed_offset_tzs.has_key(offsetmins):
+ if offsetmins < 0:
+ sign = '-'
+ absoff = -offsetmins
+ else:
+ sign = '+'
+ absoff = offsetmins
+
+ name = "UTC%s%02d:%02d" % (sign, int(absoff / 60), absoff % 60)
+ inst = tzoffset(offsetmins, name)
+ _fixed_offset_tzs[offsetmins] = inst
+
+ return _fixed_offset_tzs[offsetmins]
+
+
+ _iso8601_parser = re.compile("""
+ ^
+ (?P<year> [0-9]{4})?(?P<ymdsep>-?)?
+ (?P<month>[0-9]{2})?(?P=ymdsep)?
+ (?P<day> [0-9]{2})?
+
+ (?: # time part... optional... at least hour must be specified
+ (?:T|\s+)?
+ (?P<hour>[0-9]{2})
+ (?:
+ # minutes, separated with :, or none, from hours
+ (?P<hmssep>[:]?)
+ (?P<minute>[0-9]{2})
+ (?:
+ # same for seconds, separated with :, or none, from hours
+ (?P=hmssep)
+ (?P<second>[0-9]{2})
+ )?
+ )?
+
+ # fractions
+ (?: [,.] (?P<frac>[0-9]{1,10}))?
+
+ # timezone, Z, +-hh or +-hh:?mm. MUST BE, but complain if not there.
+ (
+ (?P<tzempty>Z)
+ |
+ (?P<tzh>[+-][0-9]{2})
+ (?: :? # optional separator
+ (?P<tzm>[0-9]{2})
+ )?
+ )?
+ )?
+ $
+ """, re.X) # """
+
+ def parse_iso(timestamp):
+ """Internal function for parsing a timestamp in
+ ISO 8601 format"""
+
+ timestamp = timestamp.strip()
+
+ m = _iso8601_parser.match(timestamp)
+ if not m:
+ raise ValueError("Not a proper ISO 8601 timestamp!: %s" % timestamp)
+
+ vals = m.groupdict()
+ def_vals = {'year': 1970, 'month': 1, 'day': 1}
+ for key in vals:
+ if vals[key] is None:
+ vals[key] = def_vals.get(key, 0)
+ elif key not in ['ymdsep', 'hmssep', 'tzempty']:
+ vals[key] = int(vals[key])
+
+ year = vals['year']
+ month = vals['month']
+ day = vals['day']
+
+ h, min, s, us = None, None, None, 0
+ frac = 0
+ if m.group('tzempty') == None and m.group('tzh') == None:
+ raise ValueError("Not a proper ISO 8601 timestamp: " +
+ "missing timezone (Z or +hh[:mm])!")
+
+ if m.group('frac'):
+ frac = m.group('frac')
+ power = len(frac)
+ frac = long(frac) / 10.0 ** power
+
+ if m.group('hour'):
+ h = vals['hour']
+
+ if m.group('minute'):
+ min = vals['minute']
+
+ if m.group('second'):
+ s = vals['second']
+
+ if frac != None:
+ # ok, fractions of hour?
+ if min == None:
+ frac, min = _math.modf(frac * 60.0)
+ min = int(min)
+
+ # fractions of second?
+ if s == None:
+ frac, s = _math.modf(frac * 60.0)
+ s = int(s)
+
+ # and extract microseconds...
+ us = int(frac * 1000000)
+
+ if m.group('tzempty') == 'Z':
+ offsetmins = 0
+ else:
+ # timezone: hour diff with sign
+ offsetmins = vals['tzh'] * 60
+ tzm = m.group('tzm')
+
+ # add optional minutes
+ if tzm != None:
+ tzm = long(tzm)
+ offsetmins += tzm if offsetmins > 0 else -tzm
+
+ tz = _get_fixed_offset_tz(offsetmins)
+ return datetime.datetime(year, month, day, h, min, s, us, tz)