@@ -309,6 +309,7 @@ def test_live_start_twice(
309309 with pytest .raises (ValueError ):
310310 live_client .start ()
311311
312+
312313def test_live_start_before_subscribe (
313314 live_client : client .Live ,
314315) -> None :
@@ -318,6 +319,7 @@ def test_live_start_before_subscribe(
318319 with pytest .raises (ValueError ):
319320 live_client .start ()
320321
322+
321323@pytest .mark .parametrize (
322324 "schema" ,
323325 [pytest .param (schema , id = str (schema )) for schema in Schema .variants ()],
@@ -428,6 +430,34 @@ def test_live_stop(
428430 live_client .block_for_close ()
429431
430432
433+ @pytest .mark .usefixtures ("mock_live_server" )
434+ def test_live_shutdown_remove_closed_stream (
435+ tmp_path : pathlib .Path ,
436+ live_client : client .Live ,
437+ ) -> None :
438+ """
439+ Test that closed streams are removed upon disconnection.
440+ """
441+ live_client .subscribe (
442+ dataset = Dataset .GLBX_MDP3 ,
443+ schema = Schema .MBO ,
444+ )
445+
446+ output = tmp_path / "output.dbn"
447+
448+ with output .open ("wb" ) as out :
449+ live_client .add_stream (out )
450+
451+ assert live_client .is_connected () is True
452+
453+ live_client .start ()
454+
455+ live_client .stop ()
456+ live_client .block_for_close ()
457+
458+ assert live_client ._user_streams == {}
459+
460+
431461def test_live_stop_twice (
432462 live_client : client .Live ,
433463) -> None :
@@ -575,6 +605,15 @@ def test_live_add_stream_invalid(
575605 with pytest .raises (ValueError ):
576606 live_client .add_stream (readable_file .open (mode = "rb" ))
577607
608+ def test_live_add_stream_path_directory (
609+ tmp_path : pathlib .Path ,
610+ live_client : client .Live ,
611+ ) -> None :
612+ """
613+ Test that passing a path to a directory raises an OSError.
614+ """
615+ with pytest .raises (OSError ):
616+ live_client .add_stream (tmp_path )
578617
579618@pytest .mark .skipif (platform .system () == "Windows" , reason = "flaky on windows runner" )
580619async def test_live_async_iteration (
@@ -730,6 +769,7 @@ def test_live_sync_iteration(
730769 assert isinstance (records [2 ], databento_dbn .MBOMsg )
731770 assert isinstance (records [3 ], databento_dbn .MBOMsg )
732771
772+
733773async def test_live_callback (
734774 live_client : client .Live ,
735775) -> None :
@@ -800,6 +840,44 @@ async def test_live_stream_to_dbn(
800840 assert output .read_bytes () == expected_data .read ()
801841
802842
843+ @pytest .mark .parametrize (
844+ "schema" ,
845+ (pytest .param (schema , id = str (schema )) for schema in Schema .variants ()),
846+ )
847+ async def test_live_stream_to_dbn_from_path (
848+ tmp_path : pathlib .Path ,
849+ test_data_path : Callable [[Schema ], pathlib .Path ],
850+ live_client : client .Live ,
851+ schema : Schema ,
852+ ) -> None :
853+ """
854+ Test that DBN data streamed by the MockLiveServer is properly re-
855+ constructed client side when specifying a file as a path.
856+ """
857+ output = tmp_path / "output.dbn"
858+
859+ live_client .subscribe (
860+ dataset = Dataset .GLBX_MDP3 ,
861+ schema = schema ,
862+ stype_in = SType .RAW_SYMBOL ,
863+ symbols = "TEST" ,
864+ )
865+ live_client .add_stream (output )
866+
867+ live_client .start ()
868+
869+ await live_client .wait_for_close ()
870+
871+ expected_data = BytesIO (
872+ zstandard .ZstdDecompressor ()
873+ .stream_reader (test_data_path (schema ).open ("rb" ))
874+ .read (),
875+ )
876+ expected_data .seek (0 ) # rewind
877+
878+ assert output .read_bytes () == expected_data .read ()
879+
880+
803881@pytest .mark .parametrize (
804882 "schema" ,
805883 (pytest .param (schema , id = str (schema )) for schema in Schema .variants ()),
0 commit comments