Repository: rapidpro/rapidpro-python

Issue:
Null DatetimeField raises an exception upon serialisation request
Objects with DatetimeField attributes cannot be properly serialised when any of their DatetimeField attributes is not set (i.e. set to null in the JSON response).  This makes the following scenario possible:

1. fetch data from the server (e.g. TembaClient(...).get_runs()) - the data is internally deserialised by rapidpro-python
2. fed the result of this deserialisation process back to rapidpro-python to have it (re)serialised
3. error (please see the example traceback below)

```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ego/.virtualenvs/rapidpro-python/local/lib/python2.7/site-packages/temba_client/serialization.py", line 63, in serialize
    field_value = field.serialize(attr_value)
  File "/home/ego/.virtualenvs/rapidpro-python/local/lib/python2.7/site-packages/temba_client/serialization.py", line 148, in serialize
    return [self.item_class.serialize(item) for item in value]
  File "/home/ego/.virtualenvs/rapidpro-python/local/lib/python2.7/site-packages/temba_client/serialization.py", line 63, in serialize
    field_value = field.serialize(attr_value)
  File "/home/ego/.virtualenvs/rapidpro-python/local/lib/python2.7/site-packages/temba_client/serialization.py", line 122, in serialize
    return format_iso8601(value)
  File "/home/ego/.virtualenvs/rapidpro-python/local/lib/python2.7/site-packages/temba_client/utils.py", line 40, in format_iso8601
    return six.text_type(value.astimezone(pytz.UTC).strftime(_format))
AttributeError: 'NoneType' object has no attribute 'astimezone'
```

Discussion:

Patch:
diff --git a/temba_client/utils.py b/temba_client/utils.py
index 39a3a2a..2489884 100644
--- a/temba_client/utils.py
+++ b/temba_client/utils.py
@@ -33,8 +33,11 @@ def parse_iso8601(value):
 
 def format_iso8601(value):
     """
-    Formats a datetime as a UTC ISO8601 date
+    Formats a datetime as a UTC ISO8601 date or returns None if value is None
     """
+    if value is None:
+        return None
+
     _format = ISO8601_DATETIME_FORMAT + '.%f'
 
     return six.text_type(value.astimezone(pytz.UTC).strftime(_format))


Test patch:
diff --git a/temba_client/tests.py b/temba_client/tests.py
index d8386f7..e24f86a 100644
--- a/temba_client/tests.py
+++ b/temba_client/tests.py
@@ -72,6 +72,9 @@ class UtilsTest(TembaTest):
         d = datetime.datetime(2014, 1, 2, 3, 4, 5, 6, UtilsTest.TestTZ())
         self.assertEqual(format_iso8601(d), '2014-01-02T08:04:05.000006')
 
+    def test_format_iso8601_should_return_none_when_no_datetime_given(self):
+        self.assertIs(format_iso8601(None), None)
+
     def test_parse_iso8601(self):
         dt = datetime.datetime(2014, 1, 2, 3, 4, 5, 0, pytz.UTC)
         self.assertEqual(parse_iso8601('2014-01-02T03:04:05.000000Z'), dt)