Skip to content

Commit 409b5b2

Browse files
committed
Upgrade anyio to v3
1 parent 6dce4d9 commit 409b5b2

File tree

6 files changed

+48
-50
lines changed

6 files changed

+48
-50
lines changed

jupyter_server/services/contents/filecheckpoints.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
)
1515
from .fileio import AsyncFileManagerMixin, FileManagerMixin
1616

17-
from anyio import run_sync_in_worker_thread
17+
from anyio.to_thread import run_sync
1818
from jupyter_core.utils import ensure_dir_exists
1919
from traitlets import Unicode
2020

@@ -156,7 +156,7 @@ async def restore_checkpoint(self, contents_mgr, checkpoint_id, path):
156156

157157
async def checkpoint_model(self, checkpoint_id, os_path):
158158
"""construct the info dict for a given checkpoint"""
159-
stats = await run_sync_in_worker_thread(os.stat, os_path)
159+
stats = await run_sync(os.stat, os_path)
160160
last_modified = tz.utcfromtimestamp(stats.st_mtime)
161161
info = dict(
162162
id=checkpoint_id,
@@ -176,7 +176,7 @@ async def rename_checkpoint(self, checkpoint_id, old_path, new_path):
176176
new_cp_path,
177177
)
178178
with self.perm_to_403():
179-
await run_sync_in_worker_thread(shutil.move, old_cp_path, new_cp_path)
179+
await run_sync(shutil.move, old_cp_path, new_cp_path)
180180

181181
async def delete_checkpoint(self, checkpoint_id, path):
182182
"""delete a file's checkpoint"""
@@ -187,7 +187,7 @@ async def delete_checkpoint(self, checkpoint_id, path):
187187

188188
self.log.debug("unlinking %s", cp_path)
189189
with self.perm_to_403():
190-
await run_sync_in_worker_thread(os.unlink, cp_path)
190+
await run_sync(os.unlink, cp_path)
191191

192192
async def list_checkpoints(self, path):
193193
"""list the checkpoints for a given file

jupyter_server/services/contents/fileio.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import os
1313
import shutil
1414

15-
from anyio import run_sync_in_worker_thread
15+
from anyio.to_thread import run_sync
1616
from tornado.web import HTTPError
1717

1818
from jupyter_server.utils import (
@@ -36,7 +36,7 @@ def replace_file(src, dst):
3636
async def async_replace_file(src, dst):
3737
""" replace dst with src asynchronously
3838
"""
39-
await run_sync_in_worker_thread(os.replace, src, dst)
39+
await run_sync(os.replace, src, dst)
4040

4141
def copy2_safe(src, dst, log=None):
4242
"""copy src to dst
@@ -55,9 +55,9 @@ async def async_copy2_safe(src, dst, log=None):
5555
5656
like shutil.copy2, but log errors in copystat instead of raising
5757
"""
58-
await run_sync_in_worker_thread(shutil.copyfile, src, dst)
58+
await run_sync(shutil.copyfile, src, dst)
5959
try:
60-
await run_sync_in_worker_thread(shutil.copystat, src, dst)
60+
await run_sync(shutil.copystat, src, dst)
6161
except OSError:
6262
if log:
6363
log.debug("copystat on %s failed", dst, exc_info=True)
@@ -355,7 +355,7 @@ async def _read_notebook(self, os_path, as_version=4):
355355
"""Read a notebook from an os path."""
356356
with self.open(os_path, 'r', encoding='utf-8') as f:
357357
try:
358-
return await run_sync_in_worker_thread(partial(nbformat.read, as_version=as_version), f)
358+
return await run_sync(partial(nbformat.read, as_version=as_version), f)
359359
except Exception as e:
360360
e_orig = e
361361

@@ -379,7 +379,7 @@ async def _read_notebook(self, os_path, as_version=4):
379379
async def _save_notebook(self, os_path, nb):
380380
"""Save a notebook to an os_path."""
381381
with self.atomic_writing(os_path, encoding='utf-8') as f:
382-
await run_sync_in_worker_thread(partial(nbformat.write, version=nbformat.NO_CONVERT), nb, f)
382+
await run_sync(partial(nbformat.write, version=nbformat.NO_CONVERT), nb, f)
383383

384384
async def _read_file(self, os_path, format):
385385
"""Read a non-notebook file.
@@ -394,7 +394,7 @@ async def _read_file(self, os_path, format):
394394
raise HTTPError(400, "Cannot read non-file %s" % os_path)
395395

