2
2
import sys
3
3
import time
4
4
import pytest
5
- import functools
6
5
from traitlets import TraitError
7
6
from tornado .web import HTTPError
8
7
from itertools import combinations
9
8
10
-
11
9
from nbformat import v4 as nbformat
12
10
13
11
from jupyter_server .services .contents .filemanager import AsyncFileContentsManager , FileContentsManager
14
12
from jupyter_server .utils import ensure_async
15
13
from ...utils import expected_http_error
16
14
15
+
17
16
@pytest .fixture (params = [(FileContentsManager , True ),
18
17
(FileContentsManager , False ),
19
18
(AsyncFileContentsManager , True ),
@@ -29,6 +28,7 @@ def file_contents_manager_class(request, tmp_path):
29
28
30
29
# -------------- Functions ----------------------------
31
30
31
+
32
32
def _make_dir (jp_contents_manager , api_path ):
33
33
"""
34
34
Make a directory.
@@ -99,6 +99,7 @@ async def check_populated_dir_files(jp_contents_manager, api_path):
99
99
100
100
# ----------------- Tests ----------------------------------
101
101
102
+
102
103
def test_root_dir (file_contents_manager_class , tmp_path ):
103
104
fm = file_contents_manager_class (root_dir = str (tmp_path ))
104
105
assert fm .root_dir == str (tmp_path )
@@ -116,6 +117,7 @@ def test_invalid_root_dir(file_contents_manager_class, tmp_path):
116
117
with pytest .raises (TraitError ):
117
118
file_contents_manager_class (root_dir = str (temp_file ))
118
119
120
+
119
121
def test_get_os_path (file_contents_manager_class , tmp_path ):
120
122
fm = file_contents_manager_class (root_dir = str (tmp_path ))
121
123
path = fm ._get_os_path ('/path/to/notebook/test.ipynb' )
@@ -146,10 +148,6 @@ def test_checkpoint_subdir(file_contents_manager_class, tmp_path):
146
148
assert cp_dir == os .path .join (str (tmp_path ), cpm .checkpoint_dir , cp_name )
147
149
148
150
149
- @pytest .mark .skipif (
150
- sys .platform == 'win32' and sys .version_info [0 ] < 3 ,
151
- reason = "System platform is Windows, version < 3"
152
- )
153
151
async def test_bad_symlink (file_contents_manager_class , tmp_path ):
154
152
td = str (tmp_path )
155
153
@@ -172,9 +170,31 @@ async def test_bad_symlink(file_contents_manager_class, tmp_path):
172
170
173
171
174
172
@pytest .mark .skipif (
175
- sys .platform == 'win32' and sys . version_info [ 0 ] < 3 ,
176
- reason = "System platform is Windows, version < 3 "
173
+ sys .platform . startswith ( 'win' ) ,
174
+ reason = "Windows doesn't detect symlink loops "
177
175
)
176
+ async def test_recursive_symlink (file_contents_manager_class , tmp_path ):
177
+ td = str (tmp_path )
178
+
179
+ cm = file_contents_manager_class (root_dir = td )
180
+ path = 'test recursive symlink'
181
+ _make_dir (cm , path )
182
+
183
+ file_model = await ensure_async (cm .new_untitled (path = path , ext = '.txt' ))
184
+
185
+ # create recursive symlink
186
+ symlink (cm , '%s/%s' % (path , "recursive" ), '%s/%s' % (path , "recursive" ))
187
+ model = await ensure_async (cm .get (path ))
188
+
189
+ contents = {
190
+ content ['name' ]: content for content in model ['content' ]
191
+ }
192
+ assert 'untitled.txt' in contents
193
+ assert contents ['untitled.txt' ] == file_model
194
+ # recursive symlinks should not be shown in the contents manager
195
+ assert 'recursive' not in contents
196
+
197
+
178
198
async def test_good_symlink (file_contents_manager_class , tmp_path ):
179
199
td = str (tmp_path )
180
200
cm = file_contents_manager_class (root_dir = td )
@@ -213,6 +233,7 @@ async def test_403(file_contents_manager_class, tmp_path):
213
233
except HTTPError as e :
214
234
assert e .status_code == 403
215
235
236
+
216
237
async def test_escape_root (file_contents_manager_class , tmp_path ):
217
238
td = str (tmp_path )
218
239
cm = file_contents_manager_class (root_dir = td )
0 commit comments