As per John's request, this patch allows lossless round-tripping of
Python datetime.datetime objects.

Unfortunately, the xmlrpclib dumps() and loads() functions use funny
wrapper objects like xmlrpclib.DateTime rather than directly serializing
to/from standard Python types like datetime.datetime.  This makes
lossless round-tripping pretty cumbersome to implement.

Doing a loads(foo, use_datetime=True) would work, but the `use_datetime`
kwarg is only available in Python2.5 and newer, so I instead extended my
xml_wrap() and xml_unwrap() functions.


>From 92ce9fa408f4b2e05cb61e3e40498b56cb709960 Mon Sep 17 00:00:00 2001
From: Jason Gerard DeRose <jder...@redhat.com>
Date: Wed, 2 Dec 2009 21:41:24 -0700
Subject: [PATCH] Allow lossless round-trip of datetime objects over XML-RPC

---
 ipalib/rpc.py                 |    9 +++++++--
 tests/test_ipalib/test_rpc.py |   28 +++++++++++++++++++++++++---
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/ipalib/rpc.py b/ipalib/rpc.py
index 62f1d77..61af52d 100644
--- a/ipalib/rpc.py
+++ b/ipalib/rpc.py
@@ -35,7 +35,10 @@ import threading
 import socket
 import os
 import errno
-from xmlrpclib import Binary, Fault, dumps, loads, ServerProxy, Transport, ProtocolError
+from datetime import datetime
+from xmlrpclib import dumps, loads
+from xmlrpclib import Binary, Fault, DateTime, ProtocolError
+from xmlrpclib import ServerProxy, Transport
 import kerberos
 from ipalib.backend import Connectible
 from ipalib.errors import public_errors, PublicError, UnknownError, NetworkError
@@ -89,7 +92,7 @@ def xml_wrap(value):
         )
     if type(value) is str:
         return Binary(value)
-    assert type(value) in (unicode, int, float, bool, NoneType)
+    assert type(value) in (unicode, int, float, bool, datetime, NoneType)
     return value
 
 
@@ -122,6 +125,8 @@ def xml_unwrap(value, encoding='UTF-8'):
     if isinstance(value, Binary):
         assert type(value.data) is str
         return value.data
+    if isinstance(value, DateTime):
+        return datetime(*value.timetuple()[0:6])
     assert type(value) in (unicode, int, float, bool, NoneType)
     return value
 
diff --git a/tests/test_ipalib/test_rpc.py b/tests/test_ipalib/test_rpc.py
index d5dd38c..ea0620f 100644
--- a/tests/test_ipalib/test_rpc.py
+++ b/tests/test_ipalib/test_rpc.py
@@ -22,7 +22,8 @@ Test the `ipalib.rpc` module.
 """
 
 import threading
-from xmlrpclib import Binary, Fault, dumps, loads, ServerProxy
+from xmlrpclib import Binary, DateTime, Fault, dumps, loads, ServerProxy
+from datetime import datetime
 from tests.util import raises, assert_equal, PluginTester, DummyClass
 from tests.data import binary_bytes, utf8_bytes, unicode_str
 from ipalib.frontend import Command
@@ -53,6 +54,9 @@ def test_round_trip():
     This tests the two functions together with ``xmlrpclib.dumps()`` and
     ``xmlrpclib.loads()`` in a full wrap/dumps/loads/unwrap round trip.
     """
+    dt_utc = datetime.utcfromtimestamp(1234567890)
+    dt_loc = datetime.fromtimestamp(1234567890)
+
     # We first test that our assumptions about xmlrpclib module in the Python
     # standard library are correct:
     assert_equal(dump_n_load(utf8_bytes), unicode_str)
@@ -65,6 +69,13 @@ def test_round_trip():
     assert_equal(dump_n_load(u''), '')
     assert dump_n_load(None) is None
 
+    dnl_utc = dump_n_load(dt_utc)
+    assert_equal(dnl_utc, DateTime(dt_utc))
+    assert isinstance(dnl_utc, DateTime)
+    dnl_loc = dump_n_load(dt_loc)
+    assert_equal(dnl_loc, DateTime(1234567890))
+    assert isinstance(dnl_loc, DateTime)
+
     # Now we test our wrap and unwrap methods in combination with dumps, loads:
     # All str should come back str (because they get wrapped in
     # xmlrpclib.Binary().  All unicode should come back unicode because str
@@ -78,8 +89,19 @@ def test_round_trip():
     assert_equal(round_trip(''), '')
     assert_equal(round_trip(u''), u'')
     assert round_trip(None) is None
-    compound = [utf8_bytes, None, binary_bytes, (None, unicode_str),
-        dict(utf8=utf8_bytes, chars=unicode_str, data=binary_bytes)
+
+    assert_equal(round_trip(dt_utc), dt_utc)
+    assert isinstance(dt_utc, datetime)
+    assert_equal(round_trip(dt_loc), dt_loc)
+    assert isinstance(dt_loc, datetime)
+
+    compound = [utf8_bytes, None, binary_bytes, (None, unicode_str), dt_loc,
+        dict(
+            utf8=utf8_bytes,
+            chars=unicode_str,
+            data=binary_bytes,
+            datetime=dt_utc,
+        ),
     ]
     assert round_trip(compound) == tuple(compound)
 
-- 
1.6.3.3

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to