396396
with self.open(os_path, 'rb') as f:
397-
bcontent = await run_sync_in_worker_thread(f.read)
397+
bcontent = await run_sync(f.read)
398398

399399
if format is None or format == 'text':
400400
# Try to interpret as unicode if format is unknown or if unicode
@@ -429,4 +429,4 @@ async def _save_file(self, os_path, content, format):
429429
) from e
430430

431431
with self.atomic_writing(os_path, text=False) as f:
432-
await run_sync_in_worker_thread(f.write, bcontent)
432+
await run_sync(f.write, bcontent)

jupyter_server/services/contents/filemanager.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import mimetypes
1313
import nbformat
1414

15-
from anyio import run_sync_in_worker_thread
15+
from anyio.to_thread import run_sync
1616
from send2trash import send2trash
1717
from tornado import web
1818

@@ -578,7 +578,7 @@ async def _dir_model(self, path, content=True):
578578
if content:
579579
model['content'] = contents = []
580580
os_dir = self._get_os_path(path)
581-
dir_contents = await run_sync_in_worker_thread(os.listdir, os_dir)
581+
dir_contents = await run_sync(os.listdir, os_dir)
582582
for name in dir_contents:
583583
try:
584584
os_path = os.path.join(os_dir, name)
@@ -588,7 +588,7 @@ async def _dir_model(self, path, content=True):
588588
continue
589589

590590
try:
591-
st = await run_sync_in_worker_thread(os.lstat, os_path)
591+
st = await run_sync(os.lstat, os_path)
592592
except OSError as e:
593593
# skip over broken symlinks in listing
594594
if e.errno == errno.ENOENT:
@@ -721,7 +721,7 @@ async def _save_directory(self, os_path, model, path=''):
721721
raise web.HTTPError(400, u'Cannot create hidden directory %r' % os_path)
722722
if not os.path.exists(os_path):
723723
with self.perm_to_403():
724-
await run_sync_in_worker_thread(os.mkdir, os_path)
724+
await run_sync(os.mkdir, os_path)
725725
elif not os.path.isdir(os_path):
726726
raise web.HTTPError(400, u'Not a directory: %s' % (os_path))
727727
else:
@@ -791,16 +791,16 @@ async def _check_trash(os_path):
791791
# It's a bit more nuanced than this, but until we can better
792792
# distinguish errors from send2trash, assume that we can only trash
793793
# files on the same partition as the home directory.
794-
file_dev = (await run_sync_in_worker_thread(os.stat, os_path)).st_dev
795-
home_dev = (await run_sync_in_worker_thread(os.stat, os.path.expanduser('~'))).st_dev
794+
file_dev = (await run_sync(os.stat, os_path)).st_dev
795+
home_dev = (await run_sync(os.stat, os.path.expanduser('~'))).st_dev
796796
return file_dev == home_dev
797797

798798
async def is_non_empty_dir(os_path):
799799
if os.path.isdir(os_path):
800800
# A directory containing only leftover checkpoints is
801801
# considered empty.
802802
cp_dir = getattr(self.checkpoints, 'checkpoint_dir', None)
803-
dir_contents = set(await run_sync_in_worker_thread(os.listdir, os_path))
803+
dir_contents = set(await run_sync(os.listdir, os_path))
804804
if dir_contents - {cp_dir}:
805805
return True
806806

@@ -828,11 +828,11 @@ async def is_non_empty_dir(os_path):
828828
raise web.HTTPError(400, u'Directory %s not empty' % os_path)
829829
self.log.debug("Removing directory %s", os_path)
830830
with self.perm_to_403():
831-
await run_sync_in_worker_thread(shutil.rmtree, os_path)
831+
await run_sync(shutil.rmtree, os_path)
832832
else:
833833
self.log.debug("Unlinking file %s", os_path)
834834
with self.perm_to_403():
835-
await run_sync_in_worker_thread(rm, os_path)
835+
await run_sync(rm, os_path)
836836

