@@ -40,7 +40,9 @@ def __init__(
40
40
self ._log = log or getLogger (__name__ )
41
41
self ._subscriptions : dict [str , Callable [[], Coroutine [Any , Any , None ]]] = {}
42
42
43
- self ._watcher = asyncio .create_task (self ._watch_file ()) if self ._poll_interval else None
43
+ self ._watcher = (
44
+ asyncio .create_task (self ._watch_file ()) if self ._poll_interval else None
45
+ )
44
46
self .last_modified = None
45
47
46
48
@property
@@ -79,7 +81,9 @@ async def clean(self) -> None:
79
81
except asyncio .CancelledError :
80
82
self ._log .info (f"file watcher for '{ self .file_id } ' is cancelled now" )
81
83
82
- def observe (self , id : str , callback : Callable [[], Coroutine [Any , Any , None ]]) -> None :
84
+ def observe (
85
+ self , id : str , callback : Callable [[], Coroutine [Any , Any , None ]]
86
+ ) -> None :
83
87
"""
84
88
Subscribe to the file to get notified about out-of-band file changes.
85
89
@@ -112,12 +116,14 @@ async def load_content(self, format: str, file_type: str) -> dict[str, Any]:
112
116
"""
113
117
async with self ._lock :
114
118
model = await ensure_async (
115
- self ._contents_manager .get (self .path , format = format , type = file_type , content = True )
119
+ self ._contents_manager .get (
120
+ self .path , format = format , type = file_type , content = True
121
+ )
116
122
)
117
123
self .last_modified = model ["last_modified" ]
118
124
return model
119
125
120
- async def maybe_save_content (self , model : dict [str , Any ]) -> None :
126
+ async def maybe_save_content (self , model : dict [str , Any ]) -> dict [ str , Any ] | None :
121
127
"""
122
128
Save the content of the file.
123
129
@@ -149,20 +155,34 @@ async def maybe_save_content(self, model: dict[str, Any]) -> None:
149
155
# otherwise it could corrupt the file
150
156
done_saving = asyncio .Event ()
151
157
task = asyncio .create_task (self ._save_content (model , done_saving ))
158
+ saved_model = None
152
159
try :
153
- await asyncio .shield (task )
160
+ saved_model = await asyncio .shield (task )
154
161
except asyncio .CancelledError :
155
162
pass
156
163
await done_saving .wait ()
164
+ return saved_model
157
165
else :
158
166
# file changed on disk, raise an error
159
167
self .last_modified = m ["last_modified" ]
160
168
raise OutOfBandChanges
161
169
162
- async def _save_content (self , model : dict [str , Any ], done_saving : asyncio .Event ) -> None :
170
+ async def _save_content (
171
+ self , model : dict [str , Any ], done_saving : asyncio .Event
172
+ ) -> dict [str , Any ]:
163
173
try :
164
174
m = await ensure_async (self ._contents_manager .save (model , self .path ))
165
175
self .last_modified = m ["last_modified" ]
176
+ # TODO, get rid of the extra `get` here once upstream issue:
177
+ # https://github.com/jupyter-server/jupyter_server/issues/1453 is resolved
178
+ model_with_hash = await ensure_async (
179
+ self ._contents_manager .get (
180
+ self .path ,
181
+ content = False ,
182
+ require_hash = True , # TODO require version supporting hash
183
+ )
184
+ )
185
+ return {** m , "hash" : model_with_hash ["hash" ]}
166
186
finally :
167
187
done_saving .set ()
168
188
@@ -181,7 +201,9 @@ async def _watch_file(self) -> None:
181
201
try :
182
202
await self .maybe_notify ()
183
203
except Exception as e :
184
- self ._log .error (f"Error watching file: { self .path } \n { e !r} " , exc_info = e )
204
+ self ._log .error (
205
+ f"Error watching file: { self .path } \n { e !r} " , exc_info = e
206
+ )
185
207
except asyncio .CancelledError :
186
208
break
187
209
@@ -192,9 +214,14 @@ async def maybe_notify(self) -> None:
192
214
do_notify = False
193
215
async with self ._lock :
194
216
# Get model metadata; format and type are not need
195
- model = await ensure_async (self ._contents_manager .get (self .path , content = False ))
217
+ model = await ensure_async (
218
+ self ._contents_manager .get (self .path , content = False )
219
+ )
196
220
197
- if self .last_modified is not None and self .last_modified < model ["last_modified" ]:
221
+ if (
222
+ self .last_modified is not None
223
+ and self .last_modified < model ["last_modified" ]
224
+ ):
198
225
do_notify = True
199
226
200
227
self .last_modified = model ["last_modified" ]
0 commit comments