@@ -100,7 +100,8 @@ def test_keepalive_socket_options_are_configured_on_adapter(self):
100100 self .assertIn ((tcp_protocol , tcp_keepidle , TCP_KEEPALIVE_IDLE_TIMEOUT ), socket_options )
101101 if hasattr (socket , "TCP_KEEPINTVL" ):
102102 self .assertIn (
103- (tcp_protocol , socket .TCP_KEEPINTVL , TCP_KEEPALIVE_INTERVAL ), socket_options
103+ (tcp_protocol , socket .TCP_KEEPINTVL , TCP_KEEPALIVE_INTERVAL ),
104+ socket_options ,
104105 )
105106 self .assertEqual (HTTPConnection .default_socket_options , default_socket_options )
106107
@@ -221,7 +222,11 @@ def test_track_with_id_and_timestamp(self):
221222 )
222223
223224 self .cio .track (
224- 1 , "purchase" , {"type" : "socks" }, id = "01HB4HBDKTFWYZCK01DMRSWRFD" , timestamp = 1561231234
225+ 1 ,
226+ "purchase" ,
227+ {"type" : "socks" },
228+ id = "01HB4HBDKTFWYZCK01DMRSWRFD" ,
229+ timestamp = 1561231234 ,
225230 )
226231
227232 def test_track_with_invalid_timestamp (self ):
@@ -444,14 +449,21 @@ def test_device_call_last_used(self):
444449 "content_type" : "application/json" ,
445450 "url_suffix" : "/customers/1/devices" ,
446451 "body" : {
447- "device" : {"id" : "device_2" , "platform" : "android" , "last_used" : 1234567890 }
452+ "device" : {
453+ "id" : "device_2" ,
454+ "platform" : "android" ,
455+ "last_used" : 1234567890 ,
456+ }
448457 },
449458 },
450459 )
451460 )
452461
453462 self .cio .add_device (
454- customer_id = 1 , device_id = "device_2" , platform = "android" , last_used = 1234567890
463+ customer_id = 1 ,
464+ device_id = "device_2" ,
465+ platform = "android" ,
466+ last_used = 1234567890 ,
455467 )
456468
457469 def test_device_call_valid_platform (self ):
@@ -566,6 +578,57 @@ def test_sanitize(self):
566578 data_out = self .cio ._sanitize (data_in )
567579 self .assertEqual (data_out , dict (dt = 1234567890 ))
568580
581+ def test_sanitize_nested_dict_datetime (self ):
582+ from datetime import timezone
583+
584+ data_in = {"event" : {"created_at" : datetime (2009 , 2 , 13 , 23 , 31 , 30 , 0 , timezone .utc )}}
585+ data_out = self .cio ._sanitize (data_in )
586+ self .assertEqual (data_out , {"event" : {"created_at" : 1234567890 }})
587+
588+ def test_sanitize_list_datetime (self ):
589+ from datetime import timezone
590+
591+ data_in = {
592+ "dates" : [
593+ datetime (2009 , 2 , 13 , 23 , 31 , 30 , 0 , timezone .utc ),
594+ datetime (2024 , 1 , 1 , 0 , 0 , 0 , 0 , timezone .utc ),
595+ ]
596+ }
597+ data_out = self .cio ._sanitize (data_in )
598+ self .assertEqual (data_out , {"dates" : [1234567890 , 1704067200 ]})
599+
600+ def test_sanitize_nested_dict_nan (self ):
601+ data_in = {"metrics" : {"score" : float ("nan" ), "count" : 5 }}
602+ data_out = self .cio ._sanitize (data_in )
603+ self .assertEqual (data_out , {"metrics" : {"score" : None , "count" : 5 }})
604+
605+ def test_sanitize_deeply_nested (self ):
606+ from datetime import timezone
607+
608+ data_in = {
609+ "outer" : {
610+ "items" : [
611+ {
612+ "ts" : datetime (2009 , 2 , 13 , 23 , 31 , 30 , 0 , timezone .utc ),
613+ "val" : float ("nan" ),
614+ },
615+ {"ts" : datetime (2024 , 1 , 1 , 0 , 0 , 0 , 0 , timezone .utc ), "val" : 42 },
616+ ],
617+ },
618+ }
619+ data_out = self .cio ._sanitize (data_in )
620+ self .assertEqual (
621+ data_out ,
622+ {
623+ "outer" : {
624+ "items" : [
625+ {"ts" : 1234567890 , "val" : None },
626+ {"ts" : 1704067200 , "val" : 42 },
627+ ],
628+ },
629+ },
630+ )
631+
569632 def test_sanitize_naive_datetime (self ):
570633 """Naive datetimes are assumed UTC (backward compatible)."""
571634 data_in = dict (dt = datetime (2009 , 2 , 13 , 23 , 31 , 30 ))
@@ -647,7 +710,10 @@ def test_merge_customers_call(self):
647710 "authorization" : _basic_auth_str ("siteid" , "apikey" ),
648711 "content_type" : "application/json" ,
649712 "url_suffix" : "/merge_customers" ,
650- "body" : {"primary" : {"cio_id" : "CIO456" }, "secondary" : {"id" : "MyCustomId" }},
713+ "body" : {
714+ "primary" : {"cio_id" : "CIO456" },
715+ "secondary" : {"id" : "MyCustomId" },
716+ },
651717 },
652718 )
653719 )
0 commit comments