837837
async def rename_file(self, old_path, new_path):
838838
"""Rename a file."""
@@ -851,7 +851,7 @@ async def rename_file(self, old_path, new_path):
851851
# Move the file
852852
try:
853853
with self.perm_to_403():
854-
await run_sync_in_worker_thread(shutil.move, old_os_path, new_os_path)
854+
await run_sync(shutil.move, old_os_path, new_os_path)
855855
except web.HTTPError:
856856
raise
857857
except Exception as e:

jupyter_server/services/contents/largefilemanager.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from anyio import run_sync_in_worker_thread
1+
from anyio.to_thread import run_sync
22
from tornado import web
33
import base64
44
import os, io
@@ -135,6 +135,6 @@ async def _save_large_file(self, os_path, content, format):
135135
if os.path.islink(os_path):
136136
os_path = os.path.join(os.path.dirname(os_path), os.readlink(os_path))
137137
with io.open(os_path, 'ab') as f:
138-
await run_sync_in_worker_thread(f.write, bcontent)
138+
await run_sync(f.write, bcontent)
139139

140140

jupyter_server/tests/services/contents/test_manager.py

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def jp_contents_manager(request, tmp_path):
2323

2424

2525
@pytest.fixture(params=[FileContentsManager, AsyncFileContentsManager])
26-
def file_contents_manager_class(request, tmp_path):
26+
def jp_file_contents_manager_class(request, tmp_path):
2727
return request.param
2828

2929
# -------------- Functions ----------------------------
@@ -100,46 +100,45 @@ async def check_populated_dir_files(jp_contents_manager, api_path):
100100
# ----------------- Tests ----------------------------------
101101

102102

103-
def test_root_dir(file_contents_manager_class, tmp_path):
104-
fm = file_contents_manager_class(root_dir=str(tmp_path))
103+
def test_root_dir(jp_file_contents_manager_class, tmp_path):
104+
fm = jp_file_contents_manager_class(root_dir=str(tmp_path))
105105
assert fm.root_dir == str(tmp_path)
106106

107107

108-
def test_missing_root_dir(file_contents_manager_class, tmp_path):
108+
def test_missing_root_dir(jp_file_contents_manager_class, tmp_path):
109109
root = tmp_path / 'notebook' / 'dir' / 'is' / 'missing'
110110
with pytest.raises(TraitError):
111-
file_contents_manager_class(root_dir=str(root))
111+
jp_file_contents_manager_class(root_dir=str(root))
112112

113113

114-
def test_invalid_root_dir(file_contents_manager_class, tmp_path):
114+
def test_invalid_root_dir(jp_file_contents_manager_class, tmp_path):
115115
temp_file = tmp_path / 'file.txt'
116116
temp_file.write_text('')
117117
with pytest.raises(TraitError):
118-
file_contents_manager_class(root_dir=str(temp_file))
118+
jp_file_contents_manager_class(root_dir=str(temp_file))
119119

120-
121-
def test_get_os_path(file_contents_manager_class, tmp_path):
122-
fm = file_contents_manager_class(root_dir=str(tmp_path))
120+
def test_get_os_path(jp_file_contents_manager_class, tmp_path):
121+
fm = jp_file_contents_manager_class(root_dir=str(tmp_path))
123122
path = fm._get_os_path('/path/to/notebook/test.ipynb')
124123
rel_path_list = '/path/to/notebook/test.ipynb'.split('/')
125124
fs_path = os.path.join(fm.root_dir, *rel_path_list)
126125
assert path == fs_path
127126

128-
fm = file_contents_manager_class(root_dir=str(tmp_path))
127+
fm = jp_file_contents_manager_class(root_dir=str(tmp_path))
129128
path = fm._get_os_path('test.ipynb')
130129
fs_path = os.path.join(fm.root_dir, 'test.ipynb')
131130
assert path == fs_path
132131

133-
fm = file_contents_manager_class(root_dir=str(tmp_path))
132+
fm = jp_file_contents_manager_class(root_dir=str(tmp_path))
134133
path = fm._get_os_path('////test.ipynb')
135134
fs_path = os.path.join(fm.root_dir, 'test.ipynb')
136135
assert path == fs_path
137136

138137

