33from pathlib import Path , PurePath
44import shutil
55
6+ from pycrdt import Map
67
78from traitlets .config import LoggingConfigurable
89from traitlets import (
1415 TraitError ,
1516 Type ,
1617 Unicode ,
18+ Int ,
1719 default ,
1820 validate ,
1921)
2224
2325class OutputsManager (LoggingConfigurable ):
2426
25- outputs_path = Instance (PurePath , help = "The local runtime dir" )
2627 _last_output_index = Dict (default_value = {})
28+ _stream_count = Dict (default_value = {})
29+
30+ outputs_path = Instance (PurePath , help = "The local runtime dir" )
31+ stream_limit = Int (default_value = 10 , config = True , allow_none = True )
2732
2833 @default ("outputs_path" )
2934 def _default_outputs_path (self ):
@@ -64,11 +69,10 @@ def get_stream(self, file_id, cell_id):
6469 def write (self , file_id , cell_id , output ):
6570 """Write a new output for file_id and cell_id."""
6671 self .log .info (f"OutputsManager.write: { file_id } { cell_id } { output } " )
67- if output ["output_type" ] == "stream" :
68- url = self .write_stream (file_id , cell_id , output )
69- else :
70- url = self .write_output (file_id , cell_id , output )
71- return url
72+ result = self .write_output (file_id , cell_id , output )
73+ if output ["output_type" ] == "stream" and self .stream_limit is not None :
74+ result = self .write_stream (file_id , cell_id , output )
75+ return result
7276
7377 def write_output (self , file_id , cell_id , output ):
7478 self ._ensure_path (file_id , cell_id )
@@ -80,17 +84,46 @@ def write_output(self, file_id, cell_id, output):
8084 with open (path , "w" , encoding = "utf-8" ) as f :
8185 f .write (data )
8286 url = f"/api/outputs/{ file_id } /{ cell_id } /{ index } .output"
83- return url
87+ return Map ({})
8488
85- def write_stream (self , file_id , cell_id , output ):
89+ def write_stream (self , file_id , cell_id , output ) -> Map :
90+ # How many stream outputs have been written for this cell previously
91+ count = self ._stream_count .get (cell_id , 0 )
92+
93+ # Go ahead and write the incoming stream
8694 self ._ensure_path (file_id , cell_id )
8795 path = self ._build_path (file_id , cell_id ) / "stream"
8896 text = output ["text" ]
8997 mode = 'a' if os .path .isfile (path ) else 'w'
9098 with open (path , "a" , encoding = "utf-8" ) as f :
9199 f .write (text )
92100 url = f"/api/outputs/{ file_id } /{ cell_id } /stream"
93- return url
101+
102+ # Increment the count
103+ count = count + 1
104+ self ._stream_count [cell_id ] = count
105+
106+ # Now create the placeholder output
107+ if count < self .stream_limit :
108+ # Return the original if we haven't reached the limit
109+ placeholder = Map (output )
110+ elif count == self .stream_limit :
111+ # Return a link to the full stream output
112+ placeholder = Map ({
113+ "output_type" : "display_data" ,
114+ "data" : {
115+ 'text/html' : f'<a href="{ url } ">Click this link to see the full stream output</a>'
116+ }
117+ })
118+ elif count > self .stream_limit :
119+ placeholder = None
120+ return placeholder
121+
122+
123+
124+
125+
126+
94127
95128 def clear (self , file_id , cell_id = None ):
96129 path = self ._build_path (file_id , cell_id )
0 commit comments