139-
def test_checkpoint_subdir(file_contents_manager_class, tmp_path):
138+
def test_checkpoint_subdir(jp_file_contents_manager_class, tmp_path):
140139
subd = 'sub ∂ir'
141140
cp_name = 'test-cp.ipynb'
142-
fm = file_contents_manager_class(root_dir=str(tmp_path))
141+
fm = jp_file_contents_manager_class(root_dir=str(tmp_path))
143142
tmp_path.joinpath(subd).mkdir()
144143
cpm = fm.checkpoints
145144
cp_dir = cpm.checkpoint_path('cp', 'test.ipynb')
@@ -148,10 +147,10 @@ def test_checkpoint_subdir(file_contents_manager_class, tmp_path):
148147
assert cp_dir == os.path.join(str(tmp_path), cpm.checkpoint_dir, cp_name)
149148

150149

151-
async def test_bad_symlink(file_contents_manager_class, tmp_path):
150+
async def test_bad_symlink(jp_file_contents_manager_class, tmp_path):
152151
td = str(tmp_path)
153152

154-
cm = file_contents_manager_class(root_dir=td)
153+
cm = jp_file_contents_manager_class(root_dir=td)
155154
path = 'test bad symlink'
156155
_make_dir(cm, path)
157156

@@ -173,10 +172,10 @@ async def test_bad_symlink(file_contents_manager_class, tmp_path):
173172
sys.platform.startswith('win'),
174173
reason="Windows doesn't detect symlink loops"
175174
)
176-
async def test_recursive_symlink(file_contents_manager_class, tmp_path):
175+
async def test_recursive_symlink(jp_file_contents_manager_class, tmp_path):
177176
td = str(tmp_path)
178177

179-
cm = file_contents_manager_class(root_dir=td)
178+
cm = jp_file_contents_manager_class(root_dir=td)
180179
path = 'test recursive symlink'
181180
_make_dir(cm, path)
182181

@@ -195,9 +194,9 @@ async def test_recursive_symlink(file_contents_manager_class, tmp_path):
195194
assert 'recursive' not in contents
196195

197196

198-
async def test_good_symlink(file_contents_manager_class, tmp_path):
197+
async def test_good_symlink(jp_file_contents_manager_class, tmp_path):
199198
td = str(tmp_path)
200-
cm = file_contents_manager_class(root_dir=td)
199+
cm = jp_file_contents_manager_class(root_dir=td)
201200
parent = 'test good symlink'
202201
name = 'good symlink'
203202
path = '{0}/{1}'.format(parent, name)
@@ -216,13 +215,13 @@ async def test_good_symlink(file_contents_manager_class, tmp_path):
216215
sys.platform.startswith('win'),
217216
reason="Can't test permissions on Windows"
218217
)
219-
async def test_403(file_contents_manager_class, tmp_path):
218+
async def test_403(jp_file_contents_manager_class, tmp_path):
220219
if hasattr(os, 'getuid'):
221220
if os.getuid() == 0:
222221
raise pytest.skip("Can't test permissions as root")
223222

224223
td = str(tmp_path)
225-
cm = file_contents_manager_class(root_dir=td)
224+
cm = jp_file_contents_manager_class(root_dir=td)
226225
model = await ensure_async(cm.new_untitled(type='file'))
227226
os_path = cm._get_os_path(model['path'])
228227

@@ -233,10 +232,9 @@ async def test_403(file_contents_manager_class, tmp_path):
233232
except HTTPError as e:
234233
assert e.status_code == 403
235234

236-
237-
async def test_escape_root(file_contents_manager_class, tmp_path):
235+
async def test_escape_root(jp_file_contents_manager_class, tmp_path):
238236
td = str(tmp_path)
239-
cm = file_contents_manager_class(root_dir=td)
237+
cm = jp_file_contents_manager_class(root_dir=td)
240238
# make foo, bar next to root
241239
with open(os.path.join(cm.root_dir, '..', 'foo'), 'w') as f:
242240
f.write('foo')

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ install_requires =
4242
terminado>=0.8.3
4343
prometheus_client
4444
pywin32>=1.0 ; sys_platform == 'win32'
45-
anyio>=2.0.2,<3
45+
anyio>=3.0.1,<4
4646

4747
[options.extras_require]
4848
test = coverage; pytest; pytest-cov; pytest-mock; requests; pytest-tornasync; pytest-console-scripts; ipykernel

0 commit comments

Comments
 (0)